aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2018-09-25 01:02:42 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-09-25 01:02:42 +0000
commit5055f108385c076346b3b279788dc0129549b11f (patch)
tree91456c9f0ec368308f734e6d649b046d57a19114 /gcc
parent414925ab0cb8d0aea39cb3383b18f72f3ce887a0 (diff)
parent44eb8fa73bb53afa17e4d72b1c073d0e08a76866 (diff)
downloadgcc-5055f108385c076346b3b279788dc0129549b11f.zip
gcc-5055f108385c076346b3b279788dc0129549b11f.tar.gz
gcc-5055f108385c076346b3b279788dc0129549b11f.tar.bz2
Merge from trunk revision 264547.
From-SVN: r264554
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5614
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in12
-rw-r--r--gcc/ada/ChangeLog324
-rw-r--r--gcc/ada/Make-generated.in10
-rw-r--r--gcc/ada/Makefile.rtl17
-rw-r--r--gcc/ada/checks.adb39
-rw-r--r--gcc/ada/checks.ads18
-rw-r--r--gcc/ada/contracts.adb45
-rw-r--r--gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst33
-rw-r--r--gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst31
-rw-r--r--gcc/ada/einfo.adb52
-rw-r--r--gcc/ada/einfo.ads50
-rw-r--r--gcc/ada/exp_aggr.adb34
-rw-r--r--gcc/ada/exp_attr.adb40
-rw-r--r--gcc/ada/exp_cg.adb9
-rw-r--r--gcc/ada/exp_ch6.adb5
-rw-r--r--gcc/ada/exp_ch7.adb7
-rw-r--r--gcc/ada/exp_ch9.adb62
-rw-r--r--gcc/ada/exp_unst.adb13
-rw-r--r--gcc/ada/exp_unst.ads2
-rw-r--r--gcc/ada/exp_util.adb18
-rw-r--r--gcc/ada/fe.h2
-rw-r--r--gcc/ada/freeze.adb209
-rw-r--r--gcc/ada/freeze.ads11
-rw-r--r--gcc/ada/gcc-interface/Make-lang.in1
-rw-r--r--gcc/ada/gcc-interface/Makefile.in13
-rw-r--r--gcc/ada/gcc-interface/decl.c2
-rw-r--r--gcc/ada/gcc-interface/gigi.h4
-rw-r--r--gcc/ada/gcc-interface/trans.c30
-rw-r--r--gcc/ada/gcc-interface/utils.c2
-rw-r--r--gcc/ada/gnat_ugn.texi70
-rw-r--r--gcc/ada/gnatlink.adb6
-rw-r--r--gcc/ada/impunit.adb9
-rw-r--r--gcc/ada/itypes.adb2
-rw-r--r--gcc/ada/itypes.ads2
-rw-r--r--gcc/ada/layout.adb10
-rw-r--r--gcc/ada/lib-writ.adb22
-rw-r--r--gcc/ada/lib-xref-spark_specific.adb13
-rw-r--r--gcc/ada/lib-xref.ads5
-rw-r--r--gcc/ada/libgnarl/a-intnam__dragonfly.ads2
-rw-r--r--gcc/ada/libgnarl/s-osinte__dragonfly.adb2
-rw-r--r--gcc/ada/libgnarl/s-osinte__dragonfly.ads2
-rw-r--r--gcc/ada/libgnarl/s-osinte__gnu.adb2
-rw-r--r--gcc/ada/libgnarl/s-osinte__gnu.ads2
-rw-r--r--gcc/ada/libgnarl/s-osinte__hpux-dce.adb2
-rw-r--r--gcc/ada/libgnarl/s-osinte__hpux-dce.ads2
-rw-r--r--gcc/ada/libgnarl/s-taprop__hpux-dce.adb2
-rw-r--r--gcc/ada/libgnarl/s-taspri__hpux-dce.ads2
-rw-r--r--gcc/ada/libgnat/g-dynhta.adb834
-rw-r--r--gcc/ada/libgnat/g-dynhta.ads310
-rw-r--r--gcc/ada/libgnat/g-lists.adb635
-rw-r--r--gcc/ada/libgnat/g-lists.ads245
-rw-r--r--gcc/ada/libgnat/s-dfmkio.ads38
-rw-r--r--gcc/ada/libgnat/s-dfmopr.ads35
-rw-r--r--gcc/ada/libgnat/s-dgmgop.ads174
-rw-r--r--gcc/ada/libgnat/s-diflmk.ads34
-rw-r--r--gcc/ada/libgnat/s-digemk.ads396
-rw-r--r--gcc/ada/libgnat/s-dilomk.ads34
-rw-r--r--gcc/ada/libgnat/s-dimmks.ads363
-rw-r--r--gcc/ada/libgnat/s-dlmkio.ads38
-rw-r--r--gcc/ada/libgnat/s-dlmopr.ads35
-rw-r--r--gcc/ada/libgnat/s-dmotpr.ads141
-rw-r--r--gcc/ada/sa_messages.adb539
-rw-r--r--gcc/ada/sa_messages.ads267
-rw-r--r--gcc/ada/sem_attr.adb9
-rw-r--r--gcc/ada/sem_ch10.adb3
-rw-r--r--gcc/ada/sem_ch13.adb78
-rw-r--r--gcc/ada/sem_ch3.adb8
-rw-r--r--gcc/ada/sem_ch6.adb250
-rw-r--r--gcc/ada/sem_res.adb35
-rw-r--r--gcc/ada/sem_spark.adb3902
-rw-r--r--gcc/ada/sem_util.adb10
-rw-r--r--gcc/ada/sem_util.ads2
-rwxr-xr-xgcc/ada/set_targ.adb3
-rw-r--r--gcc/ada/sinfo.ads2
-rw-r--r--gcc/ada/sprint.adb9
-rw-r--r--gcc/ada/terminals.c9
-rw-r--r--gcc/ada/vxlink-bind.adb390
-rw-r--r--gcc/ada/vxlink-bind.ads87
-rw-r--r--gcc/ada/vxlink-link.adb194
-rw-r--r--gcc/ada/vxlink-link.ads63
-rw-r--r--gcc/ada/vxlink-main.adb81
-rw-r--r--gcc/ada/vxlink.adb288
-rw-r--r--gcc/ada/vxlink.ads68
-rw-r--r--gcc/alias.c11
-rw-r--r--gcc/asan.c2
-rw-r--r--gcc/asan.h2
-rw-r--r--gcc/attribs.c5
-rw-r--r--gcc/auto-profile.c21
-rw-r--r--gcc/bb-reorder.c20
-rw-r--r--gcc/builtin-attrs.def2
-rw-r--r--gcc/builtin-types.def8
-rw-r--r--gcc/builtins.c370
-rw-r--r--gcc/builtins.def23
-rw-r--r--gcc/builtins.h7
-rw-r--r--gcc/c-family/ChangeLog243
-rw-r--r--gcc/c-family/c-ada-spec.c53
-rw-r--r--gcc/c-family/c-attribs.c1
-rw-r--r--gcc/c-family/c-common.c327
-rw-r--r--gcc/c-family/c-common.h5
-rw-r--r--gcc/c-family/c-cppbuiltin.c67
-rw-r--r--gcc/c-family/c-format.c364
-rw-r--r--gcc/c-family/c-format.h2
-rw-r--r--gcc/c-family/c-indentation.c193
-rw-r--r--gcc/c-family/c-lex.c2
-rw-r--r--gcc/c-family/c-opts.c1
-rw-r--r--gcc/c-family/c-ppoutput.c23
-rw-r--r--gcc/c-family/c-spellcheck.cc10
-rw-r--r--gcc/c-family/c-warn.c7
-rw-r--r--gcc/c-family/c.opt108
-rw-r--r--gcc/c-family/known-headers.cc2
-rw-r--r--gcc/c/ChangeLog131
-rw-r--r--gcc/c/c-decl.c90
-rw-r--r--gcc/c/c-objc-common.c131
-rw-r--r--gcc/c/c-parser.c182
-rw-r--r--gcc/c/c-tree.h2
-rw-r--r--gcc/c/c-typeck.c303
-rw-r--r--gcc/c/gimple-parser.c11
-rw-r--r--gcc/calls.c28
-rw-r--r--gcc/cfg.c2
-rw-r--r--gcc/cfg.h60
-rw-r--r--gcc/cfganal.c152
-rw-r--r--gcc/cfganal.h2
-rw-r--r--gcc/cfgexpand.c40
-rw-r--r--gcc/cfgloop.c9
-rw-r--r--gcc/cgraph.c10
-rw-r--r--gcc/cgraph.h8
-rw-r--r--gcc/cgraphclones.c5
-rw-r--r--gcc/cgraphunit.c102
-rw-r--r--gcc/combine-stack-adj.c1
-rw-r--r--gcc/combine.c63
-rw-r--r--gcc/common.opt23
-rw-r--r--gcc/common/common-target.def11
-rw-r--r--gcc/common/common-targhooks.c9
-rw-r--r--gcc/common/common-targhooks.h1
-rw-r--r--gcc/common/config/csky/csky-common.c42
-rw-r--r--gcc/common/config/i386/i386-common.c272
-rw-r--r--gcc/common/config/nds32/nds32-common.c12
-rw-r--r--gcc/common/config/nvptx/nvptx-common.c9
-rw-r--r--gcc/common/config/s390/s390-common.c2
-rw-r--r--gcc/config.gcc141
-rw-r--r--gcc/config.in6
-rw-r--r--gcc/config/aarch64/aarch64-builtins.c4
-rw-r--r--gcc/config/aarch64/aarch64-cores.def6
-rw-r--r--gcc/config/aarch64/aarch64-cost-tables.h104
-rw-r--r--gcc/config/aarch64/aarch64-passes.def2
-rw-r--r--gcc/config/aarch64/aarch64-protos.h55
-rw-r--r--gcc/config/aarch64/aarch64-simd-builtins.def2
-rw-r--r--gcc/config/aarch64/aarch64-simd.md84
-rw-r--r--gcc/config/aarch64/aarch64-speculation.cc494
-rw-r--r--gcc/config/aarch64/aarch64-tune.md2
-rw-r--r--gcc/config/aarch64/aarch64-tuning-flags.def2
-rw-r--r--gcc/config/aarch64/aarch64.c754
-rw-r--r--gcc/config/aarch64/aarch64.h9
-rw-r--r--gcc/config/aarch64/aarch64.md438
-rw-r--r--gcc/config/aarch64/aarch64.opt24
-rw-r--r--gcc/config/aarch64/arm_neon.h31
-rw-r--r--gcc/config/aarch64/atomics.md33
-rw-r--r--gcc/config/aarch64/constraints.md12
-rw-r--r--gcc/config/aarch64/falkor-tag-collision-avoidance.c881
-rw-r--r--gcc/config/aarch64/falkor.md8
-rw-r--r--gcc/config/aarch64/iterators.md7
-rw-r--r--gcc/config/aarch64/predicates.md30
-rw-r--r--gcc/config/aarch64/t-aarch6420
-rw-r--r--gcc/config/alpha/alpha.h2
-rw-r--r--gcc/config/arc/arc.c3
-rw-r--r--gcc/config/arc/arc.h4
-rw-r--r--gcc/config/arc/linux.h2
-rw-r--r--gcc/config/arm/arm-builtins.c5
-rw-r--r--gcc/config/arm/arm-protos.h2
-rw-r--r--gcc/config/arm/arm.c21
-rw-r--r--gcc/config/arm/arm.md27
-rw-r--r--gcc/config/arm/neon.md49
-rw-r--r--gcc/config/arm/unspecs.md1
-rw-r--r--gcc/config/cris/cris.c3
-rw-r--r--gcc/config/csky/constraints.md174
-rw-r--r--gcc/config/csky/csky-elf.h81
-rw-r--r--gcc/config/csky/csky-linux-elf.h132
-rw-r--r--gcc/config/csky/csky-protos.h71
-rw-r--r--gcc/config/csky/csky.c6795
-rw-r--r--gcc/config/csky/csky.h1054
-rw-r--r--gcc/config/csky/csky.md3798
-rw-r--r--gcc/config/csky/csky.opt173
-rw-r--r--gcc/config/csky/csky_cores.def199
-rw-r--r--gcc/config/csky/csky_genopt.sh97
-rw-r--r--gcc/config/csky/csky_insn_dsp.md95
-rw-r--r--gcc/config/csky/csky_insn_fpu.md567
-rw-r--r--gcc/config/csky/csky_isa.def59
-rw-r--r--gcc/config/csky/csky_isa.h47
-rw-r--r--gcc/config/csky/csky_opts.h63
-rw-r--r--gcc/config/csky/csky_pipeline_ck801.md54
-rw-r--r--gcc/config/csky/csky_pipeline_ck802.md77
-rw-r--r--gcc/config/csky/csky_pipeline_ck803.md64
-rw-r--r--gcc/config/csky/csky_pipeline_ck810.md34
-rw-r--r--gcc/config/csky/csky_tables.opt230
-rw-r--r--gcc/config/csky/predicates.md298
-rw-r--r--gcc/config/csky/print-sysroot-suffix.sh147
-rw-r--r--gcc/config/csky/t-csky (renamed from gcc/config/rs6000/t-aix43)30
-rw-r--r--gcc/config/csky/t-csky-elf107
-rw-r--r--gcc/config/csky/t-csky-linux52
-rw-r--r--gcc/config/csky/t-sysroot-suffix28
-rw-r--r--gcc/config/darwin.c32
-rw-r--r--gcc/config/darwin.h53
-rw-r--r--gcc/config/darwin10.h10
-rw-r--r--gcc/config/darwin12.h8
-rw-r--r--gcc/config/fr30/fr30.c3
-rw-r--r--gcc/config/frv/frv.c3
-rw-r--r--gcc/config/h8300/h8300.c3
-rw-r--r--gcc/config/i386/constraints.md7
-rw-r--r--gcc/config/i386/djgpp.c17
-rw-r--r--gcc/config/i386/djgpp.h11
-rw-r--r--gcc/config/i386/emmintrin.h2
-rw-r--r--gcc/config/i386/i386-modes.def3
-rw-r--r--gcc/config/i386/i386.c1160
-rw-r--r--gcc/config/i386/i386.h250
-rw-r--r--gcc/config/i386/i386.md1580
-rw-r--r--gcc/config/i386/i386.opt8
-rw-r--r--gcc/config/i386/movdirintrin.h2
-rw-r--r--gcc/config/i386/predicates.md3
-rw-r--r--gcc/config/i386/sse.md36
-rw-r--r--gcc/config/i386/x86-tune-costs.h104
-rw-r--r--gcc/config/i386/xmmintrin.h5
-rw-r--r--gcc/config/ia64/ia64.opt4
-rw-r--r--gcc/config/iq2000/iq2000.c3
-rw-r--r--gcc/config/m32r/m32r.c3
-rw-r--r--gcc/config/m68k/m68k-protos.h1
-rw-r--r--gcc/config/m68k/m68k.c71
-rw-r--r--gcc/config/m68k/m68k.h3
-rw-r--r--gcc/config/mcore/mcore.c3
-rw-r--r--gcc/config/mips/frame-header-opt.c2
-rw-r--r--gcc/config/mmix/mmix.c51
-rw-r--r--gcc/config/mn10300/mn10300.c3
-rw-r--r--gcc/config/msp430/msp430.c3
-rw-r--r--gcc/config/nds32/nds32-isr.c470
-rw-r--r--gcc/config/nds32/nds32-predicates.c16
-rw-r--r--gcc/config/nds32/nds32-protos.h9
-rw-r--r--gcc/config/nds32/nds32.c79
-rw-r--r--gcc/config/nds32/nds32.h14
-rw-r--r--gcc/config/nds32/nds32.md11
-rw-r--r--gcc/config/nds32/nds32.opt8
-rw-r--r--gcc/config/nds32/nds32_init.inc43
-rw-r--r--gcc/config/nds32/nds32_isr.h526
-rw-r--r--gcc/config/nios2/nios2.c3
-rw-r--r--gcc/config/nvptx/nvptx-opts.h30
-rw-r--r--gcc/config/nvptx/nvptx.c8
-rw-r--r--gcc/config/nvptx/nvptx.h8
-rw-r--r--gcc/config/nvptx/nvptx.md3
-rw-r--r--gcc/config/nvptx/nvptx.opt14
-rw-r--r--gcc/config/pa/pa.c37
-rw-r--r--gcc/config/pa/pa.md139
-rw-r--r--gcc/config/pdp11/pdp11.c3
-rw-r--r--gcc/config/powerpcspe/powerpcspe-c.c9
-rw-r--r--gcc/config/powerpcspe/powerpcspe.c3
-rw-r--r--gcc/config/riscv/pic.md113
-rw-r--r--gcc/config/riscv/riscv.c8
-rw-r--r--gcc/config/riscv/riscv.md16
-rw-r--r--gcc/config/rs6000/aix43.h167
-rw-r--r--gcc/config/rs6000/aix51.h169
-rw-r--r--gcc/config/rs6000/aix52.h179
-rw-r--r--gcc/config/rs6000/aix53.h180
-rw-r--r--gcc/config/rs6000/altivec.md85
-rw-r--r--gcc/config/rs6000/darwin.h13
-rw-r--r--gcc/config/rs6000/darwin.md45
-rw-r--r--gcc/config/rs6000/dfp.md6
-rw-r--r--gcc/config/rs6000/emmintrin.h3
-rw-r--r--gcc/config/rs6000/htm.md36
-rw-r--r--gcc/config/rs6000/rs6000-c.c10
-rw-r--r--gcc/config/rs6000/rs6000-opts.h3
-rw-r--r--gcc/config/rs6000/rs6000-string.c735
-rw-r--r--gcc/config/rs6000/rs6000.c300
-rw-r--r--gcc/config/rs6000/rs6000.md256
-rw-r--r--gcc/config/rs6000/rs6000.opt16
-rw-r--r--gcc/config/rs6000/sync.md6
-rw-r--r--gcc/config/rs6000/vsx.md23
-rw-r--r--gcc/config/rs6000/xmmintrin.h3
-rw-r--r--gcc/config/rx/rx.c3
-rw-r--r--gcc/config/s390/2064.md22
-rw-r--r--gcc/config/s390/constraints.md16
-rw-r--r--gcc/config/s390/driver-native.c2
-rw-r--r--gcc/config/s390/linux.h1
-rw-r--r--gcc/config/s390/predicates.md12
-rw-r--r--gcc/config/s390/s390-c.c11
-rw-r--r--gcc/config/s390/s390-opts.h10
-rw-r--r--gcc/config/s390/s390-passes.def20
-rw-r--r--gcc/config/s390/s390-protos.h6
-rw-r--r--gcc/config/s390/s390.c1950
-rw-r--r--gcc/config/s390/s390.h118
-rw-r--r--gcc/config/s390/s390.md553
-rw-r--r--gcc/config/s390/s390.opt9
-rw-r--r--gcc/config/s390/t-s3901
-rw-r--r--gcc/config/s390/tpf.h11
-rw-r--r--gcc/config/spu/spu-c.c2
-rw-r--r--gcc/config/spu/spu.c3
-rw-r--r--gcc/config/stormy16/stormy16.c3
-rw-r--r--gcc/config/v850/v850.c3
-rw-r--r--gcc/config/visium/visium.c27
-rw-r--r--gcc/config/vxworks-dummy.h10
-rw-r--r--gcc/config/vxworks.c9
-rw-r--r--gcc/config/vxworks.h63
-rw-r--r--gcc/config/xtensa/xtensa.c4
-rwxr-xr-xgcc/configure57
-rw-r--r--gcc/configure.ac16
-rw-r--r--gcc/coverage.c77
-rw-r--r--gcc/coverage.h4
-rw-r--r--gcc/cp/ChangeLog622
-rw-r--r--gcc/cp/call.c306
-rw-r--r--gcc/cp/class.c108
-rw-r--r--gcc/cp/constexpr.c230
-rw-r--r--gcc/cp/constraint.cc3
-rw-r--r--gcc/cp/cp-gimplify.c31
-rw-r--r--gcc/cp/cp-tree.def7
-rw-r--r--gcc/cp/cp-tree.h28
-rw-r--r--gcc/cp/cvt.c3
-rw-r--r--gcc/cp/cxx-pretty-print.c6
-rw-r--r--gcc/cp/decl.c325
-rw-r--r--gcc/cp/decl2.c3
-rw-r--r--gcc/cp/dump.c1
-rw-r--r--gcc/cp/error.c43
-rw-r--r--gcc/cp/except.c9
-rw-r--r--gcc/cp/friend.c4
-rw-r--r--gcc/cp/g++spec.c1
-rw-r--r--gcc/cp/init.c48
-rw-r--r--gcc/cp/lambda.c25
-rw-r--r--gcc/cp/lex.c1
-rw-r--r--gcc/cp/method.c4
-rw-r--r--gcc/cp/name-lookup.c87
-rw-r--r--gcc/cp/optimize.c2
-rw-r--r--gcc/cp/parser.c53
-rw-r--r--gcc/cp/pt.c58
-rw-r--r--gcc/cp/rtti.c2
-rw-r--r--gcc/cp/search.c10
-rw-r--r--gcc/cp/semantics.c22
-rw-r--r--gcc/cp/tree.c15
-rw-r--r--gcc/cp/typeck.c259
-rw-r--r--gcc/cp/typeck2.c92
-rw-r--r--gcc/cppbuiltin.c5
-rw-r--r--gcc/cse.c187
-rw-r--r--gcc/cselib.c42
-rw-r--r--gcc/cselib.h2
-rw-r--r--gcc/dce.c11
-rw-r--r--gcc/debug.h15
-rw-r--r--gcc/defaults.h4
-rw-r--r--gcc/df-problems.c2
-rw-r--r--gcc/df-scan.c6
-rw-r--r--gcc/diagnostic-core.h10
-rw-r--r--gcc/diagnostic-show-locus.c746
-rw-r--r--gcc/diagnostic.c116
-rw-r--r--gcc/diagnostic.h24
-rw-r--r--gcc/doc/cpp.texi4
-rw-r--r--gcc/doc/extend.texi176
-rw-r--r--gcc/doc/gcov-dump.texi6
-rw-r--r--gcc/doc/gcov.texi12
-rw-r--r--gcc/doc/generic.texi2
-rw-r--r--gcc/doc/install.texi4
-rw-r--r--gcc/doc/invoke.texi441
-rw-r--r--gcc/doc/md.texi176
-rw-r--r--gcc/doc/rtl.texi55
-rw-r--r--gcc/doc/service.texi2
-rw-r--r--gcc/doc/standards.texi2
-rw-r--r--gcc/doc/tm.texi146
-rw-r--r--gcc/doc/tm.texi.in79
-rw-r--r--gcc/dojump.c16
-rw-r--r--gcc/dse.c3
-rw-r--r--gcc/dump-context.h25
-rw-r--r--gcc/dumpfile.c1040
-rw-r--r--gcc/dumpfile.h62
-rw-r--r--gcc/dwarf2out.c218
-rw-r--r--gcc/emit-rtl.c25
-rw-r--r--gcc/emit-rtl.h3
-rw-r--r--gcc/except.c3
-rw-r--r--gcc/explow.c3
-rw-r--r--gcc/expmed.c123
-rw-r--r--gcc/expmed.h2
-rw-r--r--gcc/expr.c445
-rw-r--r--gcc/expr.h4
-rw-r--r--gcc/final.c77
-rw-r--r--gcc/fold-const.c110
-rw-r--r--gcc/fold-const.h3
-rw-r--r--gcc/fortran/ChangeLog397
-rw-r--r--gcc/fortran/cpp.c7
-rw-r--r--gcc/fortran/decl.c10
-rw-r--r--gcc/fortran/dump-parse-tree.c13
-rw-r--r--gcc/fortran/error.c2
-rw-r--r--gcc/fortran/expr.c14
-rw-r--r--gcc/fortran/frontend-passes.c710
-rw-r--r--gcc/fortran/gfortran.h8
-rw-r--r--gcc/fortran/gfortran.texi35
-rw-r--r--gcc/fortran/gfortranspec.c1
-rw-r--r--gcc/fortran/interface.c29
-rw-r--r--gcc/fortran/invoke.texi18
-rw-r--r--gcc/fortran/iresolve.c2
-rw-r--r--gcc/fortran/match.c23
-rw-r--r--gcc/fortran/module.c16
-rw-r--r--gcc/fortran/openmp.c2
-rw-r--r--gcc/fortran/options.c4
-rw-r--r--gcc/fortran/primary.c6
-rw-r--r--gcc/fortran/resolve.c68
-rw-r--r--gcc/fortran/simplify.c61
-rw-r--r--gcc/fortran/trans-array.c79
-rw-r--r--gcc/fortran/trans-decl.c26
-rw-r--r--gcc/fortran/trans-expr.c239
-rw-r--r--gcc/fortran/trans-intrinsic.c158
-rw-r--r--gcc/fortran/trans-io.c5
-rw-r--r--gcc/fortran/trans-stmt.c51
-rw-r--r--gcc/fortran/trans-stmt.h2
-rw-r--r--gcc/fortran/trans.c7
-rw-r--r--gcc/fortran/trans.h3
-rw-r--r--gcc/function-tests.c1
-rw-r--r--gcc/function.c1
-rw-r--r--gcc/gcc-ar.c16
-rw-r--r--gcc/gcc-rich-location.c14
-rw-r--r--gcc/gcc-rich-location.h71
-rw-r--r--gcc/gcc.c75
-rw-r--r--gcc/gcc.h1
-rw-r--r--gcc/gcov-dump.c81
-rw-r--r--gcc/gcov-io.c398
-rw-r--r--gcc/gcov-io.h71
-rw-r--r--gcc/gcov-tool.c1
-rw-r--r--gcc/gcov.c107
-rw-r--r--gcc/genattrtab.c132
-rw-r--r--gcc/genconfig.c1
-rw-r--r--gcc/genemit.c144
-rw-r--r--gcc/gengtype.c2
-rw-r--r--gcc/genmatch.c18
-rw-r--r--gcc/genmodes.c15
-rw-r--r--gcc/genopinit.c68
-rw-r--r--gcc/genpreds.c2
-rw-r--r--gcc/genrecog.c3
-rw-r--r--gcc/gimple-fold.c147
-rw-r--r--gcc/gimple-fold.h6
-rw-r--r--gcc/gimple-loop-jam.c30
-rw-r--r--gcc/gimple-low.c2
-rw-r--r--gcc/gimple-pretty-print.c20
-rw-r--r--gcc/gimple-ssa-evrp-analyze.c7
-rw-r--r--gcc/gimple-ssa-evrp.c2
-rw-r--r--gcc/gimple-ssa-isolate-paths.c26
-rw-r--r--gcc/gimple-ssa-sprintf.c254
-rw-r--r--gcc/gimple-ssa-store-merging.c92
-rw-r--r--gcc/gimple-ssa-warn-alloca.c98
-rw-r--r--gcc/gimple-ssa-warn-restrict.c21
-rw-r--r--gcc/gimple-ssa-warn-restrict.h2
-rw-r--r--gcc/gimple-streamer-in.c1
-rw-r--r--gcc/gimple-streamer-out.c1
-rw-r--r--gcc/gimple.c7
-rw-r--r--gcc/gimplify.c32
-rw-r--r--gcc/go/ChangeLog12
-rw-r--r--gcc/go/go-gcc.cc4
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/escape.cc25
-rw-r--r--gcc/go/gofrontend/expressions.cc161
-rw-r--r--gcc/go/gofrontend/expressions.h11
-rw-r--r--gcc/go/gofrontend/gogo.cc3
-rw-r--r--gcc/go/gofrontend/gogo.h3
-rw-r--r--gcc/go/gofrontend/lex.cc8
-rw-r--r--gcc/go/gofrontend/lex.h8
-rw-r--r--gcc/go/gofrontend/parse.cc15
-rw-r--r--gcc/go/gofrontend/runtime.def22
-rw-r--r--gcc/go/gofrontend/statements.cc251
-rw-r--r--gcc/go/gofrontend/statements.h64
-rw-r--r--gcc/go/gofrontend/types.cc54
-rw-r--r--gcc/go/gofrontend/types.h2
-rw-r--r--gcc/go/gofrontend/wb.cc239
-rw-r--r--gcc/go/gospec.c1
-rw-r--r--gcc/graphite.h2
-rw-r--r--gcc/haifa-sched.c15
-rw-r--r--gcc/hash-table.c14
-rw-r--r--gcc/hash-table.h12
-rw-r--r--gcc/hsa-brig.c2
-rw-r--r--gcc/hsa-dump.c2
-rw-r--r--gcc/hsa-gen.c26
-rw-r--r--gcc/hsa-regalloc.c4
-rw-r--r--gcc/internal-fn.c36
-rw-r--r--gcc/internal-fn.h2
-rw-r--r--gcc/ipa-cp.c5
-rw-r--r--gcc/ipa-devirt.c39
-rw-r--r--gcc/ipa-fnsummary.c9
-rw-r--r--gcc/ipa-icf.c6
-rw-r--r--gcc/ipa-icf.h6
-rw-r--r--gcc/ipa-inline.c6
-rw-r--r--gcc/ipa-param-manipulation.c2
-rw-r--r--gcc/ipa-profile.c26
-rw-r--r--gcc/ipa-split.c5
-rw-r--r--gcc/ipa-utils.h54
-rw-r--r--gcc/ipa-visibility.c2
-rw-r--r--gcc/ira-build.c5
-rw-r--r--gcc/ira-costs.c7
-rw-r--r--gcc/ira.c6
-rw-r--r--gcc/jit/ChangeLog2
-rw-r--r--gcc/jump.c1
-rw-r--r--gcc/langhooks.c2
-rw-r--r--gcc/lra-constraints.c2
-rw-r--r--gcc/lra-eliminations.c11
-rw-r--r--gcc/lra-int.h2
-rw-r--r--gcc/lra-lives.c34
-rw-r--r--gcc/lra-remat.c2
-rw-r--r--gcc/lra.c66
-rw-r--r--gcc/lto-cgraph.c138
-rw-r--r--gcc/lto-opts.c16
-rw-r--r--gcc/lto-streamer-in.c8
-rw-r--r--gcc/lto-streamer-out.c19
-rw-r--r--gcc/lto-wrapper.c95
-rw-r--r--gcc/lto/ChangeLog52
-rw-r--r--gcc/lto/lto-lang.c3
-rw-r--r--gcc/lto/lto-symtab.c8
-rw-r--r--gcc/lto/lto.c7
-rw-r--r--gcc/machmode.h4
-rw-r--r--gcc/match.pd91
-rw-r--r--gcc/memory-block.h5
-rw-r--r--gcc/mode-classes.def1
-rw-r--r--gcc/modulo-sched.c8
-rw-r--r--gcc/multiple_target.c1
-rw-r--r--gcc/objc/ChangeLog2
-rw-r--r--gcc/objcp/ChangeLog6
-rw-r--r--gcc/omp-low.c7
-rw-r--r--gcc/opt-functions.awk1
-rw-r--r--gcc/opt-suggestions.c30
-rw-r--r--gcc/opt-suggestions.h6
-rw-r--r--gcc/optabs.c3
-rw-r--r--gcc/optc-gen.awk18
-rw-r--r--gcc/opth-gen.awk1
-rw-r--r--gcc/optinfo-emit-json.cc2
-rw-r--r--gcc/optinfo.cc135
-rw-r--r--gcc/optinfo.h38
-rw-r--r--gcc/opts-common.c29
-rw-r--r--gcc/opts.c41
-rw-r--r--gcc/opts.h3
-rw-r--r--gcc/params.def75
-rw-r--r--gcc/passes.def6
-rw-r--r--gcc/postreload-gcse.c23
-rw-r--r--gcc/postreload.c25
-rw-r--r--gcc/predict.c388
-rw-r--r--gcc/predict.def12
-rw-r--r--gcc/pretty-print.c47
-rw-r--r--gcc/pretty-print.h17
-rw-r--r--gcc/print-rtl.c3
-rw-r--r--gcc/print-tree.c6
-rw-r--r--gcc/profile-count.c2
-rw-r--r--gcc/profile.c116
-rw-r--r--gcc/profile.h2
-rw-r--r--gcc/read-md.c5
-rw-r--r--gcc/read-md.h55
-rw-r--r--gcc/read-rtl.c233
-rw-r--r--gcc/recog.c9
-rw-r--r--gcc/recog.h2
-rw-r--r--gcc/reg-stack.c64
-rw-r--r--gcc/regcprop.c10
-rw-r--r--gcc/reginfo.c5
-rw-r--r--gcc/reload1.c16
-rw-r--r--gcc/reorg.c27
-rw-r--r--gcc/resource.c24
-rw-r--r--gcc/rtl.c15
-rw-r--r--gcc/rtl.def12
-rw-r--r--gcc/rtl.h36
-rw-r--r--gcc/rtlanal.c48
-rw-r--r--gcc/sanopt.c6
-rw-r--r--gcc/sched-deps.c15
-rw-r--r--gcc/sel-sched.c4
-rw-r--r--gcc/selftest-diagnostic.c1
-rw-r--r--gcc/simplify-rtx.c9
-rw-r--r--gcc/sort.cc18
-rw-r--r--gcc/spellcheck.c231
-rw-r--r--gcc/spellcheck.h19
-rw-r--r--gcc/sreal.c59
-rw-r--r--gcc/sreal.h61
-rw-r--r--gcc/stmt.c4
-rw-r--r--gcc/stor-layout.c41
-rw-r--r--gcc/substring-locations.c133
-rw-r--r--gcc/substring-locations.h66
-rw-r--r--gcc/symtab.c2
-rw-r--r--gcc/system.h10
-rw-r--r--gcc/target.def69
-rw-r--r--gcc/targhooks.c56
-rw-r--r--gcc/targhooks.h4
-rw-r--r--gcc/testsuite/ChangeLog2080
-rw-r--r--gcc/testsuite/c-c++-common/Wmisleading-indentation-pr70693.c12
-rw-r--r--gcc/testsuite/c-c++-common/array-init.c5
-rw-r--r--gcc/testsuite/c-c++-common/asan/pointer-subtract-3.c1
-rw-r--r--gcc/testsuite/c-c++-common/asan/pointer-subtract-4.c1
-rw-r--r--gcc/testsuite/c-c++-common/attr-nonstring-3.c2
-rw-r--r--gcc/testsuite/c-c++-common/attributes-1.c2
-rw-r--r--gcc/testsuite/c-c++-common/dump-ada-spec-14.c10
-rw-r--r--gcc/testsuite/c-c++-common/ident-0a.c6
-rw-r--r--gcc/testsuite/c-c++-common/ident-0b.c10
-rw-r--r--gcc/testsuite/c-c++-common/ident-1a.c8
-rw-r--r--gcc/testsuite/c-c++-common/ident-1b.c7
-rw-r--r--gcc/testsuite/c-c++-common/ident-2a.c6
-rw-r--r--gcc/testsuite/c-c++-common/ident-2b.c7
-rw-r--r--gcc/testsuite/c-c++-common/inc-from-1.c5
-rw-r--r--gcc/testsuite/c-c++-common/inc-from-1a.h1
-rw-r--r--gcc/testsuite/c-c++-common/inc-from-1b.h1
-rw-r--r--gcc/testsuite/c-c++-common/pr59521-1.c15
-rw-r--r--gcc/testsuite/c-c++-common/pr59521-2.c15
-rw-r--r--gcc/testsuite/c-c++-common/spec-barrier-1.c38
-rw-r--r--gcc/testsuite/c-c++-common/spec-barrier-2.c17
-rw-r--r--gcc/testsuite/c-c++-common/torture/pr87248.c36
-rw-r--r--gcc/testsuite/g++.dg/Walloca1.C6
-rw-r--r--gcc/testsuite/g++.dg/Wno-frame-address.C2
-rw-r--r--gcc/testsuite/g++.dg/abi/pr87137.C40
-rw-r--r--gcc/testsuite/g++.dg/asan/pr85774.C51
-rw-r--r--gcc/testsuite/g++.dg/concepts/pr67595.C2
-rw-r--r--gcc/testsuite/g++.dg/concepts/pr84980.C6
-rw-r--r--gcc/testsuite/g++.dg/concepts/pr85065.C6
-rw-r--r--gcc/testsuite/g++.dg/concepts/pr85265.C6
-rw-r--r--gcc/testsuite/g++.dg/conversion/Wwrite-strings.C24
-rw-r--r--gcc/testsuite/g++.dg/conversion/op4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wnarrowing10.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wnarrowing11.C30
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wnarrowing12.C32
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wnarrowing6.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wnarrowing7.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wnarrowing8.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wnarrowing9.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move1.C132
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move2.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move3.C59
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move4.C46
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move5.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wredundant-move1.C106
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wredundant-move2.C57
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wredundant-move3.C43
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wredundant-move4.C86
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto52.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-47969.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-data2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ex2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-targ.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-virtual5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/deleted2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/desig5.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/explicit4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inline-ns10.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const-this.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-in-class-neg.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-in-class.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-non-local.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-shadow3.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this10.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this17.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this18.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this8.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/move-return2.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept30.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr85070.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr87155.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/ref-qual19.C117
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/ref-qual20.C70
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-cast5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/scoped_enum2.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/auto-fn52.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/auto-fn53.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/auto-fn54.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-82218.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-86767.C119
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-array6.C26
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-return4.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/func_constexpr2.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic18.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic19.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr64382.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr77739.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/Wpessimizing-move1.C18
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp46.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp47.C32
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C60
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/lambda-this1.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/lambda-this2.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/aggr1.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/aggr2.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-virtual1.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-virtual2.C49
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-virtual3.C52
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-virtual4.C57
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-virtual5.C60
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-virtual6.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-virtual7.C87
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-virtual8.C50
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-virtual9.C83
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated1.C66
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/lambda-this1.C51
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/lambda-this2.C51
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/lambda-this3.C55
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/range-for11.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/range-for12.C33
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/range-for13.C33
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/range-for14.C24
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/range-for15.C43
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/range-for16.C36
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/range-for17.C30
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/range-for18.C16
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/pr85302.C1
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/aka3.C25
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/auto1.C4
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/missing-typename.C12
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C97
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C20
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/pr86993.C13
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/virtual-constexpr.C7
-rw-r--r--gcc/testsuite/g++.dg/expr/pmf-1.C2
-rw-r--r--gcc/testsuite/g++.dg/expr/pmf-3.C1
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-returns-nonnull.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/is_aggregate.C11
-rw-r--r--gcc/testsuite/g++.dg/ext/is_constructible2.C12
-rw-r--r--gcc/testsuite/g++.dg/ext/stmtexpr15.C2
-rw-r--r--gcc/testsuite/g++.dg/gcov/loop.C6
-rw-r--r--gcc/testsuite/g++.dg/gomp/pr47963.C2
-rw-r--r--gcc/testsuite/g++.dg/guality/pr86687.C28
-rw-r--r--gcc/testsuite/g++.dg/init/goto3.C6
-rw-r--r--gcc/testsuite/g++.dg/init/new37.C2
-rw-r--r--gcc/testsuite/g++.dg/init/new43.C66
-rw-r--r--gcc/testsuite/g++.dg/init/string2.C104
-rw-r--r--gcc/testsuite/g++.dg/init/string3.C35
-rw-r--r--gcc/testsuite/g++.dg/init/string4.C60
-rw-r--r--gcc/testsuite/g++.dg/ipa/pr64059.C2
-rw-r--r--gcc/testsuite/g++.dg/lookup/name-clash12.C9
-rw-r--r--gcc/testsuite/g++.dg/lto/20081109-1_0.C2
-rw-r--r--gcc/testsuite/g++.dg/lto/20090302_0.C2
-rw-r--r--gcc/testsuite/g++.dg/lto/pr45621_0.C2
-rw-r--r--gcc/testsuite/g++.dg/lto/pr60567_0.C2
-rw-r--r--gcc/testsuite/g++.dg/lto/pr62026.C2
-rw-r--r--gcc/testsuite/g++.dg/opt/eh1.C2
-rw-r--r--gcc/testsuite/g++.dg/opt/mpx.C4
-rw-r--r--gcc/testsuite/g++.dg/opt/pr86738.C12
-rw-r--r--gcc/testsuite/g++.dg/other/fold1.C2
-rw-r--r--gcc/testsuite/g++.dg/other/friend10.C9
-rw-r--r--gcc/testsuite/g++.dg/other/friend11.C8
-rw-r--r--gcc/testsuite/g++.dg/other/friend12.C11
-rw-r--r--gcc/testsuite/g++.dg/other/friend13.C6
-rw-r--r--gcc/testsuite/g++.dg/other/friend14.C14
-rw-r--r--gcc/testsuite/g++.dg/other/friend15.C14
-rw-r--r--gcc/testsuite/g++.dg/other/friend8.C6
-rw-r--r--gcc/testsuite/g++.dg/other/friend9.C9
-rw-r--r--gcc/testsuite/g++.dg/other/switch4.C6
-rw-r--r--gcc/testsuite/g++.dg/other/vrp1.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/array-size2.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/defarg4.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/defarg8.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/error61.C4
-rw-r--r--gcc/testsuite/g++.dg/plugin/plugin.exp1
-rw-r--r--gcc/testsuite/g++.dg/plugin/show-template-tree-color-labels.C38
-rw-r--r--gcc/testsuite/g++.dg/pr61941.C12
-rw-r--r--gcc/testsuite/g++.dg/pr83239.C2
-rw-r--r--gcc/testsuite/g++.dg/pr85523.C91
-rw-r--r--gcc/testsuite/g++.dg/pr86593.C11
-rw-r--r--gcc/testsuite/g++.dg/pr86988.C16
-rw-r--r--gcc/testsuite/g++.dg/pr87185.C4
-rw-r--r--gcc/testsuite/g++.dg/predict-1.C15
-rw-r--r--gcc/testsuite/g++.dg/recip_sqrt_mult_1.C49
-rw-r--r--gcc/testsuite/g++.dg/recip_sqrt_mult_2.C49
-rw-r--r--gcc/testsuite/g++.dg/template/char1.C3
-rw-r--r--gcc/testsuite/g++.dg/template/crash84.C2
-rw-r--r--gcc/testsuite/g++.dg/template/dependent-name3.C2
-rw-r--r--gcc/testsuite/g++.dg/template/inline1.C2
-rw-r--r--gcc/testsuite/g++.dg/template/pr86706.C16
-rw-r--r--gcc/testsuite/g++.dg/template/ptrmem20.C2
-rw-r--r--gcc/testsuite/g++.dg/template/ptrmem8.C4
-rw-r--r--gcc/testsuite/g++.dg/torture/20180705-1.C30
-rw-r--r--gcc/testsuite/g++.dg/torture/pr44295.C1
-rw-r--r--gcc/testsuite/g++.dg/torture/pr86763.C37
-rw-r--r--gcc/testsuite/g++.dg/torture/pr86816.C42
-rw-r--r--gcc/testsuite/g++.dg/torture/pr87014.C37
-rw-r--r--gcc/testsuite/g++.dg/torture/pr87124.C12
-rw-r--r--gcc/testsuite/g++.dg/torture/type-generic-1.C1
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/lifetime-dse1.C2
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr61034.C2
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr81408.C2
-rw-r--r--gcc/testsuite/g++.dg/ubsan/vptr-13.C19
-rw-r--r--gcc/testsuite/g++.dg/warn/Wclass-conversion1.C19
-rw-r--r--gcc/testsuite/g++.dg/warn/Wclass-conversion2.C20
-rw-r--r--gcc/testsuite/g++.dg/warn/Wreturn-local-addr-5.C8
-rw-r--r--gcc/testsuite/g++.dg/warn/Wunreachable-code-1.C22
-rw-r--r--gcc/testsuite/g++.dg/warn/Wunreachable-code-2.C23
-rw-r--r--gcc/testsuite/g++.dg/warn/conversion-function-1.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/pr31246-2.C9
-rw-r--r--gcc/testsuite/g++.dg/warn/pr31246.C9
-rw-r--r--gcc/testsuite/g++.dg/warn/pr86881.C20
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900215_01.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900330_02.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/conversion11.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/conversion5.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/arg11.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/arm9.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/p784.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.robertl/eb131.C4
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20000804-1.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20180915-1.c27
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/dse.c19
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr85704.c10
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr87110.c13
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20101011-1.c4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20180921-1.c161
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/ieee/mul-subnormal-single-1.x5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/memchr-1.c153
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr86714.c26
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr86844.c24
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr87053.c17
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr87290.c63
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/widechar-3.c26
-rw-r--r--gcc/testsuite/gcc.c-torture/unsorted/dump-noaddr.x4
-rw-r--r--gcc/testsuite/gcc.dg/20020312-2.c5
-rw-r--r--gcc/testsuite/gcc.dg/Warray-bounds-33.c36
-rw-r--r--gcc/testsuite/gcc.dg/Warray-bounds-34.c18
-rw-r--r--gcc/testsuite/gcc.dg/Warray-bounds-35.c15
-rw-r--r--gcc/testsuite/gcc.dg/Wno-frame-address.c2
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-6.c2
-rw-r--r--gcc/testsuite/gcc.dg/addr_equal-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/asan/pr81923.c5
-rw-r--r--gcc/testsuite/gcc.dg/asan/pr86962.c13
-rw-r--r--gcc/testsuite/gcc.dg/bad-binary-ops.c26
-rw-r--r--gcc/testsuite/gcc.dg/c11-true_min-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/completion-4.c6
-rw-r--r--gcc/testsuite/gcc.dg/cpp/macsyntx.c8
-rw-r--r--gcc/testsuite/gcc.dg/cpp/macsyntx2.c8
-rw-r--r--gcc/testsuite/gcc.dg/cpp/pr66415-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/debug/dwarf2/pr80263.c2
-rw-r--r--gcc/testsuite/gcc.dg/dfp/warn-abs-2.c28
-rw-r--r--gcc/testsuite/gcc.dg/diagnostic-token-ranges.c3
-rw-r--r--gcc/testsuite/gcc.dg/driver-specs.c4
-rw-r--r--gcc/testsuite/gcc.dg/empty.h0
-rw-r--r--gcc/testsuite/gcc.dg/fixits-pr84852-1.c5
-rw-r--r--gcc/testsuite/gcc.dg/fixits-pr84852-2.c5
-rw-r--r--gcc/testsuite/gcc.dg/format/diagnostic-ranges.c55
-rw-r--r--gcc/testsuite/gcc.dg/format/gcc_diag-1.c19
-rw-r--r--gcc/testsuite/gcc.dg/format/gcc_diag-10.c45
-rw-r--r--gcc/testsuite/gcc.dg/format/pr72858.c108
-rw-r--r--gcc/testsuite/gcc.dg/format/pr78498.c2
-rw-r--r--gcc/testsuite/gcc.dg/graphite/pr82451.c2
-rw-r--r--gcc/testsuite/gcc.dg/guality/const-volatile.c2
-rw-r--r--gcc/testsuite/gcc.dg/guality/zero-length-array.c21
-rw-r--r--gcc/testsuite/gcc.dg/init-string-3.c58
-rw-r--r--gcc/testsuite/gcc.dg/ipa/pr85734.c2
-rw-r--r--gcc/testsuite/gcc.dg/ipa/propmalloc-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/ipa/propmalloc-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/ipa/propmalloc-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr45736_0.c2
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr52634_0.c2
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr83719_0.c1
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr85248_0.c9
-rw-r--r--gcc/testsuite/gcc.dg/lvalue-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/memcmp-1.c9
-rw-r--r--gcc/testsuite/gcc.dg/missing-header-fixit-3.c21
-rw-r--r--gcc/testsuite/gcc.dg/missing-header-fixit-4.c23
-rw-r--r--gcc/testsuite/gcc.dg/nested-func-11.c34
-rw-r--r--gcc/testsuite/gcc.dg/param-type-mismatch.c56
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-group-test-1.c26
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw-line-numbers.c120
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c73
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color-line-numbers.c26
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color.c16
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-no-labels.c27
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic_group_plugin.c234
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c2
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c72
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugin.exp7
-rw-r--r--gcc/testsuite/gcc.dg/plugin/poly-int-07_plugin.c2
-rw-r--r--gcc/testsuite/gcc.dg/pointer-range-check-1.c37
-rw-r--r--gcc/testsuite/gcc.dg/pointer-range-check-2.c31
-rw-r--r--gcc/testsuite/gcc.dg/pr33092.c6
-rw-r--r--gcc/testsuite/gcc.dg/pr41837.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr41841.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr42250.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr43084.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr43317.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr51879-18.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr69554-1.c29
-rw-r--r--gcc/testsuite/gcc.dg/pr69627.c4
-rw-r--r--gcc/testsuite/gcc.dg/pr79342.c18
-rw-r--r--gcc/testsuite/gcc.dg/pr83666.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr85195.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr85467.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr85799.c19
-rw-r--r--gcc/testsuite/gcc.dg/pr86064.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr86835.c29
-rw-r--r--gcc/testsuite/gcc.dg/pr87009.c23
-rw-r--r--gcc/testsuite/gcc.dg/pr87024.c14
-rw-r--r--gcc/testsuite/gcc.dg/pr87052.c41
-rw-r--r--gcc/testsuite/gcc.dg/pr87054.c29
-rw-r--r--gcc/testsuite/gcc.dg/pr87074.c25
-rw-r--r--gcc/testsuite/gcc.dg/pr87092.c10
-rw-r--r--gcc/testsuite/gcc.dg/pr87099.c21
-rw-r--r--gcc/testsuite/gcc.dg/pr87112.c31
-rw-r--r--gcc/testsuite/gcc.dg/pr87117-1.c21
-rw-r--r--gcc/testsuite/gcc.dg/pr87117-2.c15
-rw-r--r--gcc/testsuite/gcc.dg/pr87259.c14
-rw-r--r--gcc/testsuite/gcc.dg/pr87309.c4
-rw-r--r--gcc/testsuite/gcc.dg/predict-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/predict-13.c4
-rw-r--r--gcc/testsuite/gcc.dg/predict-16.c36
-rw-r--r--gcc/testsuite/gcc.dg/predict-17.c13
-rw-r--r--gcc/testsuite/gcc.dg/predict-18.c31
-rw-r--r--gcc/testsuite/gcc.dg/predict-19.c13
-rw-r--r--gcc/testsuite/gcc.dg/predict-20.c23
-rw-r--r--gcc/testsuite/gcc.dg/predict-21.c13
-rw-r--r--gcc/testsuite/gcc.dg/predict-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/predict-4.c2
-rw-r--r--gcc/testsuite/gcc.dg/predict-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/predict-6.c2
-rw-r--r--gcc/testsuite/gcc.dg/predict-9.c4
-rw-r--r--gcc/testsuite/gcc.dg/recip_sqrt_mult_1.c15
-rw-r--r--gcc/testsuite/gcc.dg/recip_sqrt_mult_2.c11
-rw-r--r--gcc/testsuite/gcc.dg/recip_sqrt_mult_3.c11
-rw-r--r--gcc/testsuite/gcc.dg/recip_sqrt_mult_4.c21
-rw-r--r--gcc/testsuite/gcc.dg/recip_sqrt_mult_5.c20
-rw-r--r--gcc/testsuite/gcc.dg/redecl-10.c4
-rw-r--r--gcc/testsuite/gcc.dg/sibcall-10.c2
-rw-r--r--gcc/testsuite/gcc.dg/sibcall-9.c2
-rw-r--r--gcc/testsuite/gcc.dg/spec-barrier-3.c13
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-identifiers-4.c10
-rw-r--r--gcc/testsuite/gcc.dg/stack-usage-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_22.c16
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_23.c16
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-55.c230
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-56.c50
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-57.c49
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-58.c93
-rw-r--r--gcc/testsuite/gcc.dg/torture/float32-tg-3.c1
-rw-r--r--gcc/testsuite/gcc.dg/torture/float32x-tg-3.c1
-rw-r--r--gcc/testsuite/gcc.dg/torture/float64-tg-3.c1
-rw-r--r--gcc/testsuite/gcc.dg/torture/float64x-tg-3.c1
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr36066.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr52969.c16
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr81790.c1
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr86505.c32
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr86945.c18
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87132.c18
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87147.c22
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87168.c30
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87169.c41
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87176.c28
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87177-2.c28
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87177.c61
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87197.c35
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87200.c23
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87211.c21
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87263.c24
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87266-1.c32
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87266-2.c32
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87266-3.c32
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87266-4.c38
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87280.c61
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87301.c34
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87328.c25
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87342.c44
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87349-1.c33
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87349-2.c33
-rw-r--r--gcc/testsuite/gcc.dg/torture/ssa-fre-1.c16
-rw-r--r--gcc/testsuite/gcc.dg/torture/ssa-fre-2.c21
-rw-r--r--gcc/testsuite/gcc.dg/torture/ssa-fre-3.c23
-rw-r--r--gcc/testsuite/gcc.dg/torture/ssa-fre-4.c17
-rw-r--r--gcc/testsuite/gcc.dg/torture/type-generic-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/pr59521-3.c34
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/section-attr-1.c5
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/section-attr-2.c5
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/section-attr-3.c5
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/stringop-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/stringop-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/val-prof-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/val-prof-10.c31
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/val-prof-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/val-prof-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/val-prof-4.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/val-prof-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/val-prof-7.c28
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-10.c119
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-11.c65
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c7
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-18.c5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-20.c22
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/dump-3.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/evrp11.c23
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ifc-8.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ifc-cd.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr45122.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr78154.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr83648.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr84512.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr87126.c25
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr87205-2.c18
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr87205.c21
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr87287.c34
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-14.c11
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-46.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-67.c16
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-68.c28
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/switch-2.c25
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/switch-3.c20
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp105.c37
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp113.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp120.c5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp92.c2
-rw-r--r--gcc/testsuite/gcc.dg/uninit-suppress_2.c2
-rw-r--r--gcc/testsuite/gcc.dg/union-duplicate-field.c21
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-over-widen-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-over-widen-2.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pow-1.c28
-rw-r--r--gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-1.c26
-rw-r--r--gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-2.c23
-rw-r--r--gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-3.c25
-rw-r--r--gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-4.c23
-rw-r--r--gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-5.c24
-rw-r--r--gcc/testsuite/gcc.dg/vect/no-section-anchors-vect-69.c5
-rw-r--r--gcc/testsuite/gcc.dg/vect/no-vfa-vect-depend-2.c5
-rw-r--r--gcc/testsuite/gcc.dg/vect/no-vfa-vect-depend-3.c5
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr65947-13.c3
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr80631-2.c3
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr86749.c26
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr86858.c13
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr86871.c15
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr86927.c15
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr87288-1.c49
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr87288-2.c64
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr87288-3.c64
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-23.c6
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-37.c9
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-perm-10.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-perm-9.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-avg-15.c52
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-avg-16.c52
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8-gap4-big-array.c5
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8-gap4.c5
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect.exp7
-rw-r--r--gcc/testsuite/gcc.dg/warn-abs-1.c68
-rw-r--r--gcc/testsuite/gcc.dg/warn-stpcpy-no-nul.c324
-rw-r--r--gcc/testsuite/gcc.dg/warn-strcpy-no-nul.c324
-rw-r--r--gcc/testsuite/gcc.dg/warn-strlen-no-nul.c304
-rw-r--r--gcc/testsuite/gcc.dg/wmain.c10
-rw-r--r--gcc/testsuite/gcc.target/aarch64/atomic-store.c75
-rw-r--r--gcc/testsuite/gcc.target/aarch64/combine_bfi_1.c4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/combine_bfxil.c117
-rw-r--r--gcc/testsuite/gcc.target/aarch64/combine_bfxil_2.c16
-rw-r--r--gcc/testsuite/gcc.target/aarch64/extract_zero_extend.c81
-rw-r--r--gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_1.c6
-rw-r--r--gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_2.c4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_3.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/frecpe_1.c18
-rw-r--r--gcc/testsuite/gcc.target/aarch64/frecpe_2.c18
-rw-r--r--gcc/testsuite/gcc.target/aarch64/imm_choice_comparison.c54
-rw-r--r--gcc/testsuite/gcc.target/aarch64/large_struct_copy.c23
-rw-r--r--gcc/testsuite/gcc.target/aarch64/large_struct_copy_2.c26
-rw-r--r--gcc/testsuite/gcc.target/aarch64/ldp_stp_13.c18
-rw-r--r--gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c8
-rw-r--r--gcc/testsuite/gcc.target/aarch64/simd/vect_su_add_sub.c26
-rw-r--r--gcc/testsuite/gcc.target/aarch64/spellcheck_1.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/spellcheck_4.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/strcmpopt_6.c (renamed from gcc/testsuite/gcc.dg/strcmpopt_6.c)6
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/bswap_1.c13
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/bswap_2.c13
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/bswap_3.c13
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/reduc_8.c20
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/single_1.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/single_2.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/single_3.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/single_4.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/slp_perm_1.c22
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/slp_perm_2.c22
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/slp_perm_3.c22
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/slp_perm_4.c22
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/slp_perm_5.c32
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/slp_perm_6.c22
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/slp_perm_7.c22
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/tls_preserve_1.c19
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/tls_preserve_2.c24
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/tls_preserve_3.c24
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/var_stride_2.c3
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/var_stride_4.c3
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/vcond_4.c54
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/vcond_5.c54
-rw-r--r--gcc/testsuite/gcc.target/aarch64/vabs_intrinsic_3.c39
-rw-r--r--gcc/testsuite/gcc.target/aarch64/vabsd_s64.c34
-rw-r--r--gcc/testsuite/gcc.target/aarch64/vneg_s.c34
-rw-r--r--gcc/testsuite/gcc.target/aarch64/vnegd_s64.c36
-rw-r--r--gcc/testsuite/gcc.target/alpha/pr86984.c96
-rw-r--r--gcc/testsuite/gcc.target/csky/and1.c12
-rw-r--r--gcc/testsuite/gcc.target/csky/and2.c12
-rw-r--r--gcc/testsuite/gcc.target/csky/and3a.c12
-rw-r--r--gcc/testsuite/gcc.target/csky/and3b.c11
-rw-r--r--gcc/testsuite/gcc.target/csky/ck801-branch.c40
-rw-r--r--gcc/testsuite/gcc.target/csky/constpool-1.c16
-rw-r--r--gcc/testsuite/gcc.target/csky/constpool-2.c15
-rw-r--r--gcc/testsuite/gcc.target/csky/constpool-3.c15
-rw-r--r--gcc/testsuite/gcc.target/csky/cse-cc.c19
-rw-r--r--gcc/testsuite/gcc.target/csky/csky.exp79
-rw-r--r--gcc/testsuite/gcc.target/csky/fnargs-1.c38
-rw-r--r--gcc/testsuite/gcc.target/csky/fnargs-2.c52
-rw-r--r--gcc/testsuite/gcc.target/csky/fnargs-3.c31
-rw-r--r--gcc/testsuite/gcc.target/csky/land1.c11
-rw-r--r--gcc/testsuite/gcc.target/csky/land2.c11
-rw-r--r--gcc/testsuite/gcc.target/csky/naked.c16
-rw-r--r--gcc/testsuite/gcc.target/csky/or1.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/addr-sel-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-cvt-2.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-cvt-2.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-pr87138.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/mpx.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr45352-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82418.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82699-1.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82699-2.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82699-3.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82699-4.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82699-5.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82699-6.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82853-1.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82853-2.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/pr83554.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr86386.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/pr87065.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/pr87198.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr87290.c34
-rw-r--r--gcc/testsuite/gcc.target/i386/rop1.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-movs.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/strcmpopt_6.c36
-rw-r--r--gcc/testsuite/gcc.target/i386/zee.c2
-rw-r--r--gcc/testsuite/gcc.target/m68k/tls-dimode.c15
-rw-r--r--gcc/testsuite/gcc.target/msp430/pr86662.c13
-rw-r--r--gcc/testsuite/gcc.target/nvptx/atomic_fetch-1.c24
-rw-r--r--gcc/testsuite/gcc.target/nvptx/atomic_fetch-2.c24
-rw-r--r--gcc/testsuite/gcc.target/nvptx/atomic_fetch-3.c24
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-splat-char.c55
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-splat-floatdouble.c46
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-splat-int.c50
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-splat-longlong.c60
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-splat-pixel.c27
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-splat-short.c49
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p8-vec-xl-xst-v2.c5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr56605.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr86731-fwrapv-longlong.c34
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr86731-fwrapv.c63
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr86731-longlong.c29
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr86731-nogimplefold-longlong.c32
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr86731-nogimplefold.c63
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr86731.c61
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr87033.c12
-rw-r--r--gcc/testsuite/gcc.target/s390/TI-constants-lra.c47
-rw-r--r--gcc/testsuite/gcc.target/s390/TI-constants-nolra.c47
-rw-r--r--gcc/testsuite/gcc.target/s390/dfp_to_bfp_rounding.c29
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-8.c20
-rw-r--r--gcc/testsuite/gcc.target/s390/hotpatch-9.c19
-rw-r--r--gcc/testsuite/gcc.target/s390/memset-1.c81
-rw-r--r--gcc/testsuite/gcc.target/s390/mnop-mcount-m31-fpic.c8
-rw-r--r--gcc/testsuite/gcc.target/s390/mnop-mcount-m31.c8
-rw-r--r--gcc/testsuite/gcc.target/s390/nomemloopunroll-1.c27
-rw-r--r--gcc/testsuite/gcc.target/s390/pr80080-3.c10
-rw-r--r--gcc/testsuite/gcc.target/s390/pr84332.c9
-rw-r--r--gcc/testsuite/gcc.target/s390/risbg-ll-3.c6
-rw-r--r--gcc/testsuite/gcc.target/s390/s390.exp9
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-arch-tune-1.c100
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-arch-tune-2.c100
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-1.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-10.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-11.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-12.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-13.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-14.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-15.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-16.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-17.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-18.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-19.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-2.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-20.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-21.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-22.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-23.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-24.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-25.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-26.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-27.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-28.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-29.c32
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-3.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-30.c32
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-31.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-32.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-4.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-5.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-6.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-7.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-8.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-9.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-1.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-10.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-11.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-12.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-13.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-14.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-15.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-16.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-17.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-18.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-19.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-2.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-20.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-21.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-22.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-23.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-24.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-25.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-26.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-27.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-28.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-29.c32
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-3.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-30.c32
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-31.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-32.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-33.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-4.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-5.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-6.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-7.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-8.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-9.c64
-rw-r--r--gcc/testsuite/gcc.target/s390/zvector/vec-cmp-2.c48
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/ms-sysv.exp2
-rw-r--r--gcc/testsuite/gfortran.dg/actual_pointer_function_1.f906
-rw-r--r--gcc/testsuite/gfortran.dg/alloc_comp_basics_6.f903
-rw-r--r--gcc/testsuite/gfortran.dg/alloc_comp_basics_7.f9015
-rw-r--r--gcc/testsuite/gfortran.dg/allocatable_scalar_14.f9017
-rw-r--r--gcc/testsuite/gfortran.dg/allocate_with_mold_2.f9062
-rw-r--r--gcc/testsuite/gfortran.dg/allocate_with_source_25.f9071
-rw-r--r--gcc/testsuite/gfortran.dg/assign_10.f902
-rw-r--r--gcc/testsuite/gfortran.dg/associate_3.f032
-rw-r--r--gcc/testsuite/gfortran.dg/associate_39.f9019
-rw-r--r--gcc/testsuite/gfortran.dg/auto_char_len_2.f902
-rw-r--r--gcc/testsuite/gfortran.dg/auto_char_len_4.f901
-rw-r--r--gcc/testsuite/gfortran.dg/blas_gemm_routines.f1955
-rw-r--r--gcc/testsuite/gfortran.dg/c_ptr_tests_15.f902
-rw-r--r--gcc/testsuite/gfortran.dg/char_array_structure_constructor.f901
-rw-r--r--gcc/testsuite/gfortran.dg/class_17.f032
-rw-r--r--gcc/testsuite/gfortran.dg/class_55.f902
-rw-r--r--gcc/testsuite/gfortran.dg/class_assign_2.f9022
-rw-r--r--gcc/testsuite/gfortran.dg/class_assign_3.f909
-rw-r--r--gcc/testsuite/gfortran.dg/class_result_7.f9036
-rw-r--r--gcc/testsuite/gfortran.dg/class_result_8.f9041
-rw-r--r--gcc/testsuite/gfortran.dg/class_result_9.f9045
-rw-r--r--gcc/testsuite/gfortran.dg/coarray_lib_alloc_4.f902
-rw-r--r--gcc/testsuite/gfortran.dg/coarray_lock_7.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/deferred_character_21.f9029
-rw-r--r--gcc/testsuite/gfortran.dg/deferred_character_22.f9027
-rw-r--r--gcc/testsuite/gfortran.dg/deferred_character_23.f9022
-rw-r--r--gcc/testsuite/gfortran.dg/dtio_1.f9019
-rw-r--r--gcc/testsuite/gfortran.dg/dtio_11.f906
-rw-r--r--gcc/testsuite/gfortran.dg/elemental_function_2.f9040
-rw-r--r--gcc/testsuite/gfortran.dg/elemental_function_3.f9044
-rw-r--r--gcc/testsuite/gfortran.dg/f2003_inquire_1.f034
-rw-r--r--gcc/testsuite/gfortran.dg/f2003_io_1.f032
-rw-r--r--gcc/testsuite/gfortran.dg/finalize_33.f90119
-rw-r--r--gcc/testsuite/gfortran.dg/generic_34.f9027
-rw-r--r--gcc/testsuite/gfortran.dg/generic_35.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/nested-parallelism.f9051
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/pr47331.f902
-rw-r--r--gcc/testsuite/gfortran.dg/implicit_actual.f902
-rw-r--r--gcc/testsuite/gfortran.dg/implied_do_io_6.f9039
-rw-r--r--gcc/testsuite/gfortran.dg/inline_matmul_13.f902
-rw-r--r--gcc/testsuite/gfortran.dg/inline_matmul_15.f902
-rw-r--r--gcc/testsuite/gfortran.dg/inline_matmul_16.f902
-rw-r--r--gcc/testsuite/gfortran.dg/inline_matmul_23.f902
-rw-r--r--gcc/testsuite/gfortran.dg/intent_optimize_2.f9026
-rw-r--r--gcc/testsuite/gfortran.dg/intent_out_10.f9014
-rw-r--r--gcc/testsuite/gfortran.dg/intent_out_11.f90309
-rw-r--r--gcc/testsuite/gfortran.dg/intent_out_12.f9023
-rw-r--r--gcc/testsuite/gfortran.dg/interface_assignment_6.f9030
-rw-r--r--gcc/testsuite/gfortran.dg/iso_c_binding_only_2.f9014
-rw-r--r--gcc/testsuite/gfortran.dg/lto/20091016-1_0.f902
-rw-r--r--gcc/testsuite/gfortran.dg/lto/pr79108_0.f902
-rw-r--r--gcc/testsuite/gfortran.dg/matmul_19.f9025
-rw-r--r--gcc/testsuite/gfortran.dg/matmul_5.f902
-rw-r--r--gcc/testsuite/gfortran.dg/matmul_blas_1.f240
-rw-r--r--gcc/testsuite/gfortran.dg/matmul_bounds_10.f902
-rw-r--r--gcc/testsuite/gfortran.dg/matmul_bounds_11.f902
-rw-r--r--gcc/testsuite/gfortran.dg/matmul_bounds_13.f9013
-rw-r--r--gcc/testsuite/gfortran.dg/matmul_bounds_14.f16
-rw-r--r--gcc/testsuite/gfortran.dg/matmul_bounds_15.f19
-rw-r--r--gcc/testsuite/gfortran.dg/matmul_bounds_16.f20
-rw-r--r--gcc/testsuite/gfortran.dg/matmul_bounds_2.f902
-rw-r--r--gcc/testsuite/gfortran.dg/matmul_bounds_3.f902
-rw-r--r--gcc/testsuite/gfortran.dg/matmul_bounds_4.f902
-rw-r--r--gcc/testsuite/gfortran.dg/matmul_bounds_5.f902
-rw-r--r--gcc/testsuite/gfortran.dg/matmul_bounds_8.f902
-rw-r--r--gcc/testsuite/gfortran.dg/max_expr.f90 (renamed from gcc/testsuite/gfortran.dg/max_fmax_aarch64.f90)4
-rw-r--r--gcc/testsuite/gfortran.dg/min_expr.f90 (renamed from gcc/testsuite/gfortran.dg/min_fmin_aarch64.f90)4
-rw-r--r--gcc/testsuite/gfortran.dg/modulo_check.f908
-rw-r--r--gcc/testsuite/gfortran.dg/nan_1.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/pointer_array_10.f9027
-rw-r--r--gcc/testsuite/gfortran.dg/pr40999.f2
-rw-r--r--gcc/testsuite/gfortran.dg/pr41011.f2
-rw-r--r--gcc/testsuite/gfortran.dg/pr42051.f031
-rw-r--r--gcc/testsuite/gfortran.dg/pr46804.f902
-rw-r--r--gcc/testsuite/gfortran.dg/pr83149_1.f901
-rw-r--r--gcc/testsuite/gfortran.dg/pr83149_b.f901
-rw-r--r--gcc/testsuite/gfortran.dg/pr86328.f9049
-rw-r--r--gcc/testsuite/gfortran.dg/pr86760.f9057
-rw-r--r--gcc/testsuite/gfortran.dg/pr87117.f9014
-rw-r--r--gcc/testsuite/gfortran.dg/pr87217.f32
-rw-r--r--gcc/testsuite/gfortran.dg/predict-1.f902
-rw-r--r--gcc/testsuite/gfortran.dg/proc_ptr_comp_52.f9033
-rw-r--r--gcc/testsuite/gfortran.dg/promotion_2.f907
-rw-r--r--gcc/testsuite/gfortran.dg/reassoc_4.f2
-rw-r--r--gcc/testsuite/gfortran.dg/select_type_43.f9048
-rw-r--r--gcc/testsuite/gfortran.dg/short_circuiting_2.f9028
-rw-r--r--gcc/testsuite/gfortran.dg/short_circuiting_3.f9028
-rw-r--r--gcc/testsuite/gfortran.dg/submodule_32.f0862
-rw-r--r--gcc/testsuite/gfortran.dg/transfer_class_3.f9018
-rw-r--r--gcc/testsuite/gfortran.dg/transpose_optimization_2.f902
-rw-r--r--gcc/testsuite/gfortran.dg/typebound_call_30.f9032
-rw-r--r--gcc/testsuite/gfortran.dg/typebound_proc_12.f902
-rw-r--r--gcc/testsuite/gfortran.dg/use_rename_9.f9019
-rw-r--r--gcc/testsuite/gfortran.dg/vect/vect-8-epilogue.F906
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_1.f902
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_10.f901
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_11.f901
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_12.f901
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_13.f901
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_14.f902
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_15.f901
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_16.f901
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_17.f902
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_18.f902
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_19.f901
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_2.f902
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_20.f032
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_3.f902
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_4.f902
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_5.f902
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_6.f902
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_7.f901
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_8.f901
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_9.f901
-rw-r--r--gcc/testsuite/gnat.dg/access5.adb5
-rw-r--r--gcc/testsuite/gnat.dg/access5.ads10
-rw-r--r--gcc/testsuite/gnat.dg/dinst.adb20
-rw-r--r--gcc/testsuite/gnat.dg/dinst_pkg.adb7
-rw-r--r--gcc/testsuite/gnat.dg/dinst_pkg.ads4
-rw-r--r--gcc/testsuite/gnat.dg/dynhash.adb750
-rw-r--r--gcc/testsuite/gnat.dg/elab6.adb8
-rw-r--r--gcc/testsuite/gnat.dg/elab6.ads6
-rw-r--r--gcc/testsuite/gnat.dg/elab6_pkg.adb17
-rw-r--r--gcc/testsuite/gnat.dg/elab6_pkg.ads4
-rw-r--r--gcc/testsuite/gnat.dg/enum4.adb59
-rw-r--r--gcc/testsuite/gnat.dg/expr_func5.adb10
-rw-r--r--gcc/testsuite/gnat.dg/expr_func6.adb7
-rw-r--r--gcc/testsuite/gnat.dg/expr_func6.ads17
-rw-r--r--gcc/testsuite/gnat.dg/expr_func7.adb5
-rw-r--r--gcc/testsuite/gnat.dg/expr_func7.ads20
-rw-r--r--gcc/testsuite/gnat.dg/linkedlist.adb1184
-rw-r--r--gcc/testsuite/gnat.dg/prot6.adb20
-rw-r--r--gcc/testsuite/gnat.dg/prot6.ads31
-rw-r--r--gcc/testsuite/gnat.dg/rep_clause7.adb29
-rw-r--r--gcc/testsuite/gnat.dg/spark2.adb12
-rw-r--r--gcc/testsuite/gnat.dg/spark2.ads16
-rw-r--r--gcc/testsuite/gnat.dg/task1.adb5
-rw-r--r--gcc/testsuite/gnat.dg/task1.ads10
-rw-r--r--gcc/testsuite/gnat.dg/task1_pkg.adb11
-rw-r--r--gcc/testsuite/gnat.dg/task1_pkg.ads10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug273.go12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4085b.go35
-rw-r--r--gcc/testsuite/lib/gcc-dg.exp8
-rw-r--r--gcc/testsuite/lib/gcc-gdb-test.exp13
-rw-r--r--gcc/testsuite/lib/gcov.exp1
-rw-r--r--gcc/testsuite/lib/multiline.exp20
-rw-r--r--gcc/testsuite/lib/prune.exp2
-rw-r--r--gcc/testsuite/lib/target-supports.exp39
-rw-r--r--gcc/toplev.c9
-rw-r--r--gcc/trans-mem.c20
-rw-r--r--gcc/tree-call-cdce.c2
-rw-r--r--gcc/tree-cfg.c116
-rw-r--r--gcc/tree-cfg.h9
-rw-r--r--gcc/tree-cfgcleanup.c7
-rw-r--r--gcc/tree-core.h5
-rw-r--r--gcc/tree-data-ref.c48
-rw-r--r--gcc/tree-diagnostic.c4
-rw-r--r--gcc/tree-eh.c28
-rw-r--r--gcc/tree-if-conv.c2
-rw-r--r--gcc/tree-inline.c37
-rw-r--r--gcc/tree-into-ssa.c22
-rw-r--r--gcc/tree-loop-distribution.c17
-rw-r--r--gcc/tree-parloops.c36
-rw-r--r--gcc/tree-pretty-print.c87
-rw-r--r--gcc/tree-pretty-print.h3
-rw-r--r--gcc/tree-scalar-evolution.c4
-rw-r--r--gcc/tree-sra.c3
-rw-r--r--gcc/tree-ssa-alias.c36
-rw-r--r--gcc/tree-ssa-ccp.c16
-rw-r--r--gcc/tree-ssa-coalesce.c113
-rw-r--r--gcc/tree-ssa-dce.c4
-rw-r--r--gcc/tree-ssa-dom.c17
-rw-r--r--gcc/tree-ssa-dse.c12
-rw-r--r--gcc/tree-ssa-forwprop.c10
-rw-r--r--gcc/tree-ssa-loop-im.c4
-rw-r--r--gcc/tree-ssa-loop-ivcanon.c57
-rw-r--r--gcc/tree-ssa-loop-niter.c1
-rw-r--r--gcc/tree-ssa-math-opts.c220
-rw-r--r--gcc/tree-ssa-operands.c3
-rw-r--r--gcc/tree-ssa-pre.c97
-rw-r--r--gcc/tree-ssa-propagate.c10
-rw-r--r--gcc/tree-ssa-reassoc.c2
-rw-r--r--gcc/tree-ssa-sccvn.c3891
-rw-r--r--gcc/tree-ssa-sccvn.h100
-rw-r--r--gcc/tree-ssa-strlen.c64
-rw-r--r--gcc/tree-ssa-structalias.c4
-rw-r--r--gcc/tree-ssa-tail-merge.c21
-rw-r--r--gcc/tree-ssa-ter.c2
-rw-r--r--gcc/tree-ssa-threadedge.c4
-rw-r--r--gcc/tree-ssa-uncprop.c2
-rw-r--r--gcc/tree-ssa-uninit.c3
-rw-r--r--gcc/tree-stdarg.c7
-rw-r--r--gcc/tree-streamer-in.c2
-rw-r--r--gcc/tree-streamer-out.c5
-rw-r--r--gcc/tree-switch-conversion.c438
-rw-r--r--gcc/tree-switch-conversion.h47
-rw-r--r--gcc/tree-tailcall.c2
-rw-r--r--gcc/tree-vect-data-refs.c1709
-rw-r--r--gcc/tree-vect-generic.c2
-rw-r--r--gcc/tree-vect-loop-manip.c105
-rw-r--r--gcc/tree-vect-loop.c1570
-rw-r--r--gcc/tree-vect-patterns.c340
-rw-r--r--gcc/tree-vect-slp.c1274
-rw-r--r--gcc/tree-vect-stmts.c2873
-rw-r--r--gcc/tree-vectorizer.c234
-rw-r--r--gcc/tree-vectorizer.h433
-rw-r--r--gcc/tree-vrp.c1442
-rw-r--r--gcc/tree-vrp.h54
-rw-r--r--gcc/tree.c65
-rw-r--r--gcc/tree.h56
-rw-r--r--gcc/ubsan.c2
-rw-r--r--gcc/value-prof.c37
-rw-r--r--gcc/varasm.c39
-rw-r--r--gcc/vec.c13
-rw-r--r--gcc/vr-values.c68
-rw-r--r--gcc/vr-values.h16
-rw-r--r--gcc/wide-int-range.cc841
-rw-r--r--gcc/wide-int-range.h186
1441 files changed, 79635 insertions, 26316 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ca67815..b3d14b9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,28 +1,5435 @@
+2018-09-24 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/82699
+ * config/i386/i386.c (rest_of_insert_endbranch): Set
+ endbr_queued_at_entrance to true and don't insert ENDBR if
+ x86_function_profiler will be called.
+ (x86_function_profiler): Insert ENDBR if endbr_queued_at_entrance
+ is true.
+ * config/i386/i386.h (machine_function): Add
+ endbr_queued_at_entrance.
+
+2018-09-24 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * genattrtab.c (mk_attr_alt): Use alternative_mask.
+ (attr_rtx_1): Adjust caching to match the new EQ_ATTR_ALT field
+ types.
+ (check_attr_test): Use alternative_mask.
+ (get_attr_value): Likewise.
+ (compute_alternative_mask): Use alternative_mask and XWINT.
+ (make_alternative_compare): Use alternative_mask.
+ (attr_alt_subset_p): Use XWINT.
+ (attr_alt_subset_of_compl_p): Likewise.
+ (attr_alt_intersection): Use alternative_mask and XWINT.
+ (attr_alt_union): Likewise.
+ (attr_alt_complement): Use HOST_WIDE_INT and XWINT.
+ (mk_attr_alt): Use alternative_mask and HOST_WIDE_INT.
+ (simplify_test_exp): Use alternative_mask and XWINT.
+ (write_test_expr): Use alternative_mask and XWINT, adjust bit
+ number calculation to support 64 bits. Generate code that
+ checks 64-bit masks.
+ (main): Use alternative_mask.
+ * rtl.def (EQ_ATTR_ALT): Change field types from ii to ww.
+
+2018-09-24 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ PR target/80080
+ * config/s390/s390.c (s390_emit_epilogue): Do not use PARALLEL
+ RETURN+USE when returning via %r14.
+
+2018-09-24 Martin Liska <mliska@suse.cz>
+
+ * gcov.c (output_lines): Print colorization legend
+ for both flag_use_colors and flag_use_hotness_colors.
+ Reword the help.
+
+2018-09-24 Martin Liska <mliska@suse.cz>
+
+ * coverage.c (get_coverage_counts): Use warning_at
+ with current_function_decl location. Use %qD in warning
+ message.
+
+2018-09-24 Martin Liska <mliska@suse.cz>
+
+ * memory-block.h (memory_block_pool::release): Annotate with
+ valgrind that the memory is not accessible.
+
+2018-09-24 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/85774
+ * asan.c: Make asan_handled_variables extern.
+ * asan.h: Likewise.
+ * cfgexpand.c (expand_stack_vars): Make sure
+ a representative is unpoison if another
+ variable in the partition is handled by
+ use-after-scope sanitization.
+
+2018-09-24 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/63155
+ * tree-ssa-propagate.c (add_ssa_edge): Avoid adding PHIs to
+ the worklist when the edge of the respective argument isn't
+ executable.
+
+2018-09-23 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.h (enum reg_class): Rename MASK_REGS to
+ ALL_MASK_REGS and MASK_EVEX_REGS to MASK_REGS.
+ (MASK_CLASS_P): Update for rename.
+ (MAYBE_MASK_CLASS_P): Ditto.
+ (REG_CLASS_NAMES): Update.
+ (REG_CLASS_CONTENT): Update.
+ * config/i386/i386.c (regclass_map): Update for MASK_REG
+ and ALL_MASK_REGS rename.
+ * config/i386/constraints.md (Yk): Update for rename.
+ (k): Ditto.
+
+2018-09-23 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.h (enum reg_class): Remove
+ EVEX_SSE_REGS and MOD4_SSE_REGS.
+ (REG_CLASS_NAMES): Update.
+ (REG_CLASS_CONTENT): Update.
+ * config/i386/i386.c (regclass_map): Declare AVX-512 SSE
+ registers as ALL_SSE_REGS.
+ (ix86_additional_allocno_class_p): Remove.
+ (TARGET_ADDITIONAL_ALLOCNO_CLASS_P): Remove.
+ (ix86_register_priority): Lower priority of EVEX SSE registers.
+ Use IN_RANGE macro where appropriate.
+ (ix86_hard_regno_mode_ok): Merge AVX-5124FMAPS and
+ AVX-5124VNNIW checks.
+ (ix86_modes_tieable_p): Tie 512-bit SSE modes.
+ * config/i386/sse.md (avx5124fmaddps_4fmaddps)
+ (avx5124fmaddps_4fmaddps_mask, avx5124fmaddps_4fmaddps_maskz)
+ (avx5124fmaddps_4fmaddss, avx5124fmaddps_4fmaddss_mask)
+ (avx5124fmaddps_4fmaddss_maskz, avx5124fmaddps_4fnmaddps)
+ (avx5124fmaddps_4fnmaddps_mask, avx5124fmaddps_4fnmaddps_maskz)
+ (avx5124fmaddps_4fnmaddss, avx5124fmaddps_4fnmaddss_mask)
+ (avx5124fmaddps_4fnmaddss_maskz, avx5124vnniw_vp4dpwssd)
+ (avx5124vnniw_vp4dpwssd_mask, avx5124vnniw_vp4dpwssd_maskz)
+ (avx5124vnniw_vp4dpwssds, avx5124vnniw_vp4dpwssds_mask)
+ (avx5124vnniw_vp4dpwssds_maskz): Use "v" instead of "Yh" constraint.
+ * config/i386/constraints.md (Yh): Remove.
+
+2018-09-23 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (regclass_map): Declare integer REX registers
+ as GENERAL_REGS.
+
+2018-09-23 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * doc/service.texi (Service): Switch the fsf.org link to https.
+
+2018-09-22 Chung-Ju Wu <jasonwucj@gmail.com>
+
+ PR target/86798
+ * config/nds32/nds32.c (TARGET_HAVE_SPECULATION_SAFE_VALUE):
+ Define to speculation_safe_value_not_needed.
+
+2018-09-21 Florian Weimer <fweimer@redhat.com>
+
+ PR middle-end/81035
+ * doc/extend.texi (Common Function Attributes): Mention that
+ noreturn suppresses tail call optimization.
+
+2018-09-21 Jeff Law <law@redhat.com>
+
+ * gimple-ssa-evrp.c (evrp_dom_walker::cleanup): Call
+ vr_values::cleanup_edges_and_switches.
+ * tree-vrp.c (to_remove_edges, to_update_switch_stmts): Moved into
+ vr_values class.
+ (identify_jump_threads): Remove EDGE_IGNORE handling.
+ (execute_vrp): Move handling of to_remove_edges and
+ to_update_switch_stmts into vr_values class member functions.
+ * tree-vrp.h (switch_update, to_remove_edges): Remove declarations.
+ (to_update_switch_stmts): Likewise.
+ * vr-values.c: Include cfghooks.h.
+ (vr_values::vr_values): Initialize to_remove_edges and
+ to_update_switch_stmts.
+ (vr_values::~vr_values): Verify to_remove_edges and
+ to_update_switch_stmts are empty.
+ (vr_values::simplify_switch_using_ranges): Set EDGE_IGNORE as needed.
+ (vr_values::cleanup_edges_and_switches): New member function.
+ * vr-values.h (vr_values): Add cleanup_edges_and_switches member
+ function. Add new data members.
+
+2018-09-21 David Malcolm <dmalcolm@redhat.com>
+
+ PR tree-optimization/87309
+ * dumpfile.c (dump_context::begin_scope): Filter the dump_loc
+ calls with pflags and alt_flags.
+ (selftest::test_capture_of_dump_calls): Add test of interaction of
+ MSG_OPTIMIZED_LOCATIONS with AUTO_DUMP_SCOPE.
+
+2018-09-21 Olivier Hainque <hainque@adacore.com>
+
+ * config.gcc: Factorize and comment inclusion of vxworks-dummy.h.
+
+2018-09-21 Olivier Hainque <hainque@adacore.com>
+
+ * config/vxworks.h (CLEAR_INSN_CACHE): #define to 1.
+
+2018-09-21 Olivier Hainque <hainque@adacore.com>
+
+ * config/vxworks.h (VXWORKS_LIBGCC_SPEC): Remove -lc_internal.
+ Merge block comment with the one ahead of VXWORKS_LIBS_RTP. Then:
+ (VXWORKS_LIBS_RTP): Minor reordering.
+
+2018-09-21 Olivier Hainque <hainque@adacore.com>
+
+ * config/vxworks.h (STARTFILE_PREFIX_SPEC): Define.
+ (VXWORKS_LIBS_DIR_RTP): Remove definition and use.
+
+2018-09-21 Olivier Hainque <hainque@adacore.com>
+
+ * config/vxworks.h (SIZE_TYPE): Account for TARGET_VXWORKS64.
+ (PTRDIFF_TYPE): Likewise.
+
+2018-09-21 Olivier Hainque <hainque@adacore.com>
+
+ * config.gcc: Enforce def of TARGET_VXWORKS64 to 1 from
+ triplet, similar to support for VxWorks7.
+ * config/vxworks-dummy.h: Provide a default definition
+ of TARGET_VXWORKS64 to 0.
+
+2018-09-21 Olivier Hainque <hainque@adacore.com>
+
+ * config/vxworks.h (TARGET_VXWORKS7): Move default definition ...
+ * config/vxworks-dummy.h: here.
+
+2018-09-21 Olivier Hainque <hainque@adacore.com>
+
+ * config.gcc: Prepend vxworks-dummy.h to tm_file for powerpc*
+
+2018-09-21 Shaokun Zhang <zhangshaokun@hisilicon.com>
+ Bo Zhou <zbo.zhou@hisilicon.com>
+
+ * config/aarch64/aarch64-cores.def (tsv110): New CPU.
+ * config/aarch64/aarch64-tune.md: Regenerated.
+ * doc/invoke.texi (AArch64 Options/-mtune): Add "tsv110".
+ * config/aarch64/aarch64.c (tsv110_tunings): New tuning table.
+ * config/aarch64/aarch64-cost-tables.h: Add "tsv110" extra costs.
+
+2018-09-21 Andrew Stubbs <ams@codesourcery.com>
+ Julian Brown <julian@codesourcery.com>
+
+ * builtins.c (get_builtin_sync_mem): Handle address spaces.
+
+2018-09-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/rs6000/rs6000.c (rs6000_function_ok_for_sibcall): Return false
+ if the call takes a static chain.
+
+2018-09-21 Martin Liska <mliska@suse.cz>
+
+ * auto-profile.c (autofdo_source_profile::read): Do not
+ set sum_all.
+ (read_profile): Do not add working sets.
+ (read_autofdo_file): Remove sum_all.
+ (afdo_callsite_hot_enough_for_early_inline): Remove const
+ qualifier.
+ * coverage.c (struct counts_entry): Remove gcov_summary.
+ (read_counts_file): Read new GCOV_TAG_OBJECT_SUMMARY,
+ do not support GCOV_TAG_PROGRAM_SUMMARY.
+ (get_coverage_counts): Remove summary and expected
+ arguments.
+ * coverage.h (get_coverage_counts): Likewise.
+ * doc/gcov-dump.texi: Remove -w option.
+ * gcov-dump.c (dump_working_sets): Remove.
+ (main): Do not support '-w' option.
+ (print_usage): Likewise.
+ (tag_summary): Likewise.
+ * gcov-io.c (gcov_write_summary): Do not dump
+ histogram.
+ (gcov_read_summary): Likewise.
+ (gcov_histo_index): Remove.
+ (gcov_histogram_merge): Likewise.
+ (compute_working_sets): Likewise.
+ * gcov-io.h (GCOV_TAG_OBJECT_SUMMARY): Mark
+ it not obsolete.
+ (GCOV_TAG_PROGRAM_SUMMARY): Mark it obsolete.
+ (GCOV_TAG_SUMMARY_LENGTH): Adjust.
+ (GCOV_HISTOGRAM_SIZE): Remove.
+ (GCOV_HISTOGRAM_BITVECTOR_SIZE): Likewise.
+ (struct gcov_summary): Simplify rapidly just
+ to runs and sum_max fields.
+ (gcov_histo_index): Remove.
+ (NUM_GCOV_WORKING_SETS): Likewise.
+ (compute_working_sets): Likewise.
+ * gcov-tool.c (print_overlap_usage_message): Remove
+ trailing empty line.
+ * gcov.c (read_count_file): Read GCOV_TAG_OBJECT_SUMMARY.
+ (output_lines): Remove program related line.
+ * ipa-profile.c (ipa_profile): Do not consider GCOV histogram.
+ * lto-cgraph.c (output_profile_summary): Do not stream GCOV
+ histogram.
+ (input_profile_summary): Do not read it.
+ (merge_profile_summaries): And do not merge it.
+ (input_symtab): Do not call removed function.
+ * modulo-sched.c (sms_schedule): Do not print sum_max.
+ * params.def (HOT_BB_COUNT_FRACTION): Reincarnate param that was
+ removed when histogram method was invented.
+ (HOT_BB_COUNT_WS_PERMILLE): Mention that it's used only in LTO
+ mode.
+ * postreload-gcse.c (eliminate_partially_redundant_load): Fix
+ GCOV coding style.
+ * predict.c (get_hot_bb_threshold): Use HOT_BB_COUNT_FRACTION
+ and dump selected value.
+ * profile.c (add_working_set): Remove.
+ (get_working_sets): Likewise.
+ (find_working_set): Likewise.
+ (get_exec_counts): Do not work with working sets.
+ (read_profile_edge_counts): Do not inform as sum_max is removed.
+ (compute_branch_probabilities): Likewise.
+ (compute_value_histograms): Remove argument for call of
+ get_coverage_counts.
+ * profile.h: Do not make gcov_summary const.
+
+2018-09-21 Monk Chiang <sh.chiang04@gmail.com>
+
+ * config.gcc (nds32*-*-*): Set TARGET_DEFAULT_TLSDESC_TRAMPOLINE=0.
+
+2018-09-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR tree-optimization/86990
+ * gimple-ssa-store-merging.c (imm_store_chain_info:coalesce_immediate):
+ Check that the entire merged store group is made of constants only for
+ overlapping stores.
+
+2018-09-20 Allan Sandfeld Jensen <allan.jensen@qt.io>
+
+ * gcc.c (LINK_COMMAND_SPEC): Handle -r like -nostdlib.
+ (VTABLE_VERIFICATION_SPEC): Likewise.
+ (SANITIZER_EARLY_SPEC): Likewise.
+ (SANITIZER_SPEC): Likewise.
+ * config/darwin.h (LINK_COMMAND_SPEC): Likewise.
+ * doc/invoke.texi (Link Options): Document -r.
+
+2018-09-20 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/87054
+ * gimplify.c (gimplify_expr): Retain alignment of
+ addressable lvalue in dereference.
+
+2018-09-20 Alexandre Oliva <aoliva@redhat.com>
+
+ PR bootstrap/87013
+ * configure.ac: Check for .loc is_stmt support.
+ * configure, config.in: Rebuilt.
+ * dwarf2out.c (dwarf2out_source_line): Skip is_stmt
+ if not supported.
+
+2018-09-20 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.opt (misel=no, misel=yes): Delete.
+ * doc/invoke.texi (RS/6000 and PowerPC Options): Delete -misel=yes and
+ -misel=no.
+
+2018-09-20 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000-opts.h (enum rs6000_vector): Delete
+ VECTOR_OTHER.
+ * config/rs6000/rs6000.c (rs6000_debug_vector_unit): Delete
+ case VECTOR_OTHER.
+
+2018-09-20 Marek Polacek <polacek@redhat.com>
+
+ * doc/invoke.texi: Add -Wno-init-list-lifetime to C++ Language Options.
+
+2018-09-20 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/87288
+ * tree-vect-loop.c (vect_analyze_loop_2): Take PEELING_FOR_GAPS
+ into account when determining PEELING_FOR_NITERS.
+
+2018-09-20 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/86877
+ * tree-vect-loop.c (vect_analyze_loop_2): Call
+ vect_verify_datarefs_alignment.
+
+2018-09-19 Marek Polacek <polacek@redhat.com>
+
+ * doc/invoke.texi: Document -Wclass-conversion.
+
+2018-09-19 John David Anglin <danglin@gcc.gnu.org>
+
+ * config/pa/pa.c (pa_adjust_priority): Delete.
+ (TARGET_SCHED_ADJUST_PRIORITY): Delete define.
+
+ * config/pa/pa.md (atomic_storeqi): Restore deleted expander.
+ (atomic_storehi): Likewise.
+ (atomic_storesi): Likewise.
+ (atomic_loaddi): Restore compare and swap exchange loop code.
+
+2018-09-19 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR rtl-optimization/86902
+ * combine.c (try_combine): When changing the CC mode used, don't change
+ an unrelated mode in other_insn to that new CC mode.
+
+2018-09-19 David Malcolm <dmalcolm@redhat.com>
+
+ * tree-data-ref.c (runtime_alias_check_p): Use formatted printing
+ with %T in place of calls to dump_generic_expr.
+ (prune_runtime_alias_test_list): Likewise.
+ (create_runtime_alias_checks): Likewise.
+ * tree-vect-data-refs.c (vect_check_nonzero_value): Likewise.
+ (vect_analyze_data_ref_dependence): Likewise.
+ (vect_slp_analyze_data_ref_dependence): Likewise.
+ (vect_record_base_alignment): Likewise. Use %G in place of call
+ to dump_gimple_stmt.
+ (vect_compute_data_ref_alignment): Likewise.
+ (verify_data_ref_alignment): Likewise.
+ (vect_find_same_alignment_drs): Likewise.
+ (vect_analyze_group_access_1): Likewise.
+ (vect_analyze_data_ref_accesses): Likewise.
+ (dependence_distance_ge_vf): Likewise.
+ (dump_lower_bound): Likewise.
+ (vect_prune_runtime_alias_test_list): Likewise.
+ (vect_find_stmt_data_reference): Likewise.
+ (vect_analyze_data_refs): Likewise.
+ (vect_create_addr_base_for_vector_ref): Likewise.
+ (vect_create_data_ref_ptr): Likewise.
+ * tree-vect-loop-manip.c (vect_set_loop_condition): Likewise.
+ (vect_can_advance_ivs_p): Likewise.
+ (vect_update_ivs_after_vectorizer): Likewise.
+ (vect_gen_prolog_loop_niters): Likewise.
+ (vect_prepare_for_masked_peels): Likewise.
+ * tree-vect-loop.c (vect_determine_vf_for_stmt): Likewise.
+ (vect_determine_vectorization_factor): Likewise.
+ (vect_is_simple_iv_evolution): Likewise.
+ (vect_analyze_scalar_cycles_1): Likewise.
+ (vect_analyze_loop_operations): Likewise.
+ (report_vect_op): Likewise.
+ (vect_is_slp_reduction): Likewise.
+ (check_reduction_path): Likewise.
+ (vect_is_simple_reduction): Likewise.
+ (vect_create_epilog_for_reduction): Likewise.
+ (vect_finalize_reduction:): Likewise.
+ (vectorizable_induction): Likewise.
+ (vect_transform_loop_stmt): Likewise.
+ (vect_transform_loop): Likewise.
+ (optimize_mask_stores): Likewise.
+ * tree-vect-patterns.c (vect_pattern_detected): Likewise.
+ (vect_split_statement): Likewise.
+ (vect_recog_over_widening_pattern): Likewise.
+ (vect_recog_average_pattern): Likewise.
+ (vect_determine_min_output_precision_1): Likewise.
+ (vect_determine_precisions_from_range): Likewise.
+ (vect_determine_precisions_from_users): Likewise.
+ (vect_mark_pattern_stmts): Likewise.
+ (vect_pattern_recog_1): Likewise.
+ * tree-vect-slp.c (vect_get_and_check_slp_defs): Likewise.
+ (vect_record_max_nunits): Likewise.
+ (vect_build_slp_tree_1): Likewise.
+ (vect_build_slp_tree_2): Likewise.
+ (vect_print_slp_tree): Likewise.
+ (vect_analyze_slp_instance): Likewise.
+ (vect_detect_hybrid_slp_stmts): Likewise.
+ (vect_detect_hybrid_slp_1): Likewise.
+ (vect_slp_analyze_operations): Likewise.
+ (vect_slp_analyze_bb_1): Likewise.
+ (vect_transform_slp_perm_load): Likewise.
+ (vect_schedule_slp_instance): Likewise.
+ * tree-vect-stmts.c (vect_mark_relevant): Likewise.
+ (vect_mark_stmts_to_be_vectorized): Likewise.
+ (vect_init_vector_1): Likewise.
+ (vect_get_vec_def_for_operand): Likewise.
+ (vect_finish_stmt_generation_1): Likewise.
+ (vect_check_load_store_mask): Likewise.
+ (vectorizable_call): Likewise.
+ (vectorizable_conversion): Likewise.
+ (vectorizable_operation): Likewise.
+ (vectorizable_load): Likewise.
+ (vect_analyze_stmt): Likewise.
+ (vect_is_simple_use): Likewise.
+ (vect_get_vector_types_for_stmt): Likewise.
+ (vect_get_mask_type_for_stmt): Likewise.
+ * tree-vectorizer.c (increase_alignment): Likewise.
+
+2018-09-19 Andrew Stubbs <ams@codesourcery.com>
+
+ * doc/rtl.texi: Adjust vec_select description.
+ * simplify-rtx.c (simplify_binary_operation_1): Allow VEC_SELECT to use
+ non-constant selectors.
+
+2018-09-19 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ * config/aarch64/aarch64-protos.h
+ (aarch64_offset_9bit_signed_unscaled_p): New declaration.
+ * config/aarch64/aarch64.md (arches): New "rcpc8_4" attribute value.
+ (arch_enabled): Add check for "rcpc8_4" attribute value of "arch".
+ * config/aarch64/aarch64.h (AARCH64_FL_RCPC8_4): New bitfield.
+ (AARCH64_FL_FOR_ARCH8_4): Include AARCH64_FL_RCPC8_4.
+ (AARCH64_FL_PROFILE): Move index so flags are ordered.
+ (AARCH64_ISA_RCPC8_4): New flag.
+ * config/aarch64/aarch64.c (offset_9bit_signed_unscaled_p): Renamed
+ to aarch64_offset_9bit_signed_unscaled_p.
+ * config/aarch64/atomics.md (atomic_store<mode>): Allow offset
+ and use stlur.
+ * config/aarch64/constraints.md (Ust): New constraint.
+ * config/aarch64/predicates.md.
+ (aarch64_9bit_offset_memory_operand): New predicate.
+ (aarch64_rcpc_memory_operand): New predicate.
+
+2018-09-19 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR rtl-optimization/87361
+ * rtlanal.c (nonzero_bits1): Revert accidental change.
+
+2018-09-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87349
+ PR tree-optimization/87342
+ * tree-ssa-sccvn.c (do_rpo_vn): Iterate max_rpo computation.
+
+2018-09-18 Marek Polacek <polacek@redhat.com>
+
+ P1064R0 - Allowing Virtual Function Calls in Constant Expressions
+ * gimple-fold.c (gimple_get_virt_method_for_vtable): Adjust assert.
+
+2018-09-18 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md: Remove old "Cygnus sibcall" comment.
+
+2018-09-18 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR rtl-optimization/86882
+ * rtlanal.c (reg_overlap_mentioned_p): Handle CLOBBER.
+
+2018-09-18 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (*<code>extend<mode>xf2): Macroize insn from
+ *<code>extendsfxf2 and *<code>extenddfxf2 using MODEF mode iterator.
+
+2018-09-18 Jonathan Wakely <jwakely@redhat.com>
+
+ PR other/87353
+ * doc/invoke.texi (Link Options): Fix formatting and grammar.
+
+2018-09-18 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/63155
+ * tree-ssa-coalesce.c (tree_int_map_hasher): Remove.
+ (compute_samebase_partition_bases): Likewise.
+ (coalesce_ssa_name): Always use compute_optimized_partition_bases.
+ (gimple_can_coalesce_p): Simplify.
+
+2018-09-18 Hans-Peter Nilsson <hp@bitrange.com>
+
+ Handle a library implementation of ffs calling __builtin_ffs.
+ * config/mmix/mmix.c (TARGET_INIT_LIBFUNCS): Override with...
+ (mmix_init_libfuncs): New function: make __builtin_ffs expand
+ to __ffsdi2.
+
+2018-09-17 David Malcolm <dmalcolm@redhat.com>
+
+ * diagnostic-show-locus.c (class layout_range): Add field
+ "m_original_idx".
+ (layout_range::layout_range): Add "original_idx" param and use it
+ to initialize new field.
+ (make_range): Use 0 for original_idx.
+ (layout::layout): Pass in index to calls to
+ maybe_add_location_range.
+ (layout::maybe_add_location_range): Add param "original_idx" and
+ pass it on to layout_range.
+ (layout::print_any_labels): Pass on range->m_original_idx to
+ get_text call.
+ (gcc_rich_location::add_location_if_nearby): Use 0 for
+ original_idx.
+ * gcc-rich-location.h (text_range_label::get_text): Update for new
+ param.
+ (range_label_for_type_mismatch::get_text): Likewise.
+
+2018-09-17 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (ix86_emit_i387_log1p): Emit fldln2 earlier.
+
+2018-09-17 David Malcolm <dmalcolm@redhat.com>
+
+ * gimple-ssa-sprintf.c (fmtwarn): Update for introduction of
+ format_string_diagnostic_t.
+ (fmtwarn_n): Likewise.
+ * substring-locations.c
+ (format_string_diagnostic_t::format_string_diagnostic_t) New ctor.
+ (format_warning_n_va): Convert to...
+ (format_string_diagnostic_t::emit_warning_n_va): ...this.
+ (format_warning_va): Convert to...
+ (format_string_diagnostic_t::emit_warning_va): ...this.
+ (format_warning_at_substring): Convert to...
+ (format_string_diagnostic_t::emit_warning): ...this.
+ (format_warning_at_substring_n): Convert to...
+ (format_string_diagnostic_t::emit_warning_n): ...this.
+ * substring-locations.h (class format_string_diagnostic_t): New
+ class.
+ (format_warning_va): Convert to
+ format_string_diagnostic_t::emit_warning_va.
+ (format_warning_n_va): Convert to
+ format_string_diagnostic_t::emit_warning_n_va.
+ (format_warning_at_substring): Convert to
+ format_string_diagnostic_t::emit_warning.
+ (format_warning_at_substring_n): Convert to
+ format_string_diagnostic_t::emit_warning_n.
+
+2018-09-17 Cesar Philippidis <cesar@codesourcery.com>
+ Bernd Schmidt <bernds_cb1@t-online.de>
+
+ * config/nvptx/nvptx.md (atomic_fetch_<logic><mode>): Enable with
+ SImode args.
+
+2018-09-17 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (truncxf<mode>2_i387_noop_unspec): Change
+ operand 0 predicate to nonimmediate operand.
+ (rint<mode>2_frndint): Remove insn pattern.
+ (rint<mode>2): Change operand 1 predicate to general_operand.
+ Extend operand 1 to XFmode and generate rintxf2 insn.
+ (frndintxf2_<rounding>): Rename from frndint<mode>2_<rounding>.
+ Do not use X87MODEF mode macro.
+ (frndintxf2_<rounding>_i387): Rename from
+ frndint<mode>2_<rounding>_i387. Do not use X87MODEF mode macro.
+ (<rounding_insn><mode>2): For non-SSE modes, extend operand 1
+ to XFmode and generate significandxf3 insn.
+
+2018-09-17 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87328
+ * tree-ssa-sccvn.c (process_bb): Remove assertion about not
+ visiting unexecutable backedges when not iterating.
+ (do_rpo_vn): Mark all edges not executable even when not
+ iterating.
+
+2018-09-17 Martin Jambor <mjambor@suse.cz>
+
+ PR c/63886
+ * doc/invoke.texi (Warning Options): Likewise.
+
+2018-09-17 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87301
+ * tree-ssa-sccvn.c (eliminate_dom_walker::eliminate_cleanup): Properly
+ clean EH info from leftover copy assignments.
+
+2018-09-17 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/85871
+ * gcov.c (output_intermediate_file): Fix out of bounds
+ access.
+
+2018-09-17 Vineet Gupta <vgupta@synopsys.com>
+
+ * config/arc/arc.c: Object attributes for core4 not reflected
+ correctly.
+ * config/arc/arc.h: Don't restrict DBNZ to core3 (core4 includes
+ core3).
+
+2018-09-17 Alexey Brodkin <abrodkin@synopsys.com>
+
+ * config/arc/linux.h (LINK_EH_SPEC): Add missing space.
+
+2018-09-17 Martin Liska <mliska@suse.cz>
+
+ * doc/gcov.texi: Document new option --use-hotness-colors.
+ * gcov.c (struct source_info): Declare new field.
+ (source_info::source_info): Set default for maximum_count.
+ (print_usage): Add new -q option.
+ (process_args): Process it.
+ (accumulate_line_info): Save src->maximum_count.
+ (output_line_beginning): Make color line number if
+ flag_use_hotness_colors is set.
+ (output_line_details): Pass default argument value.
+ (output_lines): Pass src->maximum_count.
+
+2018-09-17 Martin Liska <mliska@suse.cz>
+
+ * common/config/i386/i386-common.c (ix86_get_valid_option_values):
+ Use processor_names table.
+ * config/i386/i386.c (ix86_default_align): Use
+ processor_cost_table for alignment values.
+ (ix86_option_override_internal): Use processor_names.
+ (ix86_function_specific_print): Likewise.
+ * config/i386/i386.h (struct processor_costs):
+ Add alignment values.
+ (struct ptt): Remove and replace with const char *.
+ * config/i386/x86-tune-costs.h (struct processor_costs):
+ Declare default alignments for all costs.
+
+2018-09-17 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-vrp.c (extract_range_from_unary_expr): Do not special case
+ symbolics or VR_VARYING ranges for ABS_EXPR.
+ * wide-int-range.cc (wide_int_range_abs): Return positive numbers
+ when range will wrap.
+
+2018-09-15 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR middle-end/86864
+ * cfgexpand.c (expand_gimple_basic_block): Be prepared for a BARRIER
+ before and after a JUMP_TABLE_DATA.
+
+2018-09-14 John David Anglin <danglin@gcc.gnu.org>
+
+ PR middle-end/87188
+ * dojump.c (do_compare_and_jump): Canonicalize function pointers
+ when one operand is a function pointer. Use POINTER_TYPE_P and
+ FUNC_OR_METHOD_TYPE_P.
+ * expr.c (do_store_flag): Use POINTER_TYPE_P and FUNC_OR_METHOD_TYPE_P.
+ * fold-const.c (build_range_check): Likewise.
+ * match.pd (simple_comparison): Likewise.
+
+2018-09-14 David Malcolm <dmalcolm@redhat.com>
+
+ PR c/82967
+ * spellcheck.c (get_edit_distance_cutoff): New function.
+ (selftest::test_edit_distance_unit_test_oneway): Rename to...
+ (selftest::test_get_edit_distance_one_way): ...this.
+ (selftest::test_get_edit_distance_unit): Rename to...
+ (selftest::test_get_edit_distance_both_ways): ...this.
+ (selftest::test_edit_distances): Move tests to this new function,
+ and test some more pairs of strings. Update for above renaming.
+ (selftest::get_old_cutoff): New function.
+ (selftest::test_get_edit_distance_cutoff): New function.
+ (selftest::assert_suggested_for): New function.
+ (ASSERT_SUGGESTED_FOR): New macro.
+ (selftest::assert_not_suggested_for): New function.
+ (ASSERT_NOT_SUGGESTED_FOR): New macro.
+ (selftest::test_suggestions): New function.
+ (selftest::spellcheck_c_tests): Move test_get_edit_distance_unit
+ tests to selftest::test_edit_distances and call it. Add calls to
+ selftest::test_get_edit_distance_cutoff and
+ selftest::test_suggestions.
+ * spellcheck.h (get_edit_distance_cutoff): New function declaration.
+ (best_match::consider): Replace hard-coded cutoff calculation with
+ a call to...
+ (best_match::get_cutoff): New declaration.
+ (best_match::get_best_meaningful_candidate): Likewise.
+
+2018-09-14 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * builtins.c (fold_builtin_strlen): Remove TODO comment.
+
+2018-09-14 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ revert:
+ 2018-07-30 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * tree-ssa-forwprop.c (simplify_builtin_call): Don't create a not NUL
+ terminated string literal.
+
+2018-09-14 Martin Sebor <msebor@redhat.com>
+
+ * builtins.c (unterminated_array): Handle ARRAY_REF.
+ (expand_builtin_stpcpy_1): Detect unterminated char arrays.
+ * builtins.h (unterminated_array): Declare extern.
+ * gimple-fold.c (gimple_fold_builtin_stpcpy): Detect unterminated
+ arrays.
+ (gimple_fold_builtin_sprintf): Propagate NO_WARNING to transformed
+ calls.
+
+2018-09-14 Martin Sebor <msebor@redhat.com>
+ Jeff Law <law@redhat.com>
+
+ * builtins.c (unterminated_array): New.
+ (expand_builtin_strcpy): Adjust.
+ (expand_builtin_strcpy_args): Detect unterminated arrays.
+ * gimple-fold.c (get_maxval_strlen): Add argument. Detect
+ unterminated arrays.
+ * gimple-fold.h (get_maxval_strlen): Add argument.
+ (gimple_fold_builtin_strcpy): Detec unterminated arrays.
+
+ * gimple-fold.c (get_range_strlen): Add argument.
+ (get_maxval_strlen): Adjust.
+ * gimple-fold.h (get_range_strlen): Add argument.
+
+2018-09-14 Wei Xiao <wei3.xiao@intel.com>
+
+ * config/i386/movdirintrin.h: Fix copyright year.
+
+2018-09-14 Uros Bizjak <ubizjak@gmail.com>
+
+ * reg-stack.c: Include regs.h.
+ (replace_reg): Assert that mode is MODE_FLOAT or MODE_COMPLEX_FLOAT.
+ (emit_pop_insn): Default pop insn mode to the reg_raw_mode of
+ FIRST_STACK_REG, not DFmode.
+ (emit_swap_insn): Default swap insn mode to the reg_raw_mode of
+ FIRST_STACK_REG, not XFmode. Explicitly construct swap RTX.
+ (change stack): Default register mode to the reg_raw_mode of
+ FIRST_STACK_REG, not DFmode.
+ * config/i386/i386.md (*swap<mode>): Remove insn pattern.
+ (*swapxf): Rename from swapxf.
+
+2018-09-14 Carl Love <cel@us.ibm.com>
+
+ * config/rs6000/emmintrin.h: Add _MM_SHUFFLE2.
+ * config/rs6000/xmmintrin.h: Add _MM_SHUFFLE.
+
+2018-09-14 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR target/87224
+ * config/rs6000/rs6000.md (*mov<mode>_hardfloat64): Add Z to the Y
+ alternatives.
+
+2018-09-14 Sam Tebbs <sam.tebbs@arm.com>
+
+ PR target/85628
+ * config/aarch64/aarch64.md (*aarch64_bfxilsi_uxtw): Define.
+
+2018-09-14 Jason Merrill <jason@redhat.com>
+
+ Fix --enable-gather-detailed-mem-stats.
+ * hash-table.c (hash_table_usage): Change from variable to function.
+ * hash-table.h: Adjust.
+ * Makefile.in: Add missing dependencies on hash-table.h.
+
+2018-09-14 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR tree-optimization/87259
+ PR lto/87283
+ (pass_cse_reciprocals::execute): Run optimize_recip_sqrt after
+ execute_cse_reciprocals_1 has tried transforming.
+
+2018-09-14 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-vrp.c (extract_range_from_binary_expr_1): Normalize
+ VR_VARYING for PLUS/MINUS_EXPR.
+
+2018-09-14 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * config/s390/s390-passes.def (INSERT_PASS_BEFORE): Improve
+ formatting.
+
+2018-09-14 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/63155
+ * tree-ssa-coalesce.c (ssa_conflicts_merge): Remove conflict
+ bits for the merged partition.
+
+2018-09-13 Martin Sebor <msebor@redhat.com>
+ Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * builtins.h (c_srlen): Add argument.
+ * builtins.c (warn_string_no_nul): New function.
+ (c_strlen): Add argument and use it. Update recursive calls.
+ Pass DECL argument to string_constant to get info on non
+ terminated strings. Update *NONSTR as needed.
+ (fold_builtin_strlen): Add argument to calls to c_strlen.
+ Warn for unterminated arrays.
+ (warn_string_no_null): Add prototype.
+ * expr.c (string_constant): Update arguments. Update recursive
+ calls appropriately. Detect missing NUL terminator and outermost
+ declaration its missing in.
+ Improve checks for arrays with nonzero lower bound or elements
+ that are not a single byte. Simplify offset computation.
+ Simplify checks for non-NUL terminated strings.
+ * gimple-fold.c (get_range_strlen): Add argument to c_strlen call.
+ * gimple-ssa-sprintf.c (get_string_length): Remove unnecessary code.
+
+2018-09-13 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * builtins.c (c_strlen): Handle not zero terminated STRING_CSTs
+ correctly.
+ * fold-const.c (c_getstr): Fix function comment. Remove unused third
+ argument. Fix range checks.
+ * fold-const.h (c_getstr): Adjust protoype.
+ * gimple-fold.c (gimple_fold_builtin_memory_op): Avoid folding when
+ string is constant but contains no NUL byte.
+
+ * expr.c (string_constant): Adjust function comment.
+ Remove bogus check for zero termination.
+
+ * fold-const.c (c_getstr): Clamp STRING_LENGTH to STRING_SIZE.
+
+ * varasm.c (compare_constant): Compare type size of STRING_CSTs.
+ (get_constant_size): Don't make STRING_CSTs larger than they are.
+ (check_string_literal): New check function for STRING_CSTs.
+ (output_constant): Use it.
+
+2018-09-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/86812
+ * config/visium/visium.c (TARGET_HAVE_SPECULATION_SAFE_VALUE): Define.
+
+2018-09-13 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87263
+ * tree-ssa-sccvn.c (visit_phi): Revert some earlier changes.
+ (struct unwind_state): Add max_rpo field.
+ (do_rpo_vn): Allow up-to-date loop state to be used when not iterating.
+ Compute max_rpo, the max RPO number a block can be backwards reached
+ from. Re-write non-iterating mode to a RPO ordered worklist approach,
+ separating it from the iterating mode.
+
+2018-09-13 Vlad Lazar <vlad.lazar@arm.com>
+
+ * haifa-sched.c (rank_for_schedule): Schedule by INSN_COST.
+ (rfs_decision): New scheduling decision.
+
+2018-09-13 Richard Biener <rguenther@suse.de>
+
+ PR bootstrap/87134
+ * tree-ssa-sccvn.c (vn_nary_op_insert_into): Fix assert.
+ (vn_nary_op_insert_pieces_predicated): Do not write useless
+ valid_dominated_by_p entry outside of the allocated storage.
+
+2018-09-13 Omar Sandoval <osandov@osandov.com>
+ Tom de Vries <tdevries@suse.de>
+
+ PR debug/86985
+ * dwarf2out.c (is_c): New function.
+ (add_subscript_info): Add DW_AT_count of 0 for C zero-length arrays.
+
+2018-09-13 Sam Tebbs <sam.tebbs@arm.com>
+
+ PR target/85628
+ * config/aarch64/aarch64.md (*aarch64_bfxil):
+ Define.
+ * config/aarch64/constraints.md (Ulc): Define.
+ * config/aarch64/aarch64-protos.h (aarch64_high_bits_all_ones_p):
+ Define.
+ * config/aarch64/aarch64.c (aarch64_high_bits_all_ones_p):
+ New function.
+
+2018-09-13 Vlad Lazar <vlad.lazar@arm.com>
+
+ * config/aarch64/aarch64.h (TARGET_COMPUTE_FRAME_LAYOUT): Define.
+ * config/aarch64/aarch64.c (aarch64_expand_prologue): Remove
+ aarch64_layout_frame call.
+ (aarch64_expand_epilogue): Likewise.
+ (aarch64_initial_elimination_offset): Likewise.
+ (aarch64_get_separate_components): Likewise.
+ (aarch64_use_return_insn_p): Likewise.
+ (aarch64_layout_frame): Remove unneeded check.
+
+2018-09-13 Jakub Jelinek <jakub@redhat.com>
+
+ * configure.ac: Only append
+ " : (reconfigured) $TOPLEVEL_CONFIGURE_ARGUMENTS" to
+ gcc_config_arguments if it was never reconfigured or last reconfigure
+ was with different arguments.
+ * configure: Regenerated.
+
+2018-09-13 Jakub Jelinek <jakub@redhat.com>
+ Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR middle-end/87290
+ * expr.c (maybe_optimize_pow2p_mod_cmp): New function.
+ (maybe_optimize_mod_cmp): Use it if integer_pow2p treeop1.
+
+2018-09-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/87287
+ * fold-const.c (fold_binary_loc) <case EQ_EXPR>: Move signed modulo
+ X % C == 0 to X % (unsigned) C == 0 optimization to ...
+ * match.pd (X % C == 0): ... here. New optimization.
+
+2018-09-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/82853
+ * expr.h (maybe_optimize_mod_cmp): Declare.
+ * expr.c (mod_inv): New function.
+ (maybe_optimize_mod_cmp): New function.
+ (do_store_flag): Use it.
+ * cfgexpand.c (expand_gimple_cond): Likewise.
+
+2018-09-09 Cesar Philippidis <cesar@codesourcery.com>
+ Julian Brown <julian@codesourcery.com>
+
+ PR middle-end/86336
+ * gimplify.c (gimplify_scan_omp_clauses): Set
+ target_firstprivatize_array_bases in OpenACC parallel and kernels
+ region contexts. Remove GOMP_MAP_FIRSTPRIVATE_REFERENCE clauses from
+ OpenACC data regions.
+
+2018-09-12 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (sqrt_extend<mode>xf3_i387): Remove.
+ (sqrt<mode>2): Extend operand 1 to XFmode and generate sqrtxf3 insn.
+
+2018-09-12 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87280
+ * tree-ssa-sccvn.c (process_bb): Handle the case of executable
+ edge but unreachable target.
+ (do_rpo_vn): For conservatively handling a PHI only mark
+ the backedge executable but not the block reachable.
+
+2018-09-12 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87266
+ * tree-ssa-sccvn.c (do_rpo_vn): Always iterate to not yet
+ visited blocks.
+
+2018-09-12 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * config/s390/s390.md (PFPO_RND_MODE_DFP, PFPO_RND_MODE_BFP): New
+ constants.
+ ("trunc<BFP:mode><DFP_ALL:mode>2")
+ ("trunc<DFP_ALL:mode><BFP:mode>2")
+ ("extend<BFP:mode><DFP_ALL:mode>2")
+ ("extend<DFP_ALL:mode><BFP:mode>2"): Set proper rounding mode
+ according to the target operand type.
+
+2018-09-12 Jakub Jelinek <jakub@redhat.com>
+ Andreas Krebbel <krebbel@linux.ibm.com>
+
+ PR tree-optimization/86844
+ * gimple-ssa-store-merging.c
+ (imm_store_chain_info::coalesce_immediate): For overlapping stores, if
+ there are any overlapping stores in between them, make sure they are
+ also coalesced or we give up completely.
+
+2018-09-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/87248
+ * fold-const.c (fold_ternary_loc) <case COND_EXPR>: Verify also that
+ BIT_AND_EXPR's second operand is a power of two. Formatting fix.
+
+2018-09-12 Tom de Vries <tdevries@suse.de>
+
+ * common.opt (gdescribe-dies): Add option.
+ * dwarf2out.c (add_name_and_src_coords_attributes): Add description
+ attribute for artifical and nameless decls.
+ (dwarf2out_register_external_die): Add description attribute to
+ external reference die.
+ (add_desc_attribute): New functions.
+ (gen_subprogram_die): Add description attribute to
+ DW_TAG_call_site_parameter.
+ * tree-pretty-print.c (print_generic_expr_to_str): New function.
+ * tree-pretty-print.h (print_generic_expr_to_str): Declare.
+ * doc/invoke.texi (@item Debugging Options): Add -gdescribe-dies and
+ -gno-describe-dies.
+ (@item -gdescribe-dies): Add.
+
+2018-09-12 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-vrp.c (vrp_shift_undefined_p): Remove.
+ (extract_range_from_binary_expr_1: Call
+ wide_int_range_shift_undefined_p instead of vrp_shift_undefined_p.
+ * wide-int-range.h (wide_int_range_shift_undefined_p): Do not
+ depend on sign.
+
+2018-09-12 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-ssa-warn-alloca.c
+ (alloca_type_and_limit::alloca_type_and_limit): Initialize limit
+ field for ALLOCA_BOUND_*_LARGE.
+
+2018-09-11 Nathan Sidwell <nathan@acm.org>
+
+ * gcc.c (load_specs, execute, run_attempt): Use %qs not '%s'.
+
+2018-09-11 Uros Bizjak <ubizjak@gmail.com>
+
+ * reg-stack.c (subst_asm_stack_regs): Call replace_reg also
+ for clobbers. Remove obsolete comment.
+
+2018-09-11 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (define_attr "type"): Remove mpxmov, mpxmk,
+ mpxchk, mpxld and mpxst types.
+ (define_attr length_immediate): Remove all processing of mpx types.
+ (define_attr prefix_0f): Ditto.
+ (define_attr memory): Ditto.
+
+2018-09-11 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (fyl2x_extend<mode>xf3_i387): Remove.
+ (log<mode>2): Change operand 1 predicate to general_operand.
+ Extend operand 1 to XFmode and generate logxf3 insn.
+ (log10<mode>2): Change operand 1 predicate to general_operand.
+ Extend operand 1 to XFmode and generate log10xf3 insn.
+ (log2<mode>2): Change operand 1 predicate to general_operand.
+ Extend operand 1 to XFmode and generate log2xf3 insn.
+ (fyl2xp1_extend<mode>xf3_i387): Remove.
+ (log1p<mode>2): Change operand 1 predicate to general_operand.
+ Extend operand 1 to XFmode and generate log1pxf3 insn.
+ (fxtract_extend<mode>xf3_i387): Remove.
+ (logb<mode>2): Change operand 1 predicate to general_operand.
+ Extend operand 1 to XFmode and generate logbxf3 insn.
+ (ilogb<mode>2): Change operand 1 predicate to general_operand.
+ Extend operand 1 to XFmode and generate fxtractxf3_i387 insn.
+ (significand<mode>2): Change operand 1 predicate to general_operand.
+ Extend operand 1 to XFmode and generate significandxf3 insn.
+
+2018-09-11 Nathan Sidwell <nathan@acm.org>
+
+ * gcc.c (perror_with_name, pfatal_with_name): Delete.
+ (load_specs): Use fatal_error.
+ (DELETE_IF_ORDINARY, process_command): Use error.
+ (execute, run_attempt): Use fatal_error.
+
+2018-09-11 Andrew Stubbs <ams@codesourcery.com>
+
+ * diagnostic-core.h (sorry_at): New prototype.
+ * diagnostic.c (sorry_at): New function.
+
+2018-09-11 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-vrp.c (extract_range_from_binary_expr_1): Treat all divisions
+ by zero as VR_UNDEFINED.
+
+2018-09-10 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (<sincos>xf2): Rename from *<sincos>xf2_i387.
+ (*<sincos>_extend<mode>xf2_i387): Remove insn pattern.
+ (<sincos>mode2): New expander.
+ (sincos_extend<mode>xf3_i387): Remove insn pattern.
+ (sincos -> sin, cos splitters): Remove splitter patterns.
+ (sincos<mode>3): Change operand 2 predicate to general_operand.
+ Extend operand 2 to XFmode and generate sincosxf3 insn.
+ (fptanxf4_i387): Change mode of operands 0 and 3 to SFmode.
+ Change operand 3 predicate to const1_operand.
+ (fptan_extend<mode>xf4_i387): Remove insn pattern.
+ (tanxf2): Update operands in the call to fptanxf4_i387.
+ (tan<mode>2): Change operand 1 predicate to general_operand.
+ Extend operand 1 to XFmode and generate tanxf3 insn.
+ (atan2xf3): Rename from *fpatanxf3_i387.
+ (fpatan_extend<mode>xf3_i387): Remove insn pattern.
+ (atan2xf3): Remove expander.
+ (atan2<mode<3): Change operand 1 and 2 predicates to general_operand.
+ Extend operands 1 and 2 to XFmode and generate atan2xf3 insn.
+ (atan<mode>2): Change operand 1 predicate to general_operand.
+ Extend operand 1 to XFmode and generate atanxf3 insn.
+
+2018-09-10 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (x87/SSE constant load splitter): Use
+ memory_operand instead of nonimmediate_operand for input operand
+ predicate.
+
+2018-09-09 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (float partial SSE register stall splitter): Move
+ splitter near its instruction pattern.
+ (float_extend partial SSE register stall splitter): Ditto.
+ (float_truncate partial SSE register stall splitter): Ditto.
+
+2018-09-09 Hans-Peter Nilsson <hp@bitrange.com>
+
+ PR target/86794
+ * config/mmix/mmix.c (TARGET_HAVE_SPECULATION_SAFE_VALUE): Redefine
+ to speculation_safe_value_not_needed.
+
+ PR target/85666
+ * config/mmix/mmix.c (mmix_assemble_integer): Handle byte-size
+ non-CONST_INT rtx:es using assemble_integer_with_op ".byte".
+ (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS): Don't call
+ leaf_function_p, instead use has_hard_reg_initial_val.
+
+2018-09-09 Nathan Sidwell <nathan@acm.org>
+
+ * gcc.h (pfatal_with_name): Don't declare here.
+ * gcc.c (pfatal_with_name): Make static.
+
+2018-09-09 Xianmiao Qu <xianmiao_qu@c-sky.com>
+
+ * config/csky/csky.md (*cskyv2_adddi3, *cskyv2_subdi3): Add
+ earlyclobber.
+
+2018-09-08 John David Anglin <danglin@gcc.gnu.org>
+
+ PR rtl-optimization/85458
+ * sel-sched.c (sel_target_adjust_priority): Allow backend adjust
+ priority hook to reduce the priority of EXPR.
+
+2018-09-07 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (float<SWI48x:mode><MODEF:mode>2) Enable
+ DImode for x87 on 32bit targets. Conditionally disable x87 modes
+ with X87_ENABLE_FLOAT. Remove preparation code.
+ (*float<SWI48:mode><MODEF:mode>2): Rename from
+ *float<SWI48:mode><MODEF:mode>2_mixed. Handle x87, SSE and mixed
+ math using "enabled" attribute.
+ (*floatdi<MODEF:mode>2_i387): Rename from
+ *float<SWI48x:mode><MODEF:mode>2_i387. Handle only DImode and
+ enable for 32bit targets only.
+ (floatdi<X87MODEF:mode>2_i387_with_xmm pre-reload splitter): New
+ splitter.
+ (floatdi<X87MODEF:mode>2_i387_with_xmm): Use register_operand
+ as operand 1 predicate. Rewrite as define_insn_and_split.
+ (floatdi<X87MODEF:mode>2_i387_with_xmm memory input splitter): Remove.
+
+2018-09-06 Uros Bizjak <ubizjak@gmail.com>
+
+ * reg-stack.c (get_true_reg) <case FLOAT_TRUNCATE>: Reorder
+ to fallthru to FLOAT case.
+
+2018-09-06 Will Schmidt <will_schmidt@vnet.ibm.com>
+
+ PR target/86731
+ * config/rs6000/rs6000.c (rs6000_gimple_fold_builtin): Update logic
+ around folding of vec_sl to handle out of range shift values.
+
+2018-09-06 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (fix_trunc<mode>_fisttp_i387_1): Remove.
+ Update callers to gen_fix_trunc<mode>_i387_fisttp
+ (fix_trunc<mode>_i387_fisttp): Change operand 0 predicate to
+ nonimmediate_operand.
+ (fix_trunc<mode>_i387_fisttp_with_temp): Remove insn pattern
+ and corresponding splitters.
+ (*fix_trunc<mode>_i387_1): Always expand with fix_trunc<mode>_i387.
+ (fix_truncdi_i387): Change operand 0 predicate to nonimmediate_operand.
+ (fix_truncdi_i387_with_temp): Remove insn pattern
+ and corresponding splitters.
+ (fix_trunc<mode>_i387): Change operand 0 predicate to
+ nonimmediate_operand.
+ (fix_trunc<mode>_i387_with_temp): Remove insn pattern
+ and corresponding splitters.
+ (*fistdi2_1): Remove.
+ (fistdi2): Ditto.
+ (fistdi2_with_temp): Remove insn pattern and corresponding splitters.
+ (lrintxfdi2): Remove expander. Reimplement as define_insn.
+ (*fist<mode>2_1): Remove.
+ (fist<mode>2): Ditto.
+ (fist<mode>2_with_temp): Remove insn pattern and corresponding
+ splitters.
+ (lrintxf<mode>2): Remove expander. Reimplement as define_insn.
+ (*fist<mode>2_<rounding>_1): Always expand with fist<mode>2_<rounding>.
+ (fistdi2_<rounding>): Change operand 0 predicate to
+ nonimmediate_operand.
+ (fistdi2_<rounding>_with_temp): Remove insn pattern
+ and corresponding splitters.
+ (fist<mode>2_<rounding>): Change operand 0 predicate to
+ nonimmediate_operand.
+ (fist<mode>2_<rounding>_with_temp): Remove insn pattern
+ and corresponding splitters.
+
+ (*fixuns_trunc<mode>si2_avx512f_zext): Depend on TARGET_SSE_MATH.
+
+2018-09-06 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * varasm.c (output_constructor_regular_field): Check TYPE_SIZE_UNIT of
+ the init value.
+
+2018-09-06 Will Schmidt <will_schmidt@vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_gimple_fold_builtin): Add support for
+ early gimple folding of vec_splat().
+ * tree-vect-generic.c: Remove static from tree_vec_extract() definition.
+ * gimple-fold.h: Add an extern define for tree_vec_extract().
+
+2018-09-06 Will Schmidt <will_schmidt@vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (fold_mergehl_helper): Add types_compatible_p
+ wrappers around TREE_TYPE comparisons.
+
+2018-09-06 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ PR target/80080
+ * config/s390/predicates.md: Add nonsym_memory_operand.
+ * config/s390/s390.c (s390_legitimize_cs_operand): If operand
+ contains a SYMBOL_REF, load it into an intermediate pseudo.
+ (s390_emit_compare_and_swap): Legitimize operand.
+ * config/s390/s390.md: Use the new nonsym_memory_operand
+ with UNSPECV_CAS patterns.
+
+2018-09-06 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ PR target/80080
+ * config/s390/s390-passes.def: New file.
+ * config/s390/s390-protos.h (class rtl_opt_pass): Add forward
+ declaration.
+ (make_pass_s390_early_mach): Add declaration.
+ * config/s390/s390.c (make_pass_s390_early_mach):
+ (s390_option_override): Remove dynamic registration.
+ * config/s390/t-s390: Add s390-passes.def.
+
+2018-09-06 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * config/s390/s390.c (s390_decompose_constant_pool_ref):
+ Remove UNSPEC_LTREL_BASE check.
+ (annotate_constant_pool_refs): Likewise.
+ (find_constant_pool_ref): Likewise.
+ (find_ltrel_base): Removed.
+ (replace_ltrel_base): Removed.
+ (s390_mainpool_finish): Remove replace_ltrel_base call.
+ (s390_chunkify_start): Remove pending LTREL_BASE logic.
+ (s390_chunkify_finish): Remove replace_ltrel_base call.
+ * config/s390/s390.md: Remove UNSPEC_LTREL_BASE.
+
+2018-09-06 Hans-Peter Nilsson <hp@axis.com>
+
+ PR target/86779
+ * config/cris/cris.c (TARGET_HAVE_SPECULATION_SAFE_VALUE): Redefine
+ to speculation_safe_value_not_needed.
+
+2018-09-05 Cesar Philippidis <cesar@codesourcery.com>
+ Bernd Schmidt <bernds_cb1@t-online.de>
+
+ * config/nvptx/nvptx-opts.h: New file.
+ * config/nvptx/nvptx.c (nvptx_file_start): Print the correct .target.
+ * config/nvptx/nvptx.h: Include "nvptx-opts.h".
+ (ASM_SPEC): Define.
+ (TARGET_SM35): New macro.
+ * config/nvptx/nvptx.md (atomic_fetch_<logic><mode>): Enable with the
+ correct predicate.
+ * config/nvptx/nvptx.opt (ptx_isa, sm_30, sm_35): New enum and its
+ values.
+ (misa=): New option.
+ * doc/invoke.texi (Nvidia PTX Options): Document -misa.
+
+2018-09-05 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (truncdfsf2): Remove expander.
+ (truncdfsf2_with_temp): Ditto.
+ (truncxf<mode>2): Ditto.
+ (*truncdfsf_fast_mixed): Remove insn pattern.
+ (*truncdfsf_fast_i387): Ditto.
+ (*truncdfsf_mixed): Ditto.
+ (*truncdfsf_i387): Ditto.
+ (*truncdfsf2_i387_1): Ditto.
+ (*truncxfsf2_mixed): Ditto.
+ (*truncxfdf2_mixed): Ditto.
+ (*truncxf<mode>2_i387_noop): Ditto. Update callers
+ to call gen_truncxf<mode>2 instead.
+ (*truncxf<mode>2_i387): Remove.
+ (reg->reg splitters): Remove splitter pattern.
+ (reg->mem splitters): Ditto.
+
+ (truncdfsf2): New insn pattern.
+ (truncxf<mode>2): Ditto.
+
+2018-09-05 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * tree-ssa-math-opts.c (is_mult_by): New function.
+ (is_square_of): Use the above.
+ (optimize_recip_sqrt): New function.
+ (pass_cse_reciprocals::execute): Use the above.
+
+2018-09-05 Richard Biener <rguenther@suse.de>
+
+ PR bootstrap/87134
+ * tree-ssa-sccvn.c (rpo_elim::eliminate_push_avail): Make sure
+ to zero-init the emplaced vec.
+
+2018-09-05 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/87205
+ * tree-switch-conversion.c (pass_lower_switch::execute):
+ Group cases for switch statements.
+
+2018-09-05 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87217
+ * tree-ssa-sccvn.c (vuse_valueize): New.
+ (vn_reference_lookup_pieces): Use it.
+ (vn_reference_lookup): Likewise.
+
+2018-09-05 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/87137
+ * stor-layout.c (place_field): Scan forwards to check last
+ bitfield when ms_bitfield_placement is in effect.
+
+2018-09-05 Richard Biener <rguenther@suse.de>
+
+ PR bootstrap/87225
+ * tree-vect-stmts.c (vectorizable_simd_clone_call): Fix bogus
+ return.
+
+2018-09-05 Siddhesh Poyarekar <siddhesh@sourceware.org>
+ Kugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org>
+
+ * config/aarch64/falkor-tag-collision-avoidance.c: New file.
+ * config.gcc (extra_objs): Build it.
+ * config/aarch64/t-aarch64 (falkor-tag-collision-avoidance.o):
+ Likewise.
+ * config/aarch64/aarch64-passes.def
+ (pass_tag_collision_avoidance): New pass.
+ * config/aarch64/aarch64.c (qdf24xx_tunings): Add
+ AARCH64_EXTRA_TUNE_RENAME_LOAD_REGS to tuning_flags.
+ (aarch64_classify_address): Remove static qualifier.
+ (aarch64_address_info, aarch64_address_type): Move to...
+ * config/aarch64/aarch64-protos.h: ... here.
+ (make_pass_tag_collision_avoidance): New function.
+ * config/aarch64/aarch64-tuning-flags.def (rename_load_regs):
+ New tuning flag.
+
+2018-09-05 Martin Liska <mliska@suse.cz>
+
+ * doc/gcov.texi: Update documentation of humar
+ readable mode.
+ * gcov.c (format_count): Print one decimal place, it provides
+ more fine number of situations like '1G' vs. '1.4G'.
+
+2018-09-05 Martin Liska <mliska@suse.cz>
+
+ PR target/87164
+ * config/rs6000/rs6000.opt: Mark the option as Deprecated.
+ * optc-gen.awk: Allow 'Var' for Deprecated options in order
+ to generate a MASK value.
+
+2018-09-04 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR debug/86593
+ * dwarf2out.c (based_loc_descr): Allow hard frame pointer even
+ if frame pointer isn't used.
+ (compute_frame_pointer_to_fb_displacement): Likewise.
+
+2018-09-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/87198
+ * common/config/i386/i386-common.c (OPTION_MASK_ISA_XSAVEOPT_SET,
+ OPTION_MASK_ISA_XSAVES_SET, OPTION_MASK_ISA_XSAVEC_SET): Use
+ OPTION_MASK_ISA_XSAVE_SET instead of OPTION_MASK_ISA_XSAVE.
+ (OPTION_MASK_ISA_XSAVE_UNSET): Add OPTION_MASK_ISA_XSAVES_UNSET
+ and OPTION_MASK_ISA_XSAVEC_UNSET.
+
+2018-09-04 Max Filippov <jcmvbkbc@gmail.com>
+
+ * config/xtensa/xtensa.c (xtensa_expand_atomic): Reorder AND and
+ XOR operations in NAND case.
+
+2018-09-04 Aldy Hernandez <aldyh@redhat.com>
+
+ * wide-int-range.cc (wide_int_range_convert): New.
+ * wide-int-range.h (wide_int_range_convert): New.
+ * tree-vrp.c (extract_range_from_unary_expr): Abstract wide int
+ code into wide_int_range_convert.
+ (extract_range_into_wide_ints): Do not munge anti range constants
+ into the entire domain. Just return the range back.
+
+2018-09-04 Martin Liska <mliska@suse.cz>
+
+ * genmatch.c (output_line_directive): Add new argument
+ fnargs.
+ (dt_simplify::gen_1): Encapsulate dump within __builtin_expect.
+
+2018-09-04 Jonathan Wakely <jwakely@redhat.com>
+
+ * doc/invoke.texi (Option Summary): Add whitespace.
+
+ * doc/invoke.texi (Option Summary): Add -Waligned-new.
+
+2018-09-04 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87211
+ * tree-ssa-sccvn.c (visit_phi): When value-numbering to a
+ backedge value we're supposed to treat as VARYING also number
+ the PHI to VARYING in case it got a different value-number already.
+
+2018-09-04 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-vrp.c (vrp_can_optimize_bit_op): Remove.
+ (extract_range_from_binary_expr_1): Do not call
+ vrp_can_optimize_bit_op.
+ * wide-int-range.cc (wide_int_range_can_optimize_bit_op): Make
+ static.
+ (wide_int_range_get_mask_and_bounds): New.
+ (wide_int_range_optimize_bit_op): New.
+ (wide_int_range_bit_ior): Call wide_int_range_optimize_bit_op.
+ (wide_int_range_bit_and): Same.
+ * wide-int-range.h (wide_int_range_can_optimize_bit_op): Remove.
+ (wide_int_range_optimize_bit_op): New.
+ (wide_int_range_get_mask_and_bounds): New.
+
+2018-09-04 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87176
+ * tree-ssa-sccvn.c (visit_phi): Remove redundant allsame
+ variable. When value-numbering a virtual PHI node make sure
+ to not value-number to the backedge value.
+
+2018-09-04 Jonathan Wakely <jwakely@redhat.com>
+
+ * doc/extend.texi (Long Long, Hex Floats): Document support for
+ long long and hex floats in more recent versions of ISO C++.
+
+2018-09-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87177
+ * tree-ssa-sccvn.c (vuse_ssa_val): Revert previous change, keep
+ cleanup.
+
+2018-09-03 Alexander Monakov <amonakov@ispras.ru>
+
+ * bb-reorder.c (edge_order): Convert to C-qsort-style
+ tri-state comparator.
+ (reorder_basic_blocks_simple): Change std::stable_sort to
+ gcc_stablesort.
+
+2018-09-03 Alexander Monakov <amonakov@ispras.ru>
+
+ * tree-loop-distribution.c (offset_cmp): Convert to C-qsort-style
+ tri-state comparator.
+ (fuse_memset_builtins): Change std::stable_sort to gcc_stablesort.
+
+2018-09-03 Alexander Monakov <amonakov@ispras.ru>
+
+ * sort.cc (struct sort_ctx): New field 'nlim'. Use it...
+ (mergesort): ... here as maximum count for using netsort.
+ (gcc_qsort): Set nlim to 3 if stable sort is requested.
+ (gcc_stablesort): New.
+ * system.h (gcc_stablesort): Declare.
+
+2018-09-03 Alexander Monakov <amonakov@ispras.ru>
+
+ * sort.cc (gcc_qsort) [CHECKING_P]: Call qsort_chk.
+ * system.h (qsort): Always redirect to gcc_qsort. Update comment.
+ * vec.c (qsort_chk): Do not call gcc_qsort. Update comment.
+
+2018-09-03 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (*mov<mode>_hardfloat32): Remove %U from the
+ lxsdx and stxsdx alternatives.
+ (*mov<mode>_hardfloat64): Ditto.
+ * config/rs6000/vsx.md (*vsx_extract_<mode>_store): Ditto.
+
+2018-09-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87200
+ * tree-ssa-sccvn.c (vn_nary_build_or_lookup_1): Valueize a
+ simplify result.
+
+2018-09-03 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/87201
+ * tree-switch-conversion.c (switch_decision_tree::balance_case_nodes):
+ Fix parenthesis in an expression.
+
+2018-09-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87197
+ * tree-ssa-sccvn.c (vn_nary_build_or_lookup_1): Mark the new def
+ visited. CSE the VN_INFO hashtable lookup.
+
+ PR tree-optimization/87169
+ * tree-ssa-sccvn.c (do_rpo_vn): When marking loops for not
+ iterating make sure there's no extra backedges from irreducible
+ regions feeding the header. Mark the destination block
+ executable.
+
+2018-09-03 Martin Liska <mliska@suse.cz>
+
+ PR driver/83193
+ * common/common-target.def: Add TARGET_GET_VALID_OPTION_VALUES.
+ * common/common-targhooks.c (default_get_valid_option_values):
+ New function.
+ * common/common-targhooks.h (default_get_valid_option_values):
+ Likewise.
+ * common/config/i386/i386-common.c: Move processor_target_table
+ from i386.c.
+ (ix86_get_valid_option_values): New function.
+ (TARGET_GET_VALID_OPTION_VALUES): New macro.
+ * config/i386/i386.c (struct ptt): Move to i386-common.c.
+ (PTA_*): Move all defined masks into i386-common.c.
+ (ix86_function_specific_restore): Use new processor_cost_table.
+ * config/i386/i386.h (struct ptt): Moved from i386.c.
+ (struct pta): Likewise.
+ * doc/tm.texi: Document new TARGET_GET_VALID_OPTION_VALUES.
+ * doc/tm.texi.in: Likewise.
+ * opt-suggestions.c (option_proposer::suggest_option):
+ Pass prefix to build_option_suggestions.
+ (option_proposer::get_completions): Likewise.
+ (option_proposer::build_option_suggestions): Use the new target
+ hook.
+ * opts.c (struct option_help_tuple): New struct.
+ (print_filtered_help): Use the new target hook.
+
+2018-09-03 Martin Liska <mliska@suse.cz>
+
+ PR middle-end/59521
+ * predict.c (set_even_probabilities): Add likely_edges
+ argument and handle cases where we have precisely one
+ likely edge.
+ (combine_predictions_for_bb): Catch also likely_edges.
+ (tree_predict_by_opcode): Handle gswitch statements.
+ * tree-cfg.h (find_case_label_for_value): New declaration.
+ (find_taken_edge_switch_expr): Likewise.
+ * tree-switch-conversion.c (switch_decision_tree::balance_case_nodes):
+ Find pivot in decision tree based on probabily, not by number of
+ nodes.
+
+2018-09-02 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * doc/standards.texi (Standards): Update Objective-C reference.
+
+2018-09-01 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * doc/install.texi (Prerequisites): Update link for MPC.
+
+2018-09-01 Michael Matz <matz@suse.de>
+
+ PR tree-optimization/87074
+ * gimple-loop-jam.c (unroll_jam_possible_p): Check loop exit
+ PHIs for outer-loop uses.
+
+2018-09-01 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * doc/generic.texi (OpenMP): Adjust link to openmp.org.
+ * doc/invoke.texi (C Dialect Options): Ditto.
+
+2018-09-01 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * doc/install.texi (Prerequisites): Adjust link mpfr.org.
+
+2018-08-31 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87168
+ * tree-ssa-sccvn.c (SSA_VAL): Add visited output parameter.
+ (rpo_elim::eliminate_avail): When OP was not visited it must
+ be available.
+
+2018-08-31 David Malcolm <dmalcolm@redhat.com>
+
+ * tree-vrp.c (copy_value_range): Convert param "from" from
+ "value_range *" to "const value_range *".
+ (range_is_null): Likewise for param "vr".
+ (range_int_cst_p): Likewise.
+ (range_int_cst_singleton_p): Likewise.
+ (symbolic_range_p): Likewise.
+ (value_ranges_intersect_p): Likewise for both params.
+ (value_range_nonnegative_p): Likewise for param "vr".
+ (value_range_constant_singleton): Likewise.
+ (vrp_set_zero_nonzero_bits): Likewise for param "ar".
+ (extract_range_into_wide_ints): Likewise for param "vr".
+ (extract_range_from_multiplicative_op): Likewise for params "vr0"
+ and "vr1".
+ (vrp_can_optimize_bit_op): Likewise.
+ (extract_range_from_binary_expr_1): Likewise for params "vr0_" and
+ "vr1_".
+ (extract_range_from_unary_expr): Likewise.
+ (debug_value_range): Likewise for param "vr".
+ (value_range::dump): Add "const" qualifier.
+ (vrp_prop::check_array_ref): Convert local "vr" from
+ "value_range *" to "const value_range *".
+ (vrp_prop::check_mem_ref): Likewise.
+ (vrp_prop::visit_stmt): Likewise for local "old_vr".
+ (vrp_intersect_ranges_1): Likewise for param "vr_1".
+ (vrp_intersect_ranges): Likewise.
+ (simplify_stmt_for_jump_threading): Likewise for local "vr".
+ (vrp_prop::vrp_finalize): Likewise.
+ * tree-vrp.h (value_range::dump): Add "const" qualifier.
+ (vrp_intersect_ranges): Add "const" qualifier to params as above.
+ (extract_range_from_unary_expr): Likewise.
+ (value_range_constant_singleton): Likewise.
+ (symbolic_range_p): Likewise.
+ (copy_value_range): Likewise.
+ (extract_range_from_binary_expr_1): Likewise.
+ (range_int_cst_p): Likewise.
+ (vrp_set_zero_nonzero_bits): Likewise.
+ (range_int_cst_singleton_p): Likewise.
+
+2018-08-31 Vlad Lazar <vlad.lazar@arm.com>
+
+ * config/aarch64/arm_neon.h (vabsd_s64): New.
+ (vnegd_s64): Likewise.
+
+2018-08-31 Martin Jambor <mjambor@suse.cz>
+
+ * ipa-cp.c (estimate_local_effects): Replace wrong MAX with MIN.
+
+2018-08-31 Martin Liska <mliska@suse.cz>
+
+ * ipa-icf.c (sem_item::add_type): Use
+ sem_item::m_type_hash_cache.
+ * ipa-icf.h: Move the cache from sem_item_optimizer
+ to sem_item.
+
+2018-08-31 Nathan Sidwell <nathan@acm.org>
+
+ * doc/extend.texi (Backwards Compatibility): Remove implicit
+ extern C leeway of () being (...).
+
+2018-08-31 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * ipa-inline.c (can_inline_edge_by_limits_p): Fix typos in comment.
+
+2018-08-31 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR target/86684
+ PR target/87149
+ * config/rs6000/rs6000.md (lround<mode>di2): Gate on TARGET_FPRND.
+
+2018-08-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/87138
+ * expmed.c (expand_mult_const): Use immed_wide_int_const instead of
+ gen_int_mode. Formatting fixes.
+
+2018-08-30 Sandra Loosemore <sandra@codesourcery.com>
+
+ * target.def (custom_function_descriptors): Improve documentation.
+ * doc/tm.texi.in (Trampolines): Expand discussion of function
+ descriptors and move TARGET_CUSTOM_FUNCTION_DESCRIPTORS to the
+ beginning of the section.
+ * doc/tm.texi: Regenerated.
+
+2018-08-30 Jose E. Marchesi <jose.marchesi@oracle.com>
+
+ * cfg.h (class auto_edge_flag): Spell out the template-id of the
+ base class in the initializer list. This is a workaround for
+ building with older GCC.
+ (class auto_bb_flag): Likewise.
+
+2018-08-30 Aaron Sawdey <acsawdey@linux.ibm.com>
+
+ * config/rs6000/altivec.md (altivec_eq<mode>): Remove star.
+ (altivec_vcmpequ<VI_char>_p): Remove star.
+ * config/rs6000/rs6000-string.c (do_load_for_compare): Support
+ vector load modes.
+ (expand_strncmp_vec_sequence): New function.
+ (emit_final_str_compare_vec): New function.
+ (expand_strn_compare): Add support for vector strncmp.
+ * config/rs6000/rs6000.opt (-mstring-compare-inline-limit): Change
+ length specification to bytes.
+ * config/rs6000/vsx.md (vsx_ld_elemrev_v16qi_internal): Remove star.
+ (vcmpnezb_p): New pattern.
+ * doc/invoke.texi (RS/6000 and PowerPC Options): Update documentation
+ for option -mstring-compare-inline-limit.
+
+2018-08-30 Thiago Macieira <thiago.macieira@intel.com>
+
+ * config/i386/i386.c (PTA_WESTMERE): Remove PTA_AES.
+ (PTA_SKYLAKE): Add PTA_AES.
+ (PTA_GOLDMONT): Likewise.
+
+2018-08-29 Jan Hubicka <jh@suse.cz>
+
+ PR lto/86517
+ * lto-opts.c (lto_write_options): Always stream PIC/PIE mode.
+ * lto-wrapper.c (merge_and_complain): Fix merging of PIC/PIE.
+
+2018-08-29 Jan Hubicka <jh@suse.cz>
+
+ * lto-streamer-out.c (DFS::DFS_write_tree_body): Do not follow
+ TYPE_STUB_DECL.
+ (hash_tree): Do not visit TYPE_STUB_DECL.
+ * tree-streamer-out.c (write_ts_type_common_tree_pointers): Do not
+ stream TYPE_STUB_DECL.
+ * tree-streamer-in.c (lto_input_ts_type_common_tree_pointers): Likewise.
+ * ipa-utils.h (type_with_linkage_p): Do not rely on TYPE_STUB_DECL
+ after free_lang_data.
+ (type_in_anonymous_namespace_p): Likewise.
+
+2018-08-29 Jan Hubicka <jh@suse.cz>
+
+ * sreal.h (SREAL_PART_BITS): Change to 31; remove seemingly unnecessary
+ comment that it has to be even number.
+ (class sreal): Change m_sig type to int32_t.
+ * sreal.c (sreal::dump, sreal::to_int, opreator+, operator-): Use
+ int64_t for temporary calculations.
+ (sreal_verify_basics): Drop one bit from minimum and maximum.
+
+2018-08-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87147
+ * tree-ssa-sccvn.c (SSA_VISITED): New function.
+ (visit_phi): When the degenerate result is from the backedge and
+ we didn't visit its definition yet drop to VARYING.
+ (do_rpo_vn): Properly mark blocks with incoming backedges as executable.
+
+2018-08-29 Jan Hubicka <jh@suse.cz>
+
+ * lto-streamer-out.c (DFS::DFS_write_tree_body): Do not walk
+ DECL_VINDEX.
+ (hash_tree): Likewise.
+
+2018-08-29 Jan Hubicka <jh@suse.cz>
+
+ * tree.c (find_decls_types_r): Walk also TYPE_NEXT_PTR_TO
+ and TYPE_NEXT_REF_TO.
+
+2018-08-29 Jan Hubicka <jh@suse.cz>
+
+ * sreal.h (SREAL_PART_BITS): Change to 31; remove seemingly unnecessary
+ comment that it has to be even number.
+ (class sreal): Change m_sig type to int32_t.
+ * sreal.c (sreal::dump, sreal::to_int, opreator+, operator-): Use
+ int64_t for temporary calculations.
+ (sreal_verify_basics): Drop one bit from minimum and maximum.
+
+2018-08-30 Tamar Christina <tamar.christina@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_expand_movmem): Set TImode max.
+
+2018-08-30 Vlad Lazar <vlad.lazar@arm.com>
+
+ PR middle-end/86995
+ * expmed.c (canonicalize_comparison): Use wi::sub instead of wi::add
+ if to_add is negative.
+
+2018-08-29 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR middle-end/87053
+ * builtins.c (c_strlen): Improve range checks.
+
+2018-08-29 Martin Sebor <msebor@redhat.com>
+ Jeff Law <law@redhat.com>
+
+ PR tree-optimization/86714
+ PR tree-optimization/86711
+ * builtins.c (c_strlen): Add arguments to call to string_constant.
+ * expr.c (string_constant): Add argument. Detect missing nul
+ terminator and outermost declaration it's missing in.
+ * expr.h (string_constant): Add argument.
+ * fold-const.c (read_from_constant_string): Add arguments to call to
+ string_constant.
+ (c_getstr): Likewise.
+ * tree-ssa-forwprop.c (simplify_builtin_call): Likewise.
+ to string_constant.
+ * tree-ssa-strlen.c (get_stridx): Likewise.
+
+2018-08-29 Jan Hubicka <jh@suse.cz>
+
+ * tree-streamer-in.c (lto_input_ts_function_decl_tree_pointers):
+ Do not stream DECL_VINDEX.
+ * tree-streamer-out.c (write_ts_function_decl_tree_pointers): Likewise.
+ * tree.c (free_lang_data_in_decl): Clear DECL_VINDEX.
+ (decl_function_context): Use DECL_VIRTUAL_P rather than DECL_VINDEX.
+
+2018-08-29 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-sccvn.c (vuse_ssa_val): Return NULL for unvisited
+ virtual operands that are not default defs to honor region
+ boundaries.
+ (rpo_vn_valueize): Remove ineffective code here.
+
+2018-08-29 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87132
+ * tree-ssa-alias.c (get_continuation_for_phi): Do not translate
+ when skipping defs reachable over backedges.
+
+2018-08-29 Richard Biener <rguenther@suse.de>
+
+ * tree-core.h: Document use of deprecated_flag in SSA_NAME.
+ * tree.h (SSA_NAME_POINTS_TO_READONLY_MEMORY): Define.
+ * tree-into-ssa.c (pass_build_ssa::execute): Initialize
+ function parameters SSA_NAME_POINTS_TO_READONLY_MEMORY from fnspec.
+ * tree-ssa-sccvn.c (const_parms, init_const_parms): Remove.
+ (vn_reference_lookup_3): Remove use of const_parms.
+ (free_rpo_vn): Do not free const_parms.
+ (do_rpo_vn): Do not call init_const_parms.
+ * tree-ssa-alias.c (refs_may_alias_p_1): Honor
+ SSA_NAME_POINTS_TO_READONLY_MEMORY.
+ (call_may_clobber_ref_p_1): Likewise.
+
+2018-08-29 Alexander Monakov <amonakov@ispras.ru>
+
+ PR other/86726
+ * invoke.texi (Optimization Options): List -ftree-scev-cprop.
+ (-O): Ditto.
+ (-ftree-scev-cprop): Document.
+
+2018-08-29 Jan Hubicka <jh@suse.cz>
+
+ * sreal.h (normalize, normalize_up, normalize_down): Add new_sig/new_exp
+ parameters.
+ (sreal constructor): Update.
+ * sreal.c (sreal:operator+, sreal:operator-, sreal:operator*,
+ sreal:operator/): Update.
+
+2018-08-29 Martin Liska <mliska@suse.cz>
+
+ * tree-switch-conversion.c (switch_conversion::expand):
+ Strenghten assumption about gswitch statements.
+
+2018-08-29 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87117
+ * tree-ssa-sccvn.c (eliminate_dom_walker::eliminate_stmt): Only
+ re-value-number released SSA VDEFs.
+
+2018-08-29 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87126
+ * tree-ssa-sccvn.c (vn_reference_insert): Remove assert.
+
+2018-08-28 Jim Wilson <jimw@sifive.com>
+
+ * config/riscv/pic.md: Rewrite.
+ * config/riscv/riscv.c (riscv_address_insns): Return cost of 3 for
+ invalid address.
+ * config/riscv/riscv.md (ZERO_EXTEND_LOAD): Delete.
+ (SOFTF, default_load, softload, softstore): New.
+
+2018-08-28 Jeff Law <law@redhat.com>
+
+ * fold-const.c (fold_binary_loc): Remove recently added assert.
+
+2018-08-28 Joern Rennecke <joern.rennecke@riscy-ip.com>
+
+ * genpreds.c (write_predicate_subfunction): Also add ATTRIBUTE_UNUSED
+ to OP parmeter of generated function.
+
+2018-08-28 MCC CS <deswurstes@users.noreply.github.com>
+
+ PR tree-optimization/87009
+ * match.pd: Add boolean optimizations.
+
+2018-08-28 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/86631
+ * calls.c (alloc_max_size): Treat HOST_WIDE_INT special.
+ * gimple-ssa-warn-alloca.c (adjusted_warn_limit): New function.
+ (pass_walloca::gate): Use it.
+ (alloca_call_type): Same.
+ (pass_walloca::execute): Same.
+ * stor-layout.c (layout_decl): Treat HOST_WIDE_INT special.
+
+2018-08-28 David Malcolm <dmalcolm@redhat.com>
+
+ * dumpfile.h (ATTRIBUTE_GCC_DUMP_PRINTF): Change version check on
+ GCC_VERSION for usage of "__gcc_dump_printf__" format from
+ >= 3005 to >= 9000.
+
+2018-08-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87124
+ * tree-ssa-sccvn.c (vn_lookup_simplify_result): Guard against
+ constants before looking up avail.
+
+2018-08-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/87099
+ * calls.c (maybe_warn_nonstring_arg): Punt early if
+ warn_stringop_overflow is zero. Don't call get_range_strlen
+ on 3rd argument, keep iterating until lenrng[1] is INTEGER_CST.
+ Swap comparison operands to have constants on rhs. Only use
+ lenrng[1] if non-NULL and INTEGER_CST. Don't uselessly
+ increment lenrng[0].
+
+2018-08-28 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-ssa-sccvn.c (fully_constant_vn_reference_p): Fix unguarded
+ use of tree_to_shwi. Remove duplicated test for the size being
+ a whole number of bytes.
+
+2018-08-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87117
+ * tree-ssa-sccvn.c (eliminate_dom_walker::eliminate_cleanup):
+ Handle removed stmt without LHS (GIMPLE_NOP).
+
+2018-08-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87117
+ * tree-ssa-sccvn.c (fully_constant_vn_reference_p): Exclude
+ void which is is_gimple_reg_type by checking for COMPLETE_TYPE_P.
+
+2018-08-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87117
+ * tree-ssa-pre.c (compute_avail): Do not make expressions
+ with predicated values available.
+ (get_expr_value_id): Assert we do not run into predicated value
+ expressions.
+
+2018-08-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87117
+ * tree-ssa-operands.c (add_stmt_operand): STRING_CST may
+ get virtual operands.
+ (get_expr_operands): Handle STRING_CST like other decls.
+
+2018-08-28 Martin Liska <mliska@suse.cz>
+
+ * tree.h: Update documentation of fndecl_built_in_p
+ functions.
+
+
+2018-08-27 Jeff Law <law@redhat.com>
+ PR tree-optimization/87110
+ * tree-ssa-dse.c (compute_trims): Handle non-constant
+ TYPE_SIZE_UNIT.
+
+2018-08-27 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/86914
+ * tree-ssa-strlen.c (maybe_set_strlen_range): Avoid MEM_REF.
+
+2018-08-27 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/87112
+ * builtins.c (expand_builtin_strnlen): Convert c_strlen result to
+ the type of the bound argument.
+
+2018-08-27 Jeff Law <law@redhat.com>
+
+ * tree-ssa-dse.c (compute_trims): Handle case where the reference's
+ type does not have a TYPE_SIZE_UNIT.
+
+2018-08-27 Steve Ellcey <sellcey@cavium.com>
+
+ * config/aarch64/aarch64-speculation.cc: Replace include of cfg.h
+ with include of backend.h.
+
+2018-08-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/86927
+ * tree-vect-loop.c (vect_create_epilog_for_reduction): Properly
+ use const cond reduction code.
+
+2018-08-27 Alexander Monakov <amonakov@ispras.ru>
+
+ PR tree-optimization/85758
+ * match.pd ((X & Y) ^ Y): Add :s qualifier to inner expression.
+
+2018-08-27 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/87091
+ * diagnostic-show-locus.c (class layout_range): Update for
+ conversion of show_caret_p to a tri-state.
+ (layout_range::layout_range): Likewise.
+ (make_range): Likewise.
+ (layout::maybe_add_location_range): Likewise.
+ (layout::should_print_annotation_line_p): Don't show annotation
+ lines for ranges that are SHOW_LINES_WITHOUT_RANGE.
+ (layout::get_state_at_point): Update for conversion of
+ show_caret_p to a tri-state. Bail out early for
+ SHOW_LINES_WITHOUT_RANGE, so that such ranges don't affect
+ underlining or source colorization.
+ (gcc_rich_location::add_location_if_nearby): Update for conversion
+ of show_caret_p to a tri-state.
+ (selftest::test_one_liner_multiple_carets_and_ranges): Likewise.
+ (selftest::test_one_liner_fixit_replace_equal_secondary_range):
+ Likewise.
+ (selftest::test_one_liner_labels): Likewise.
+ * gcc-rich-location.c (gcc_rich_location::add_expr): Update for
+ conversion of show_caret_p to a tri-state.
+ * pretty-print.c (text_info::set_location): Likewise.
+ * pretty-print.h (text_info::set_location): Likewise.
+ * substring-locations.c (format_warning_n_va): Likewise.
+ * tree-diagnostic.c (default_tree_printer): Likewise.
+ * tree-pretty-print.c (newline_and_indent): Likewise.
+
+2018-08-27 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/87091
+ * diagnostic-show-locus.c (get_line_span_for_fixit_hint): Show the
+ line above for line-insertion fix-it hints.
+ (selftest::test_fixit_insert_containing_newline): Update the
+ expected results, and add a test with line-numbering enabled.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/86962
+ * sanopt.c (sanitize_rewrite_addressable_params): Ignore
+ params with DECL_HAS_VALUE_EXPR_P.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ * config/i386/i386.c (ix86_expand_set_or_movmem): Dump
+ selected expansion strategy.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ * builtins.h (is_builtin_fn): Remove and fndecl_built_in_p.
+ * builtins.c (is_builtin_fn): Likewise.
+ * attribs.c (diag_attr_exclusions): Use new function
+ fndecl_built_in_p and remove check for FUNCTION_DECL if
+ possible.
+ (builtin_mathfn_code): Likewise.
+ (fold_builtin_expect): Likewise.
+ (fold_call_expr): Likewise.
+ (fold_builtin_call_array): Likewise.
+ (fold_call_stmt): Likewise.
+ (set_builtin_user_assembler_name): Likewise.
+ (is_simple_builtin): Likewise.
+ * calls.c (gimple_alloca_call_p): Likewise.
+ (maybe_warn_nonstring_arg): Likewise.
+ * cfgexpand.c (expand_call_stmt): Likewise.
+ * cgraph.c (cgraph_update_edges_for_call_stmt_node): Likewise.
+ (cgraph_edge::verify_corresponds_to_fndecl): Likewise.
+ (cgraph_node::verify_node): Likewise.
+ * cgraphclones.c (build_function_decl_skip_args): Likewise.
+ (cgraph_node::create_clone): Likewise.
+ * config/arm/arm.c (arm_insert_attributes): Likewise.
+ * config/i386/i386.c (ix86_gimple_fold_builtin): Likewise.
+ * dse.c (scan_insn): Likewise.
+ * expr.c (expand_expr_real_1): Likewise.
+ * fold-const.c (operand_equal_p): Likewise.
+ (fold_binary_loc): Likewise.
+ * gimple-fold.c (gimple_fold_stmt_to_constant_1): Likewise.
+ * gimple-low.c (lower_stmt): Likewise.
+ * gimple-pretty-print.c (dump_gimple_call): Likewise.
+ * gimple-ssa-warn-restrict.c (wrestrict_dom_walker::check_call):
+ Likewise.
+ * gimple.c (gimple_build_call_from_tree): Likewise.
+ (gimple_call_builtin_p): Likewise.
+ (gimple_call_combined_fn): Likewise.
+ * gimplify.c (gimplify_call_expr): Likewise.
+ (gimple_boolify): Likewise.
+ (gimplify_modify_expr): Likewise.
+ (gimplify_addr_expr): Likewise.
+ * hsa-gen.c (gen_hsa_insns_for_call): Likewise.
+ * ipa-cp.c (determine_versionability): Likewise.
+ * ipa-fnsummary.c (compute_fn_summary): Likewise.
+ * ipa-param-manipulation.c (ipa_modify_formal_parameters): Likewise.
+ * ipa-split.c (visit_bb): Likewise.
+ (split_function): Likewise.
+ * ipa-visibility.c (cgraph_externally_visible_p): Likewise.
+ * lto-cgraph.c (input_node): Likewise.
+ * lto-streamer-out.c (write_symbol): Likewise.
+ * omp-low.c (setjmp_or_longjmp_p): Likewise.
+ (lower_omp_1): Likewise.
+ * predict.c (strip_predict_hints): Likewise.
+ * print-tree.c (print_node): Likewise.
+ * symtab.c (symtab_node::output_to_lto_symbol_table_p): Likewise.
+ * trans-mem.c (is_tm_irrevocable): Likewise.
+ (is_tm_load): Likewise.
+ (is_tm_simple_load): Likewise.
+ (is_tm_store): Likewise.
+ (is_tm_simple_store): Likewise.
+ (is_tm_abort): Likewise.
+ (tm_region_init_1): Likewise.
+ * tree-call-cdce.c (gen_shrink_wrap_conditions): Likewise.
+ * tree-cfg.c (verify_gimple_call): Likewise.
+ (move_stmt_r): Likewise.
+ (stmt_can_terminate_bb_p): Likewise.
+ * tree-eh.c (lower_eh_constructs_2): Likewise.
+ * tree-if-conv.c (if_convertible_stmt_p): Likewise.
+ * tree-inline.c (remap_gimple_stmt): Likewise.
+ (copy_bb): Likewise.
+ (estimate_num_insns): Likewise.
+ (fold_marked_statements): Likewise.
+ * tree-sra.c (scan_function): Likewise.
+ * tree-ssa-ccp.c (surely_varying_stmt_p): Likewise.
+ (optimize_stack_restore): Likewise.
+ (pass_fold_builtins::execute): Likewise.
+ * tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Likewise.
+ (mark_all_reaching_defs_necessary_1): Likewise.
+ * tree-ssa-dom.c (dom_opt_dom_walker::optimize_stmt): Likewise.
+ * tree-ssa-forwprop.c (simplify_builtin_call): Likewise.
+ (pass_forwprop::execute): Likewise.
+ * tree-ssa-loop-im.c (stmt_cost): Likewise.
+ * tree-ssa-math-opts.c (pass_cse_reciprocals::execute): Likewise.
+ * tree-ssa-sccvn.c (fully_constant_vn_reference_p): Likewise.
+ * tree-ssa-strlen.c (get_string_length): Likewise.
+ * tree-ssa-structalias.c (handle_lhs_call): Likewise.
+ (find_func_aliases_for_call): Likewise.
+ * tree-ssa-ter.c (find_replaceable_in_bb): Likewise.
+ * tree-stdarg.c (optimize_va_list_gpr_fpr_size): Likewise.
+ * tree-tailcall.c (find_tail_calls): Likewise.
+ * tree.c (need_assembler_name_p): Likewise.
+ (free_lang_data_in_decl): Likewise.
+ (get_call_combined_fn): Likewise.
+ * ubsan.c (is_ubsan_builtin_p): Likewise.
+ * varasm.c (incorporeal_function_p): Likewise.
+ * tree.h (DECL_BUILT_IN): Remove and replace with
+ fndecl_built_in_p.
+ (DECL_BUILT_IN_P): Transfort to fndecl_built_in_p.
+ (fndecl_built_in_p): New.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/86847
+ * tree-switch-conversion.c (switch_decision_tree::dump_case_nodes):
+ Dump also subtree probability.
+ (switch_decision_tree::do_jump_if_equal): New function.
+ (switch_decision_tree::emit_case_nodes): Handle special
+ situations in balanced tree that can be emitted much simpler.
+ Fix calculation of probabilities that happen in tree expansion.
+ * tree-switch-conversion.h (struct cluster): Add
+ is_single_value_p.
+ (struct simple_cluster): Likewise.
+ (struct case_tree_node): Add new function has_child.
+ (do_jump_if_equal): New.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ * tree-switch-conversion.c (bit_test_cluster::find_bit_tests):
+ Add new argument to bit_test_cluster constructor.
+ (bit_test_cluster::emit): Set bits really number of values
+ handlel by a test.
+ (bit_test_cluster::hoist_edge_and_branch_if_true): Add
+ probability argument.
+ * tree-switch-conversion.h (struct bit_test_cluster):
+ Add m_handles_entire_switch.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/86702
+ * tree-switch-conversion.c (jump_table_cluster::emit):
+ Make probabilities even for values in jump table
+ according to number of cases handled.
+ (switch_decision_tree::compute_cases_per_edge): Pass
+ argument to reset_out_edges_aux function.
+ (switch_decision_tree::analyze_switch_statement): Likewise.
+ * tree-switch-conversion.h (switch_decision_tree::reset_out_edges_aux):
+ Make it static.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ * cfgexpand.c (expand_asm_stmt): Use label_to_block and pass
+ cfun argument explicitly.
+ * gimple-pretty-print.c (dump_gimple_switch): Likewise.
+ * hsa-gen.c (gen_hsa_insns_for_switch_stmt): Use new
+ function gimple_switch_default_bb.
+ (convert_switch_statements):
+ (expand_builtins):
+ * ipa-fnsummary.c (set_switch_stmt_execution_predicate):
+ * stmt.c (label_to_block_fn): Use label_to_block and pass
+ cfun argument explicitly and use gimple_switch_label_bb.
+ (expand_case): Likewise.
+ * tree-cfg.c (lower_phi_internal_fn): Use label_to_block and pass
+ cfun argument explicitly. Likewise.
+ (make_edges_bb): Likewise.
+ (make_cond_expr_edges): Likewise.
+ (get_cases_for_edge): Likewise.
+ (make_gimple_switch_edges): Likewise.
+ (label_to_block_fn): Likewise.
+ (label_to_block): Likewise.
+ (make_goto_expr_edges): Likewise.
+ (make_gimple_asm_edges): Likewise.
+ (main_block_label): Likewise.
+ (group_case_labels_stmt): Likewise.
+ (find_taken_edge_computed_goto): Likewise.
+ (find_taken_edge_switch_expr): Likewise.
+ (gimple_verify_flow_info): Likewise.
+ (gimple_redirect_edge_and_branch): Likewise.
+ (gimple_switch_label_bb): New function.
+ (gimple_switch_default_bb): Likewise.
+ (gimple_switch_edge): Likewise.
+ (gimple_switch_default_edge): Likewise.
+ * tree-cfg.h (label_to_block_fn): Remove and replace ...
+ (label_to_block): ... with this.
+ (gimple_switch_label_bb): New.
+ (gimple_switch_default_bb): Likewise.
+ (gimple_switch_edge): Likewise.
+ (gimple_switch_default_edge): Likewise.
+ * tree-cfgcleanup.c (convert_single_case_switch): Use
+ new gimple functions and pass new argument to label_to_block.
+ (cleanup_control_flow_bb):
+ * tree-eh.c (make_eh_dispatch_edges): Use label_to_block and pass
+ cfun argument explicitly.
+ (make_eh_edges): Likewise.
+ (redirect_eh_dispatch_edge): Likewise.
+ (lower_resx): Likewise.
+ (lower_eh_dispatch): Likewise.
+ (maybe_remove_unreachable_handlers): Likewise.
+ (unsplit_eh): Likewise.
+ (cleanup_empty_eh): Likewise.
+ (verify_eh_edges): Likewise.
+ (verify_eh_dispatch_edge): Likewise.
+ * tree-ssa-dom.c (record_edge_info): Likewise.
+ * tree-ssa-forwprop.c (simplify_gimple_switch_label_vec): Likewise.
+ * tree-ssa-threadedge.c (thread_around_empty_blocks): Likewise.
+ (thread_through_normal_block): Likewise.
+ * tree-ssa-uncprop.c (associate_equivalences_with_edges): Likewise.
+ * tree-ssa-uninit.c (convert_control_dep_chain_into_preds):
+ * tree-switch-conversion.c (switch_conversion::collect): Use new
+ gimple functions.
+ (switch_conversion::check_final_bb): Likewise.
+ (switch_conversion::gather_default_values): Pass new argument
+ to label_to_block.
+ (switch_conversion::build_constructors): Likewise.
+ (switch_decision_tree::compute_cases_per_edge): Use new
+ gimple_switch_edge function.
+ (switch_decision_tree::analyze_switch_statement): Pass new argument
+ to label_to_block.
+ (switch_decision_tree::try_switch_expansion): Use
+ gimple_switch_default_edge.
+ * tree-vrp.c (find_switch_asserts): Pass new argument
+ to label_to_block.
+ * vr-values.c (vr_values::vrp_visit_switch_stmt): Likewise.
+ (vr_values::simplify_switch_using_ranges): Likewise.
+
+2018-08-27 Richard Biener <rguenther@suse.de>
+
+ * cfganal.h (rev_post_order_and_mark_dfs_back_seme): Declare.
+ * cfganal.c (rev_post_order_and_mark_dfs_back_seme): New function.
+
+ * tree-ssa-sccvn.h (struct vn_pval): New structure.
+ (struct vn_nary_op_s): Add unwind_to member. Add
+ predicated_values flag and put result into a union together
+ with a linked list of vn_pval.
+ (struct vn_ssa_aux): Add name member to make maintaining
+ a map of SSA name to vn_ssa_aux possible. Remove no longer
+ needed info, dfsnum, low, visited, on_sccstack, use_processed
+ and range_info_anti_range_p members.
+ (run_scc_vn, vn_eliminate, free_scc_vn, vn_valueize): Remove.
+ (do_rpo_vn, run_rpo_vn, eliminate_with_rpo_vn, free_rpo_vn):
+ New functions.
+ (vn_valueize): New global.
+ (vn_context_bb): Likewise.
+ (VN_INFO_RANGE_INFO, VN_INFO_ANTI_RANGE_P, VN_INFO_RANGE_TYPE,
+ VN_INFO_PTR_INFO): Remove.
+ * tree-ssa-sccvn.c: ... (rewrite)
+ (pass_fre::execute): For -O2+ initialize loops and run
+ RPO VN in optimistic mode (iterating). For -O1 and -Og
+ run RPO VN in non-optimistic mode.
+ * params.def (PARAM_SCCVN_MAX_SCC_SIZE): Remove.
+ (PARAM_RPO_VN_MAX_LOOP_DEPTH): Add.
+ * doc/invoke.texi (sccvn-max-scc-size): Remove.
+ (rpo-vn-max-loop-depth): Document.
+ * tree-ssa-alias.c (walk_non_aliased_vuses): Stop walking
+ when valuezing the VUSE signals we walked out of the region.
+ * tree-ssa-pre.c (phi_translate_1): Ignore predicated values.
+ (phi_translate): Set VN context block to use for availability
+ lookup.
+ (compute_avail): Likewise.
+ (pre_valueize): New function.
+ (pass_pre::execute): Adjust to the RPO VN API.
+
+ * tree-ssa-loop-ivcanon.c: Include tree-ssa-sccvn.h.
+ (propagate_constants_for_unrolling): Remove.
+ (tree_unroll_loops_completely): Perform value-numbering
+ on the unrolled bodies loop parent.
+
+2018-08-27 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-pre.c (compute_antic): Re-use inverted postorder
+ for partial antic compute.
+
+2018-08-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/87065
+ * combine.c (simplify_if_then_else): Formatting fix.
+ (if_then_else_cond): Guard MULT optimization with SCALAR_INT_MODE_P
+ check.
+ (known_cond): Don't return const_true_rtx for vector modes. Use
+ CONST0_RTX instead of const0_rtx. Formatting fixes.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/87069
+ * gcov.c (process_file): Record files already processed
+ and warn about a file being processed multiple times.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ PR driver/83193
+ * config/aarch64/aarch64.c (aarch64_override_options_internal):
+ Set default values for x_aarch64_*_string strings.
+ * config/aarch64/aarch64.opt: Remove --{march,mcpu,mtune}==
+ prefix. For -mabi do not print '=ABI' in help and use
+ <option_value> format for -msve-vector-bits and -moverride
+ options.
+
+2018-08-26 Jeff Law <law@redhat.com>
+
+ * config/mips/frame-header-opt.c: Include "backend.h" rather than
+ "cfg.h"
+
+2018-08-26 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87029, Implement -Wredundant-move.
+ * doc/invoke.texi: Document -Wredundant-move.
+
+2018-08-25 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/87059
+ * builtins.c (expand_builtin_strncmp): Convert MIN_EXPR operand
+ to the same type as the other.
+ * fold-const.c (fold_binary_loc): Assert expectation.
+
+2018-08-25 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.c (machopic_legitimize_pic_address): Clean up
+ extraneous parentheses, dead code section and formatting.
+
+2018-08-24 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/87091
+ * diagnostic-show-locus.c (layout::layout): Ensure the margin is
+ wide enough for jumps in the line-numbering to be visible.
+ (layout::print_gap_in_line_numbering): New member function.
+ (layout::calculate_line_spans): When using line numbering, merge
+ line spans that are only 1 line apart.
+ (diagnostic_show_locus): When printing line numbers, show gaps in
+ line numbering directly, rather than printing headers.
+ (selftest::test_diagnostic_show_locus_fixit_lines): Add test of
+ line-numbering with multiple line spans.
+ (selftest::test_fixit_insert_containing_newline_2): Add test of
+ line-numbering, in which the spans are close enough to be merged.
+
+2018-08-24 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-ssa-evrp-analyze.c (set_ssa_range_info): Pass value_range
+ to range_includes_zero_p. Do not special case VR_ANTI_RANGE.
+ * tree-vrp.c (range_is_nonnull): Remove.
+ (range_includes_zero_p): Accept value_range instead of min/max.
+ (extract_range_from_binary_expr_1): Do not early bail on
+ POINTER_PLUS_EXPR.
+ Use range_includes_zero_p instead of range_is_nonnull.
+ (extract_range_from_unary_expr): Use range_includes_zero_p instead
+ of range_is_nonnull.
+ (vrp_meet_1): Pass value_range to range_includes_zero_p. Do not
+ special case VR_ANTI_RANGE.
+ (vrp_finalize): Same.
+ * tree-vrp.h (range_includes_zero_p): Pass value_range as argument
+ instead of min/max.
+ (range_is_nonnull): Remove.
+ * vr-values.c (vrp_stmt_computes_nonzero): Use
+ range_includes_zero_p instead of range_is_nonnull.
+ (extract_range_basic): Pass value_range to range_includes_zero_p
+ instead of range_is_nonnull.
+
+2018-08-24 Uros Bizjak <ubizjak@gmail.com>
+
+ * emit-rtl.c (init_emit_once): Do not emit MODE_POINTER_BOUNDS RTXes.
+ * emit-rtl.h (rtl_data): Remove return_bnd.
+ * explow.c (trunc_int_for_mode): Do not handle POINTER_BOUNDS_MODE_P.
+ * function.c (diddle_return_value): Do not handle crtl->return_bnd.
+ * genmodes.c (complete_mode): Do not handle MODE_POINTER_BOUNDS.
+ (POINTER_BOUNDS_MODE): Remove definition.
+ (make_pointer_bounds_mode): Remove.
+ (get_mode_class): Do not handle MODE_POINTER_BOUNDS.
+ * machmode.h (POINTER_BOUNDS_MODE_P): Remove definition.
+ (scalare_mode::includes_p): Do not handle MODE_POINTER_BOUNDS.
+ * mode-classes.def: Do not define MODE_POINTER_BOUNDS.
+ * stor-layout.c (int_mode_for_mode): Do not handle MODE_POINTER_BOUNDS.
+ * tree-core.h (enum tree_index): Remove TI_POINTER_BOUNDS_TYPE.
+ * varasm.c (output_constant_pool_2): Do not handle MODE_POINTER_BOUNDS.
+
+ * config/i386/i386-modes.def (BND32, BND64): Remove.
+ * config/i386/i386.c (dbx_register_map): Remove bound registers.
+ (dbx64_register_map): Ditto.
+ (svr4_dbx_register_map): Ditto.
+ (indirect_thunk_bnd_needed): Remove.
+ (indirect_thunks_bnd_used): Ditto.
+ (indirect_return_bnd_needed): Ditto.
+ (indirect_return_via_cx_bnd): Ditto.
+ (enum indirect_thunk_prefix): Remove indirect_thunk_prefix_bnd.
+ (indirect_thunk_name): Remove handling of indirect_thunk_prefix_bnd.
+ (output_indirect_thunk): Ditto. Remove need_prefix argument.
+ (output_indirect_thunk_function): Remove handling of
+ indirect_return_bnd_needed, indirect_return_via_cx_bnd,
+ indirect_thunk_bnd_needed and indirect_thunks_bnd_used variables.
+ (ix86_save_reg): Remove handling of crtl->return_bnd.
+ (ix86_legitimate_constant_p): Remove handling of POINTER_BOUNDS_MODE_P.
+ (ix86_print_operand_address_as): Remove handling of UNSPEC_BNDMK_ADDR
+ and UNSPEC_BNDLX_ADDR.
+ (ix86_output_indirect_branch_via_reg): Remove handling of
+ indirect_thunk_prefix_bnd.
+ (ix86_output_indirect_branch_via_push): Ditto.
+ (ix86_output_function_return): Ditto.
+ (ix86_output_indirect_function_return): Ditto.
+ (avoid_func_arg_motion): Do not handle UNSPEC_BNDSTX.
+ * config/i386/i386.h (FIXED_REGISTERS): Remove bound registers.
+ (CALL_USED_REGISTERS): Ditto.
+ (REG_ALLOC_ORDER): Update for removal of bound registers.
+ (HI_REGISTER_NAMES): Ditto.
+ * config/i386/i386.md (UNSPEC_BNDMK, UNSPEC_BNDMK_ADDR, UNSPEC_BNDSTX)
+ (UNSPEC_BNDLDX, UNSPEC_BNDLDX_ADDR, UNSPEC_BNDCL, UNSPEC_BNDCU)
+ (UNSPEC_BNDCN, UNSPEC_MPX_FENCE): Remove.
+ (BND0_REG, BND1_REG, BND2_REG, BND3_REG): Remove
+ (FIRST_PSEUDO_REG): Update.
+ (BND): Remove mode iterator.
+ * config/i386/predicates.md (bnd_mem_operator): Remove.
+
+2018-08-24 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-stmts.c (vectorizable_bswap): Handle variable-length
+ vectors.
+
+2018-08-24 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-slp.c (vect_transform_slp_perm_load): Separate out
+ the case in which the permute needs only a single element and
+ repeats for every vector of the result. Extend that case to
+ handle variable-length vectors.
+ * tree-vect-stmts.c (vectorizable_load): Update accordingly.
+
+2018-08-24 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR debug/79342
+ * dwarf2out.c (save_macinfo_strings): Call set_indirect_string
+ on DW_MACINFO_start_file for -gsplit-dwarf -g3.
+
+2018-08-24 Richard Biener <rguenther@suse.de>
+
+ * cfg.h (struct control_flow_graph): Add edge_flags_allocated and
+ bb_flags_allocated members.
+ (auto_flag): New RAII class for allocating flags.
+ (auto_edge_flag): New RAII class for allocating edge flags.
+ (auto_bb_flag): New RAII class for allocating bb flags.
+ * cfgloop.c (verify_loop_structure): Allocate temporary edge
+ flag dynamically.
+ * cfganal.c (dfs_enumerate_from): Remove use of visited sbitmap
+ in favor of temporarily allocated BB flag.
+ * hsa-brig.c: Re-order includes.
+ * hsa-dump.c: Likewise.
+ * hsa-regalloc.c: Likewise.
+ * print-rtl.c: Likewise.
+ * profile-count.c: Likewise.
+
+2018-08-24 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR target/86989
+ * config/rs6000/rs6000.c (toc_relative_expr_p): Check that the base is
+ the TOC register.
+
+2018-08-24 Aldy Hernandez <aldyh@redhat.com>
+
+ PR 87073/bootstrap
+ * wide-int-range.cc (wide_int_range_div): Do not ignore result
+ from wide_int_range_multiplicative_op.
+
+2018-08-23 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ * tree-vect-data-refs.c (vect_grouped_store_supported): Fix typo
+ "permutaion".
+
+2018-08-23 Giuliano Belinassi <giuliano.belinassi@usp.br>
+
+ * genmatch.c (parser::parse_operation): Fix typo 'exapnded'
+ to 'expanded'.
+
+2018-08-23 Alexander Monakov <amonakov@ispras.ru>
+
+ * tree-scalar-evolution.c (final_value_replacement_loop): Dump
+ full GENERIC expression used for replacement.
+
+2018-08-23 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-vrp.c (abs_extent_range): Remove.
+ (extract_range_into_wide_ints): Pass wide ints by reference.
+ (extract_range_from_binary_expr_1): Rewrite the *DIV_EXPR code.
+ Pass wide ints by reference in all calls to
+ extract_range_into_wide_ints.
+ * wide-int-range.cc (wide_int_range_div): New.
+ * wide-int-range.h (wide_int_range_div): New.
+ (wide_int_range_includes_zero_p): New.
+ (wide_int_range_zero_p): New.
+
+2018-08-23 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ * config/aarch64/aarch64.md (arches): New enum.
+ (arch): New enum attr.
+ (arch_enabled): New attr.
+ (enabled): Now uses arch_enabled only.
+ (simd, sve, fp16): Removed attribute.
+ (fp): Attr now defined in terms of 'arch'.
+ (*mov<mode>_aarch64, *movsi_aarch64, *movdi_aarch64, *movti_aarch64,
+ *movhf_aarch64, <optab><fcvt_target><GPF:mode>2,
+ <FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3,
+ <FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3): Merge 'fp' and 'simd'
+ attributes into 'arch'.
+ (*movsf_aarch64, *movdf_aarch64, *movtf_aarch64, *add<mode>3_aarch64,
+ subdi3, neg<mode>2, <optab><mode>3, one_cmpl<mode>2,
+ *<NLOGICAL:optab>_one_cmpl<mode>3, *xor_one_cmpl<mode>3,
+ *aarch64_ashl_sisd_or_int_<mode>3, *aarch64_lshr_sisd_or_int_<mode>3,
+ *aarch64_ashr_sisd_or_int_<mode>3, *aarch64_sisd_ushl): Convert use of
+ 'simd' attribute into 'arch'.
+ (load_pair_sw_<SX:mode><SX2:mode>, load_pair_dw_<DX:mode><DX2:mode>,
+ store_pair_sw_<SX:mode><SX2:mode>, store_pair_dw_<DX:mode><DX2:mode>):
+ Convert use of 'fp' attribute to 'arch'.
+ * config/aarch64/aarch64-simd.md (move_lo_quad_internal_<mode>,
+ move_lo_quad_internal_<mode>): (different modes) Merge 'fp' and 'simd'
+ into 'arch'.
+ (move_lo_quad_internal_be_<mode>, move_lo_quad_internal_be_<mode>):
+ (different modes) Merge 'fp' and 'simd' into 'arch'.
+ (*aarch64_combinez<mode>, *aarch64_combinez_be<mode>): Merge 'fp' and
+ 'simd' into 'arch'.
+
+2018-08-23 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR rtl-optimization/87026
+ * expmed.c (canonicalize_comparison): If we can no longer create
+ pseudoregisters, don't.
+
+2018-08-23 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/86951
+ * config/arm/arm-protos.h (arm_emit_speculation_barrier): New
+ prototype.
+ * config/arm/arm.c (speculation_barrier_libfunc): New static
+ variable.
+ (arm_init_libfuncs): Initialize it.
+ (arm_emit_speculation_barrier): New function.
+ * config/arm/arm.md (speculation_barrier): Call
+ arm_emit_speculation_barrier for architectures that do not have
+ DSB or ISB.
+ (speculation_barrier_insn): Only match on Armv7 or later.
+
+2018-08-23 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/87024
+ * tree-inline.c (copy_bb): Drop unused __builtin_va_arg_pack_len
+ calls.
+
+2018-08-23 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_evpc_sve_tbl): Fix handling
+ of single-vector TBLs.
+ (aarch64_vectorize_vec_perm_const): Set one_vector_p when only
+ one input is given.
+
+2018-08-23 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR target/85910
+ * config/aarch64/aarch64.c (aarch64_expand_vec_perm_const_1): Fix
+ aarch64_evpc_tbl guard.
+
+2018-08-22 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * tree-ssa-dse.c (compute_trims): Avoid folding away undefined
+ behaviour.
+
+2018-08-22 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/87052
+ * tree-pretty-print.c (pretty_print_string): Add argument.
+ (dump_generic_node): Call to pretty_print_string with string size.
+
+2018-08-22 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR rtl-optimization/86771
+ * combine.c (try_combine): Do not allow splitting a resulting PARALLEL
+ of two SETs into those two SETs, one to be placed at i2, if that SETs
+ destination is modified between i2 and i3.
+
+2018-08-22 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/86725
+ * tree-vect-loop.c (vect_inner_phi_in_double_reduction_p): New
+ function.
+ (vect_analyze_scalar_cycles_1): Check it.
+
+2018-08-22 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/86725
+ * tree-vect-loop.c (vect_is_simple_reduction): When treating
+ an outer loop phi as a double reduction, make sure that the
+ single user of the phi result is an inner loop phi.
+
+2018-08-22 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-data-refs.c (vect_analyze_group_access_1): Convert
+ grouped stores with gaps to a strided group.
+
+2018-08-22 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-stmts.c (get_group_load_store_type)
+ (get_load_store_type): Only test STMT_VINFO_STRIDED_P for the
+ first statement in a group.
+
+2018-08-22 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.h (LINK_COMMAND_SPEC_A): Sync LTO options with
+ the sequence used in gcc/gcc.c.
+
+2018-08-22 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR other/704
+ * gcc-ar.c (main): Don’t try to invoke the plug-in if we’re not
+ building it.
+
+2018-08-22 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin10.h (LINK_GCC_C_SEQUENCE_SPEC): Adjust to use the
+ Darwin10-specific unwinder-shim.
+ * config/darwin12.h (LINK_GCC_C_SEQUENCE_SPEC): Remove.
+ * config/rs6000/darwin.h (DARWIN_CRT1_SPEC, DARWIN_DYLIB1_SPEC):
+ New to cater for Darwin10 Rosetta.
+
+2018-08-22 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/i386/i386.c (ix86_output_addr_diff_elt): Move the MACH-O
+ specific test before the one for HAVE_AS_GOTOFF_IN_DATA.
+
+2018-08-22 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR bootstrap/81033
+ PR target/81733
+ PR target/52795
+ * gcc/dwarf2out.c (FUNC_SECOND_SECT_LABEL): New.
+ (dwarf2out_switch_text_section): Generate a local label for the
+ second function sub-section and apply it as the second FDE start
+ label.
+ * gcc/final.c (final_scan_insn_1): Emit second FDE label after the
+ second sub-section start.
+
+2018-08-22 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/86988
+ * tree-vrp.c (vrp_prop::check_mem_ref): Bail out on VLAs.
+
+2018-08-22 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/86945
+ * tree-cfg.c (generate_range_test): Use unsigned arithmetic.
+
+2018-08-22 Alexandre Oliva <oliva@adacore.com>
+
+ * config/rs6000/rs6000.c (SMALL_DATA_RELOC, SMALL_DATA_REG): Add
+ a comment about how uses of r2 for .sdata2 come about.
+
+2018-08-22 Alexandre Oliva <aoliva@redhat.com>
+
+ * tree-ssa-reassoc.c (is_reassociable_op): Fix cut&pasto.
+
+2018-08-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/86981, Implement -Wpessimizing-move.
+ * doc/invoke.texi: Document -Wpessimizing-move.
+
+2018-08-21 Jan Hubicka <jh@suse.cz>
+
+ * tree.c (find_decls_types_r): Do not check for redundant typedefs.
+ * tree.h (is_redundant_typedef): Remove.
+ * dwarf2out.c (is_redundant_typedef): Turn into static function.
+
+2018-08-21 Jan Hubicka <jh@suse.cz>
+
+ * tree.c (free_lang_data_in_decl): Remove types from DECL_CONTEXT
+ when possible.
+
+2018-08-21 Tamar Christina <tamar.christina@arm.com>
+
+ * expmed.c (extract_low_bits): Reject invalid subregs early.
+
+2018-08-21 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR middle-end/86121
+ * tree-ssa-strlen.c (adjust_last_stmt): Avoid folding away undefined
+ behaviour.
+
+2018-08-21 Rasmus Villemoes <rv@rasmusvillemoes.dk>
+
+ * config/vxworks.h: Guard vxworks_asm_out_constructor and
+ vxworks_asm_out_destructor by !HAVE_INITFINI_ARRAY_SUPPORT
+ * config/vxworks.c: Likewise.
+
+2018-08-21 Rasmus Villemoes <rv@rasmusvillemoes.dk>
+
+ * config/vxworks.c: Set targetm.have_ctors_dtors
+ if HAVE_INITFINI_ARRAY_SUPPORT.
+ * config/vxworks.h: Set SUPPORTS_INIT_PRIORITY
+ if HAVE_INITFINI_ARRAY_SUPPORT.
+
+2018-08-21 Rasmus Villemoes <rv@rasmusvillemoes.dk>
+
+ * config/vxworks.h: Add $(WIND_BASE)/target/h/wrn/coreip to
+ default search path for VxWorks < 7.
+
+2018-08-21 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * gimple-ssa-sprintf.c (decl_constant_value): Remove.
+ (get_format_string): Refer to c_getstr.
+
+2018-08-21 Tom de Vries <tdevries@suse.de>
+
+ * cgraph.h (debuginfo_early_init, debuginfo_init, debuginfo_fini)
+ (debuginfo_start, debuginfo_stop, debuginfo_early_start)
+ (debuginfo_early_stop): Declare.
+ * cgraphunit.c (debuginfo_early_init, debuginfo_init, debuginfo_fini)
+ (debuginfo_start, debuginfo_stop, debuginfo_early_start)
+ (debuginfo_early_stop): New function.
+ (symbol_table::finalize_compilation_unit): Call debuginfo_early_start
+ and debuginfo_early_stop.
+ * dwarf2out.c (dwarf2out_finish, dwarf2out_early_finish): Dump dwarf.
+ * toplev.c (compile_file): Call debuginfo_start and debuginfo_stop.
+ (general_init): Call debuginfo_early_init.
+ (finalize): Call debuginfo_fini.
+ (do_compile): Call debuginfo_init.
+ * doc/invoke.texi (@gccoptlist): Add -fdump-debug and
+ -fdump-early-debug.
+ (@item -fdump-debug, @item -fdump-earlydebug): Add.
+
+2018-08-21 Tom de Vries <tdevries@suse.de>
+
+ * dwarf2out.c (print_dw_val, print_loc_descr, print_die): Handle
+ flag_dump_noaddr and flag_dump_unnumbered.
+
+2018-08-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * wide-int-range.cc (wide_int_range_abs): New.
+ (wide_int_range_order_set): Rename from wide_int_range_min_max.
+ * wide-int-range.h (wide_int_range_abs): New.
+ (wide_int_range_min_max): New.
+ * tree-vrp.c (extract_range_from_unary_expr): Rewrite ABS_EXPR
+ case to call wide_int_range_abs.
+ Rewrite MIN/MAX_EXPR to call wide_int_range_min_max.
+ (extract_range_from_abs_expr): Delete.
+
+2018-08-20 Michael Meissner <meissner@linux.ibm.com>
+
+ PR target/87033
+ * config/rs6000/rs6000.md (extendsi<mode>2): Change constraints
+ from 'Y' to 'YZ' to enable the LWAX instruction to be generated
+ for indexed loads.
+
+2018-08-20 Nathan Sidwell <nathan@acm.org>
+ Jeff Law <law@redhat.com>
+
+ * config/s390/s390-c (s390_macro_to_expand): Use cpp_macro_p.
+ * config/spu/spu-c.c (spu_macro_to_expand): Likewise.
+
+2018-08-20 David Malcolm <dmalcolm@redhat.com>
+
+ PR other/84889
+ * attribs.c (diag_attr_exclusions): Add auto_diagnostic_group instance.
+ (decl_attributes): Likewise.
+ * calls.c (maybe_warn_nonstring_arg): Add auto_diagnostic_group
+ instance.
+ * cgraphunit.c (maybe_diag_incompatible_alias): Likewise.
+ * diagnostic-core.h (class auto_diagnostic_group): New class.
+ * diagnostic.c (diagnostic_initialize): Initialize the new fields.
+ (diagnostic_report_diagnostic): Handle the first diagnostics within
+ a group.
+ (emit_diagnostic): Add auto_diagnostic_group instance.
+ (inform): Likewise.
+ (inform_n): Likewise.
+ (warning): Likewise.
+ (warning_at): Likewise.
+ (warning_n): Likewise.
+ (pedwarn): Likewise.
+ (permerror): Likewise.
+ (error): Likewise.
+ (error_n): Likewise.
+ (error_at): Likewise.
+ (sorry): Likewise.
+ (fatal_error): Likewise.
+ (internal_error): Likewise.
+ (internal_error_no_backtrace): Likewise.
+ (auto_diagnostic_group::auto_diagnostic_group): New ctor.
+ (auto_diagnostic_group::~auto_diagnostic_group): New dtor.
+ * diagnostic.h (struct diagnostic_context): Add fields
+ "diagnostic_group_nesting_depth",
+ "diagnostic_group_emission_count", "begin_group_cb",
+ "end_group_cb".
+ * gimple-ssa-isolate-paths.c (find_implicit_erroneous_behavior):
+ Add auto_diagnostic_group instance(s).
+ (find_explicit_erroneous_behavior): Likewise.
+ * gimple-ssa-warn-alloca.c (pass_walloca::execute): Likewise.
+ * gimple-ssa-warn-restrict.c (maybe_diag_offset_bounds): Likewise.
+ * gimplify.c (warn_implicit_fallthrough_r): Likewise.
+ (gimplify_va_arg_expr): Likewise.
+ * hsa-gen.c (HSA_SORRY_ATV): Likewise.
+ (HSA_SORRY_AT): Likewise.
+ * ipa-devirt.c (compare_virtual_tables): Likewise.
+ (warn_odr): Likewise.
+ * multiple_target.c (expand_target_clones): Likewise.
+ * opts-common.c (cmdline_handle_error): Likewise.
+ * reginfo.c (globalize_reg): Likewise.
+ * substring-locations.c (format_warning_n_va): Likewise.
+ * tree-inline.c (expand_call_inline): Likewise.
+ * tree-ssa-ccp.c (pass_post_ipa_warn::execute): Likewise.
+ * tree-ssa-loop-niter.c
+ (do_warn_aggressive_loop_optimizations): Likewise.
+ * tree-ssa-uninit.c (warn_uninit): Likewise.
+ * tree.c (warn_deprecated_use): Likewise.
+
+2018-08-20 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/87014
+ * config/i386/i386.md (eh_return): Always update EH return
+ address in word_mode.
+
+2018-08-20 Chung-Lin Tang <cltang@codesourcery.com>
+
+ * targhooks.c (std_gimplify_va_arg_expr): Properly handle case of when
+ TARGET_SPLIT_COMPLEX_ARG is defined.
+
+2018-08-20 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * expr.c (store_field): Change gcc_assert to gcc_checking_assert.
+
+2018-08-20 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR target/86984
+ * expr.c (expand_assignment): Assert that bitpos is positive.
+ (store_field): Likewise
+ (expand_expr_real_1): Make sure that bitpos is positive.
+ * config/alpha/alpha.h (CONSTANT_ADDRESS_P): Avoid signed
+ integer overflow.
+
+2018-08-20 Nathan Sidwell <nathan@acm.org>
+
+ * Makefile.in (CPP_ID_DATA_H): Delete.
+ (CPP_INTERNAL_H): Don't add it.
+ (GTFILES): Replace CPP_ID_DATA_H with CPPLIB_H.
+ * gengtype.c (open_base_files): Replace cpp-id-data.h with cpplib.h
+
+2018-08-20 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/78655
+ * tree-vrp.c (extract_range_from_binary_expr_1): Make
+ pointer + offset nonnull if either operand is nonnull work.
+
+2018-08-20 Tom de Vries <tdevries@suse.de>
+
+ * dwarf2out.c (add_scalar_info): Don't add reference to existing die
+ unless the referenced die describes the added property using
+ DW_AT_location or DW_AT_const_value. Fall back to exprloc case.
+ Otherwise, add a DW_AT_location to the referenced die.
+
+2018-08-19 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/86994
+ * config/i386/i386.c (ix86_rtx_costs) [case SET]: Check source for
+ register_operand when calling ix86_set_reg_reg_cost.
+ [case CONST_INT, case CONST, case LABEL_REF, case SYMBOL_REF]:
+ Set *total to 0 for operands that satisfy x86_64_immediate_operand
+ predicate and to 1 otherwise.
+
+2018-08-18 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.c (darwin_override_options): If -gsplit-dwarf is set,
+ emit a diagnostic that it is not supported and reset the option.
+ * config/darwin.h (DRIVER_SELF_SPECS): Note that gsplit-dwarf is not
+ supported and consume the option. (ASM_FINAL_SPEC): New.
+
+2018-08-17 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * doc/md.texi (Patterns): Use @ref instead of @xref in the middle of
+ a sentence.
+
+2018-08-17 Sandra Loosemore <sandra@codesourcery.com>
+
+ C-SKY port: Documentation
+
+ * doc/extend.texi (C-SKY Function Attributes): New section.
+ * doc/invoke.texi (Option Summary): Add C-SKY options.
+ (C-SKY Options): New section.
+ * doc/md.texi (Machine Constraints): Document C-SKY constraints.
+
+2018-08-17 Jojo <jijie_rong@c-sky.com>
+ Huibin Wang <huibin_wang@c-sky.com>
+ Sandra Loosemore <sandra@codesourcery.com>
+ Chung-Lin Tang <cltang@codesourcery.com>
+
+ C-SKY port: Backend implementation
+
+ * config/csky/*: New.
+ * common/config/csky/*: New.
+
+2018-08-17 Jojo <jijie_rong@c-sky.com>
+ Huibin Wang <huibin_wang@c-sky.com>
+ Sandra Loosemore <sandra@codesourcery.com>
+ Chung-Lin Tang <cltang@codesourcery.com>
+ Andrew Jenner <andrew@codesourcery.com>
+
+ C-SKY port: Configury
+
+ * config.gcc (csky-*-*): New.
+ * configure.ac: Add csky to targets for dwarf2 debug_line support.
+ * configure: Regenerated.
+
+2018-08-17 David Malcolm <dmalcolm@redhat.com>
+
+ * dump-context.h: Include "dumpfile.h".
+ (dump_context::dump_printf_va): Convert final param from va_list
+ to va_list *. Convert from ATTRIBUTE_PRINTF to
+ ATTRIBUTE_GCC_DUMP_PRINTF.
+ (dump_context::dump_printf_loc_va): Likewise.
+ * dumpfile.c: Include "stringpool.h".
+ (make_item_for_dump_printf_va): Delete.
+ (make_item_for_dump_printf): Delete.
+ (class dump_pretty_printer): New class.
+ (dump_pretty_printer::dump_pretty_printer): New ctor.
+ (dump_pretty_printer::emit_items): New member function.
+ (dump_pretty_printer::emit_any_pending_textual_chunks): New member
+ function.
+ (dump_pretty_printer::emit_item): New member function.
+ (dump_pretty_printer::stash_item): New member function.
+ (dump_pretty_printer::format_decoder_cb): New member function.
+ (dump_pretty_printer::decode_format): New member function.
+ (dump_context::dump_printf_va): Reimplement in terms of
+ dump_pretty_printer.
+ (dump_context::dump_printf_loc_va): Convert final param from va_list
+ to va_list *.
+ (dump_context::begin_scope): Reimplement call to
+ make_item_for_dump_printf.
+ (dump_printf): Update for change to dump_printf_va.
+ (dump_printf_loc): Likewise.
+ (selftest::test_capture_of_dump_calls): Convert "stmt" from
+ greturn * to gimple *. Add a test_decl. Add tests of dump_printf
+ with %T, %E, and %G.
+ * dumpfile.h (ATTRIBUTE_GCC_DUMP_PRINTF): New macro.
+ (dump_printf): Replace ATTRIBUTE_PRINTF_2 with
+ ATTRIBUTE_GCC_DUMP_PRINTF (2, 3).
+ (dump_printf_loc): Replace ATTRIBUTE_PRINTF_3 with
+ ATTRIBUTE_GCC_DUMP_PRINTF (3, 0).
+ * tree-vect-data-refs.c (vect_lanes_optab_supported_p): Convert
+ use of HOST_WIDE_INT_PRINT_DEC on unsigned HOST_WIDE_INT "count"
+ within a dump_printf_loc call to "%wu".
+ (vector_alignment_reachable_p): Merge two dump_printf[_loc] calls,
+ converting a use of HOST_WIDE_INT_PRINT_DEC to "%wd". Add a
+ missing space after "=".
+ * tree-vect-loop.c (vect_analyze_loop_2) Within a dump_printf
+ call, convert use of HOST_WIDE_INT_PRINT_DEC to "%wd".
+ * tree-vect-slp.c (vect_slp_bb): Within a dump_printf_loc call,
+ convert use of HOST_WIDE_INT_PRINT_UNSIGNED to "%wu".
+ * tree-vectorizer.c (try_vectorize_loop_1): Likewise. Remove
+ duplicate "vectorized" from message.
+
+2018-08-17 Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+ * config/arm/arm-builtins.c (arm_init_simd_builtin_types): Clear
+ polyNxK_t element's TYPE_STRING_FLAG.
+
+2018-08-17 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (*cbranch, *creturn): Name these patterns
+ (they were unnamed before). Fix comments.
+
+2018-08-17 Nathan Sidwell <nathan@acm.org>
+
+ * cppbuiltin.c: Include "cpplib.h", not "cpp-id-data.h".
+
+2018-08-17 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/86841
+ * wide-int-range.cc (wide_int_range_lshift): Use to_uhwi.
+
+2018-08-17 Martin Liska <mliska@suse.cz>
+
+ * common.opt: Remove Warn, Init and Report for options with
+ Ignore/Deprecated flag. Warning is done automatically for
+ Deprecated flags.
+ * config/i386/i386.opt: Likewise.
+ * config/ia64/ia64.opt: Likewise.
+ * config/rs6000/rs6000.opt: Likewise.
+ * cppbuiltin.c (define_builtin_macros_for_compilation_flags):
+ Remove usage of flag_check_pointer_bounds.
+ * lto-wrapper.c (merge_and_complain): Do not handle
+ OPT_fcheck_pointer_bounds.
+ (append_compiler_options): Likewise.
+ * opt-functions.awk: Do not handle Deprecated.
+ * optc-gen.awk: Check that Var, Report and Init are not
+ used for an option with Ignore/Deprecated flag.
+ * opts-common.c (decode_cmdline_option): Do not report
+ CL_ERR_DEPRECATED.
+ (read_cmdline_option): Report warning for OPT_SPECIAL_deprecated
+ options.
+ * opts.h (struct cl_option): Remove cl_deprecated flag.
+ (CL_ERR_DEPRECATED): Remove error enum value.
+
+2018-08-17 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/86505
+ * tree-inline.c (copy_bb): When inlining __builtin_va_arg_pack_len ()
+ across a va-arg-pack using call adjust its return value accordingly.
+
+2018-08-16 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/86853
+ * gimple-ssa-sprintf.c (struct format_result): Rename member.
+ (struct fmtresult): Add member and initialize it in ctors.
+ (format_character): Handle %C. Extend range to NUL. Set MAYFAIL.
+ (format_string): Handle %S the same as %ls. Set MAYFAIL.
+ (format_directive): Set POSUNDER4K when MAYFAIL is set.
+ (parse_directive): Handle %C same as %c.
+ (sprintf_dom_walker::compute_format_length): Adjust.
+ (is_call_safe): Adjust.
+
+2018-08-16 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * builtins.c (c_strlen): Add new parameter eltsize. Use it
+ for determining how to count the elements.
+ * builtins.h (c_strlen): Adjust prototype.
+ * expr.c (string_constant): Add new parameter mem_size.
+ Set *mem_size appropriately.
+ * expr.h (string_constant): Adjust protoype.
+ * gimple-fold.c (get_range_strlen): Add new parameter eltsize.
+ * gimple-fold.h (get_range_strlen): Adjust prototype.
+ * gimple-ssa-sprintf.c (get_string_length): Add new parameter eltsize.
+ (format_string): Call get_string_length with eltsize.
+
+2018-08-16 David Malcolm <dmalcolm@redhat.com>
+
+ * diagnostic.c (default_diagnostic_start_span_fn): Call pp_string
+ to emit the span, rather than setting it as the prefix.
+
+2018-08-16 David Malcolm <dmalcolm@redhat.com>
+
+ * diagnostic-show-locus.c (layout::start_annotation_line): Add
+ "margin_char" parameter, defaulting to space. Use it in place
+ of pp_space for the initial part of the margin.
+ (layout::print_leading_fixits): Use '+' when filling the margin
+ of line-insertion fix-it hints.
+
+2018-08-16 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (two unnamed define_insn and define_split):
+ Delete.
+
+2018-08-16 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/altivec.md: Don't set length attribute to the default
+ value.
+ * config/rs6000/darwin.md: Ditto.
+ * config/rs6000/dfp.md: Ditto.
+ * config/rs6000/htm.md: Ditto.
+ * config/rs6000/rs6000.md: Ditto.
+ * config/rs6000/sync.md: Ditto.
+ * config/rs6000/vsx.md: Ditto.
+
+2018-08-16 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/altivec.md: Don't set length attribute to the default
+ value, for branch instructions.
+ * config/rs6000/darwin.md: Ditto.
+ * config/rs6000/rs6000.md: Ditto.
+
+2018-08-16 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (length): Always define as const_int 4.
+ (unnamed conditional branch define_insn): Set length to 4 or 8
+ depending on offset.
+ (<bd>_<mode>): Similar, for alternative 0.
+ (<bd>tf_<mode>): Ditto.
+
+2018-08-16 Tamar Christina <tamar.christina@arm.com>
+
+ * expr.c (copy_blkmode_to_reg): Perform larger copies when safe.
+
+2018-08-16 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ * doc/rtl.texi: Replace old RTX class names with new names.
+
+
+2018-08-16 Vlad Lazar <vlad.lazar@arm.com>
+
+ * expmed.h (canonicalize_comparison): New declaration.
+ * expmed.c (canonicalize_comparison, equivalent_cmp_code): New function.
+ * expmed.c (emit_store_flag_1): Add call to canonicalize_comparison.
+ * optabs.c (prepare_cmp_insn): Likewise.
+ * rtl.h (unsigned_condition_p): New function which checks if a
+ comparison operator is unsigned.
+
+2018-08-16 Nathan Sidwell <nathan@acm.org>
+
+ * config/rs6000/rs6000-c.c (rs6000_macro_to_expend): Use cpp_macro_p.
+ * config/powerpcspc/powerpcspe-c.c (rs6000_macro_to_expend): Likewise.
+
+2018-08-16 Tamar Christina <tamar.christina@arm.com>
+
+ PR target/84711
+ * config/arm/arm.c (arm_can_change_mode_class): Disallow subreg.
+ * config/arm/neon.md (movv4hf, movv8hf): Refactored to..
+ (mov<mov>): ..this and enable unconditionally.
+
+2018-08-16 Tamar Christina <tamar.christina@arm.com>
+
+ * config/arm/neon.md (*neon_mov<mode>): Remove reg-to-reg alternative.
+
+2018-08-16 Sam Tebbs <sam.tebbs@arm.com>
+
+ * config/aarch64/aarch64.opt (mlow-precision-recip-sqrt)
+ (mlow-precision-sqrt, mlow-precision-div, mverbose-cost-dump): Replace
+ "Common" with "Target".
+
+2018-08-15 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.opt (mmitigate-rop): Mark as deprecated.
+ * doc/invoke.texi (mmitigate-rop): Remove.
+ * config/i386/i386.c: Do not include "regrename.h".
+ (ix86_rop_should_change_byte_p, reg_encoded_number)
+ (ix86_get_modrm_for_rop, set_rop_modrm_reg_bits, ix86_mitigate_rop):
+ Remove.
+ (ix86_reorg): Remove call to ix86_mitigate_rop.
+ * config/i386/i386.md (attr "modrm_class"): Remove.
+ (cmp<mode>_ccno_1, mov<mode>_xor, movstrict<mode>_xor)
+ (x86_mov<mode>cc_0_m1. x86_mov<mode>cc_0_m1_se)
+ (x86_mov<mode>cc_0_m1_neg): Remove modrm_class attribute override.
+
+2018-08-15 Will Schmidt <will_schmidt@vnet.ibm.com>
+
+ * config/rs6000/rs600.c (rs6000_gimple_fold_builtin): Add entries to
+ allow folding of mergeh() and mergel() for the float and double types.
+ (fold_mergehl_helper): Rework to handle building a permute tree
+ for float vectors.
+
+2018-08-15 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (expand_vec_perm_movs): Enable V4SFmode
+ for TARGET_SSE.
+
+2018-08-15 David Malcolm <dmalcolm@redhat.com>
+
+ * common.opt (fdiagnostics-show-labels): New option.
+ * diagnostic-show-locus.c (class layout_range): Add field
+ "m_label".
+ (class layout): Add field "m_show_labels_p".
+ (layout_range::layout_range): Add param "label" and use it to
+ initialize m_label.
+ (make_range): Pass in NULL for new "label" param of layout_range's
+ ctor.
+ (layout::layout): Initialize m_show_labels_p.
+ (layout::maybe_add_location_range): Pass in loc_range->m_label
+ when constructing layout_range instances.
+ (struct line_label): New struct.
+ (layout::print_any_labels): New member function.
+ (layout::print_line): Call it if label-printing is enabled.
+ (selftest::test_one_liner_labels): New test.
+ (selftest::test_diagnostic_show_locus_one_liner): Call it.
+ * diagnostic.c (diagnostic_initialize): Initialize
+ context->show_labels_p.
+ * diagnostic.h (struct diagnostic_context): Add field
+ "show_labels_p".
+ * doc/invoke.texi (Diagnostic Message Formatting Options): Add
+ -fno-diagnostics-show-labels.
+ * dwarf2out.c (gen_producer_string): Add
+ OPT_fdiagnostics_show_labels to the ignored options.
+ * gcc-rich-location.c (gcc_rich_location::add_expr): Add "label"
+ param.
+ (gcc_rich_location::maybe_add_expr): Likewise.
+ * gcc-rich-location.h (gcc_rich_location::gcc_rich_location): Add
+ label" param, defaulting to NULL.
+ (gcc_rich_location::add_expr): Add "label" param.
+ (gcc_rich_location::maybe_add_expr): Likewise.
+ (class text_range_label): New class.
+ (class range_label_for_type_mismatch): New class.
+ * gimple-ssa-sprintf.c (fmtwarn): Pass NULL for new label params
+ of format_warning_va.
+ (fmtwarn_n): Likewise for new params of format_warning_n_va.
+ * lto-wrapper.c (merge_and_complain): Add
+ OPT_fdiagnostics_show_labels to the "pick one setting" options.
+ (append_compiler_options): Likewise to the dropped options.
+ (append_diag_options): Likewise to the passed-on options.
+ * opts.c (common_handle_option): Handle the new option.
+ * selftest-diagnostic.c
+ (test_diagnostic_context::test_diagnostic_context): Enable
+ show_labels_p.
+ * substring-locations.c: Include "gcc-rich-location.h".
+ (format_warning_n_va): Add "fmt_label" and "param_label" params
+ and use them as appropriate.
+ (format_warning_va): Add "fmt_label" and "param_label" params,
+ passing them on to format_warning_n_va.
+ (format_warning_at_substring): Likewise.
+ (format_warning_at_substring_n): Likewise.
+ * substring-locations.h (format_warning_va): Add "fmt_label" and
+ "param_label" params.
+ (format_warning_n_va): Likewise.
+ (format_warning_at_substring): Likewise.
+ (format_warning_at_substring_n): Likewise.
+ * toplev.c (general_init): Initialize global_dc->show_labels_p.
+
+2018-08-15 Qing Zhao <qing.zhao@oracle.com>
+
+ PR testsuite/86519
+ * builtins.c (expand_builtin_memcmp): Do not expand the call
+ when overflow is detected.
+
+2018-08-15 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/71625
+ * config/aarch64/aarch64-builtins.c
+ (aarch64_init_simd_builtin_types): Clear Poly8_t's TYPE_STRING_FLAG.
+
+2018-08-15 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * config/s390/s390.c (s390_reorg): Remove loop.
+
+2018-08-15 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.c
+ (darwin_function_switched_text_sections): Delete.
+ * gcc/config/darwin.h
+ (TARGET_ASM_FUNCTION_SWITCHED_TEXT_SECTIONS): Likewise.
+
+2018-08-15 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR target/81685
+ * config/darwin.h: (DEBUG_STR_OFFSETS_SECTION, DEBUG_LOCLISTS_SECTION,
+ DEBUG_RNGLISTS_SECTION) new macros. (DEBUG_PUBNAMES_SECTION,
+ DEBUG_PUBTYPES_SECTION) update to include GNU variant.
+
+2018-08-15 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/86925
+ * predict.c (expr_expected_value_1): When taking
+ later predictor, assign also probability.
+ Use fold_build2_initializer_loc in order to fold
+ the expression in -frounding-math.
+
+2018-08-14 Allan Sandfeld Jensen <allan.jensen@qt.io>
+
+ * config/i386/i386.c (expand_vec_perm_movs): New method matching movs
+ patterns.
+ (expand_vec_perm_1): Try the new method.
+
+2018-08-14 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ PR target/86547
+ * lra-lives.c (remove_some_program_points_and_update_live_ranges):
+ Check whether lra_live_max_point is 0 before dividing.
+
+2018-08-14 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/86650
+ * tree-vrp.c (vrp_prop::check_array_ref): Print an inform message.
+ (vrp_prop::check_mem_ref): Same.
+
+2018-08-13 Liu Hao <lh_mouse@126.com>
+
+ * pretty-print.c (eat_esc_sequence): Swap the foreground and
+ background colors if the COMMON_LVB_REVERSE_VIDEO flag is set,
+ and clear it thereafter, as it only works for DBCS.
+
+2018-08-13 Liu Hao <lh_mouse@126.com>
+
+ * pretty-print.c (mingw_ansi_fputs): Do not call _close() on the
+ handle returned by _get_osf_handle().
+
+2018-08-13 Will Schmidt <will_schmidt@vnet.ibm.com>
+
+ * gcc/config/rs6000/rs6000.c (rs6000_gimple_fold_builtin): Add support
+ for folding vec_perm.
+
+2018-08-13 Will Schmidt <will_schmidt@vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_gimple_fold_builtin):
+ Add support for gimple-folding of vec_pack() and vec_unpack()
+ intrinsics.
+
+2018-08-13 Will Schmidt <will_schmidt@vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_builtin_valid_without_lhs): Add
+ vec_xst variants to the list.
+ (rs6000_gimple_fold_builtin): Add support for folding unaligned
+ vector loads and stores.
+
+2018-08-13 David Edelsohn <dje.gcc@gmail.com>
+
+ * config.gcc (rs6000-ibm-aix4.x): Delete.
+ (rs6000-ibm-aix5.1): Delete.
+ (rs6000-ibm-aix5.2): Delete.
+ (rs6000-ibm-aix5.3): Delete.
+ * config/rs6000/aix43.h: Delete.
+ * config/rs6000/aix51.h: Delete.
+ * config/rs6000/aix52.h: Delete.
+ * config/rs6000/t-aix43: Delete.
+
+2018-08-13 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * config/s390/s390.c (s390_decompose_constant_pool_ref):
+ New function.
+ (s390_decompose_address): Factor out constant pool ref
+ decomposition.
+
+2018-08-12 Chung-Ju Wu <jasonwucj@gmail.com>
+
+ * config/nds32/nds32-predicates.c
+ (nds32_can_use_bclr_p): Change return type as bool.
+ (nds32_can_use_bset_p): Ditto.
+ (nds32_can_use_btgl_p): Ditto.
+ (nds32_can_use_bitci_p): Ditto.
+ * config/nds32/nds32-protos.h
+ (nds32_can_use_bclr_p): Change declaration.
+ (nds32_can_use_bset_p): Ditto.
+ (nds32_can_use_btgl_p): Ditto.
+ (nds32_can_use_bitci_p): Ditto.
+
+2018-08-12 Chung-Ju Wu <jasonwucj@gmail.com>
+
+ * config/nds32/nds32.c (nds32_expand_prologue, nds32_expand_epilogue):
+ Support -msched-prolog-epilog option.
+ * config/nds32/nds32.opt (msched-prolog-epilog): New option.
+
+2018-08-12 Chung-Ju Wu <jasonwucj@gmail.com>
+
+ * common/config/nds32/nds32-common.c
+ (nds32_option_optimization_table): Enalbe -malways-align.
+
+2018-08-12 Chung-Ju Wu <jasonwucj@gmail.com>
+
+ * config.gcc (nds32*): Add nds32_isr.h and nds32_init.inc in
+ extra_headers.
+ * common/config/nds32/nds32-common.c (nds32_handle_option): Handle
+ OPT_misr_secure_ case.
+ * config/nds32/nds32-isr.c: Implementation of backward compatibility.
+ * config/nds32/nds32-protos.h (nds32_isr_function_critical_p): New.
+ * config/nds32/nds32.c (nds32_attribute_table): Add critical and
+ secure attribute.
+ * config/nds32/nds32.h (nds32_isr_nested_type): Add NDS32_CRITICAL.
+ (nds32_isr_info): New field security_level.
+ (TARGET_ISR_VECTOR_SIZE_4_BYTE): New macro.
+ * config/nds32/nds32.md (return_internal): Consider critical attribute.
+ * config/nds32/nds32.opt (misr-secure): New option.
+ * config/nds32/nds32_init.inc: New file.
+ * config/nds32/nds32_isr.h: New file.
+
+2018-08-11 John David Anglin <danglin@gcc.gnu.org>
+
+ * config/pa/pa.md (UNSPEC_MEMORY_BARRIER): New unspec enum.
+ Update comment for atomic instructions.
+ (atomic_storeqi, atomic_storehi, atomic_storesi, atomic_storesf,
+ atomic_loaddf, atomic_loaddf_1, atomic_storedf, atomic_storedf_1):
+ Remove.
+ (atomic_loaddi): Revise fence expansion to only emit fence prior to
+ load for __ATOMIC_SEQ_CST model.
+ (atomic_loaddi_1): Remove float register target.
+ (atomic_storedi): Handle CONST_INT values.
+ (atomic_storedi_1): Remove float register source. Add special case
+ for zero value.
+ (memory_barrier): New expander and insn.
+
+2018-08-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/86835
+ * tree-ssa-math-opts.c (insert_reciprocals): Even when inserting
+ new_stmt after def_gsi, make sure to insert new_square_stmt after
+ that stmt, not 2 stmts before it.
+
+2018-08-10 Alexander Monakov <amonakov@ispras.ru>
+
+ PR target/82418
+ * config/i386/i386.md (<s>mul<mode>3_highpart): Use DWIH mode iterator
+ instead of SWI48.
+
+2018-08-10 Martin Liska <mliska@suse.cz>
+
+ PR target/83610
+ * builtin-types.def (BT_FN_LONG_LONG_LONG_DOUBLE): Add new
+ function type.
+ * builtins.c (expand_builtin_expect_with_probability):
+ New function.
+ (expand_builtin_expect_with_probability): New function.
+ (build_builtin_expect_predicate): Add new argumnet probability
+ for BUILT_IN_EXPECT_WITH_PROBABILITY.
+ (fold_builtin_expect):
+ (fold_builtin_2):
+ (fold_builtin_3):
+ * builtins.def (BUILT_IN_EXPECT_WITH_PROBABILITY):
+ * builtins.h (fold_builtin_expect): Set new argument.
+ * doc/extend.texi: Document __builtin_expect_with_probability.
+ * doc/invoke.texi: Likewise.
+ * gimple-fold.c (gimple_fold_call): Pass new argument.
+ * ipa-fnsummary.c (find_foldable_builtin_expect): Handle
+ also BUILT_IN_EXPECT_WITH_PROBABILITY.
+ * predict.c (get_predictor_value): New function.
+ (expr_expected_value): Add new argument probability. Assume
+ that predictor and probability are always non-null.
+ (expr_expected_value_1): Likewise. For __builtin_expect and
+ __builtin_expect_with_probability set probability. Handle
+ combination in binary expressions.
+ (tree_predict_by_opcode): Simplify code by simply calling
+ get_predictor_value.
+ (pass_strip_predict_hints::execute): Add handling of
+ BUILT_IN_EXPECT_WITH_PROBABILITY.
+ * predict.def (PRED_BUILTIN_EXPECT_WITH_PROBABILITY): Add
+ new predictor.
+ * tree.h (DECL_BUILT_IN_P): New function.
+
+2018-08-10 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/85799
+ * passes.def: Add argument for pass_strip_predict_hints.
+ * predict.c (class pass_strip_predict_hints): Add new argument
+ early_p.
+ (strip_predictor_early): New function.
+ (pass_strip_predict_hints::execute): Call the function to
+ strip predictors.
+ (strip_predict_hints): New function.
+ * predict.def: Fix comment.
+
+2018-08-10 Thomas Preud'homme <thomas.preudhomme@linaro.org>
+
+ * Makefile.in: Clarify which tm.texi to copy over to assert the
+ right to grant a GFDL license for all.
+
+2018-08-09 Jeff Law <law@redhat.com>
+
+ * config/m68k/m68k.c (m68k_adjust_decorated_operand): Remove
+ unused variable.
+
+2018-08-09 Andreas Schwab <schwab@linux-m68k.org>
+
+ * config/m68k/m68k-protos.h (m68k_final_prescan_insn): Remove
+ prototype.
+
+2018-08-09 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-loop.c (vectorizable_reduction): Allow inner-loop
+ reductions for variable-length vectors.
+
+2018-08-09 David Malcolm <dmalcolm@redhat.com>
+
+ PR other/84889
+ * common.opt (fdiagnostics-show-line-numbers): New option.
+ * diagnostic-show-locus.c (class layout): Add fields
+ "m_show_line_numbers_p" and "m_linenum_width";
+ (num_digits): New function.
+ (test_num_digits): New function.
+ (layout::layout): Initialize new fields. Update m_x_offset
+ logic to handle any left margin.
+ (layout::print_source_line): Print line number when requested.
+ (layout::start_annotation_line): New member function.
+ (layout::print_annotation_line): Call it.
+ (layout::print_leading_fixits): Likewise.
+ (layout::print_trailing_fixits): Likewise. Update calls to
+ move_to_column for new parameter.
+ (layout::get_x_bound_for_row): Add "add_left_margin" param and use
+ it to potentially call start_annotation_line.
+ (layout::show_ruler): Call start_annotation_line.
+ (selftest::test_line_numbers_multiline_range): New selftest.
+ (selftest::diagnostic_show_locus_c_tests): Call test_num_digits
+ and selftest::test_line_numbers_multiline_range.
+ * diagnostic.c (diagnostic_initialize): Initialize
+ show_line_numbers_p.
+ * diagnostic.h (struct diagnostic_context): Add field
+ "show_line_numbers_p".
+ * doc/invoke.texi (Diagnostic Message Formatting Options): Add
+ -fno-diagnostics-show-line-numbers.
+ * dwarf2out.c (gen_producer_string): Add
+ OPT_fdiagnostics_show_line_numbers to the ignored options.
+ * lto-wrapper.c (merge_and_complain): Likewise to the "pick
+ one setting" options.
+ (append_compiler_options): Likewise to the dropped options.
+ (append_diag_options): Likewise to the passed-on options.
+ * opts.c (common_handle_option): Handle the new option.
+ * toplev.c (general_init): Set up global_dc->show_line_numbers_p.
+
+2018-08-09 Kelvin Nilsen <kelvin@gcc.gnu.org>
+
+ * doc/extend.texi (PowerPC AltiVec Built-in Functions Available on
+ ISA 2.07): Correct spelling of bcdsub to be __builtin_bcdsub. Add
+ third argument of type "const signed char" to descriptions of
+ __builtin_bcdadd, __builtin_bcdadd_lt, __builtin_bcdadd_eq,
+ __builtin_bcdadd_gt, __builtin_bcdadd_ov, __builtin_bcdsub,
+ __builtin_bcdsub_lt, __builtin_bcdsub_eq, __builtin_bcdsub_gt,
+ __builtin_bcdsub_ov functions.
+
+2018-08-09 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/86858
+ * tree-vect-loop.c (vect_is_simple_reduction): Restore
+ flow_bb_inside_loop_p calls.
+
+2018-08-09 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/86871
+ * tree-vect-stmts.c (vect_transform_stmt): Use gimple_get_lhs
+ instead of gimple_assign_lhs.
+
+2018-08-09 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/86887
+ * config/aarch64/aarch64.md (add<mode>3_carryinC_zero): Add missing
+ register constraint to operand 0.
+ (add<mode>3_carryinC): Likewise.
+ (add<mode>3_carryinV_zero, add<mode>3_carryinV): Likewise.
+
+2018-08-09 Martin Liska <mliska@suse.cz>
+
+ PR c/86895
+ * common.opt: Remove extra line.
+
+2018-08-09 Martin Liska <mliska@suse.cz>
+
+ * params.def (PARAM_ALIGN_LOOP_ITERATIONS): Remove double dots
+ at the end of a line, make first letter capital and end up
+ a sentence with a dot.
+ (PARAM_LOOP_INTERCHANGE_STRIDE_RATIO): Likewise.
+ (PARAM_LOOP_BLOCK_TILE_SIZE): Likewise.
+ (PARAM_GRAPHITE_MAX_NB_SCOP_PARAMS): Likewise.
+ (PARAM_GRAPHITE_MAX_ARRAYS_PER_SCOP): Likewise.
+ (PARAM_MAX_ISL_OPERATIONS): Likewise.
+ (PARAM_GRAPHITE_ALLOW_CODEGEN_ERRORS): Likewise.
+ (PARAM_PROFILE_FUNC_INTERNAL_ID): Likewise.
+ (PARAM_INDIR_CALL_TOPN_PROFILE): Likewise.
+ (PARAM_SLP_MAX_INSNS_IN_BB): Likewise.
+ (PARAM_IPA_CP_EVAL_THRESHOLD): Likewise.
+ (PARAM_IPA_CP_RECURSION_PENALTY): Likewise.
+ (PARAM_IPA_CP_SINGLE_CALL_PENALTY): Likewise.
+ (PARAM_IPA_CP_LOOP_HINT_BONUS): Likewise.
+ (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS): Likewise.
+ (PARAM_TREE_REASSOC_WIDTH): Likewise.
+ (PARAM_HSA_GEN_DEBUG_STORES): Likewise.
+ (PARAM_MAX_SPECULATIVE_DEVIRT_MAYDEFS): Likewise.
+ (PARAM_MAX_VRP_SWITCH_ASSERTIONS): Likewise.
+
+2018-08-09 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ PR target/84332
+ * config/s390/s390.c (s390_option_override_internal): Reduce the
+ stack-clash-protection-probe-interval param if it would be too big
+ for z900.
+
+2018-08-08 Andreas Schwab <schwab@linux-m68k.org>
+
+ PR target/46179
+ * config/m68k/m68k.h (FINAL_PRESCAN_INSN): Don't define.
+ * config/m68k/m68k.c (handle_move_double): Don't call
+ m68k_final_prescan_insn.
+ (m68k_adjust_decorated_operand): Renamed from
+ m68k_final_prescan_insn, remove first and third operand and
+ simplify.
+ (print_operand): Call it.
+ (print_operand_address): Call it.
+
+2018-08-08 Nathan Sidwell <nathan@acm.org>
+
+ * diagnostic.c (diagnostic_report_current_module): Use
+ linemap_included_from & linemap_included_from_linemap.
+
+2018-08-08 Hongbo Zhang <hongbo.zhang@linaro.org>
+
+ * config/aarch64/aarch64-cores.def: Add phecda core.
+ * config/aarch64/aarch64-tune.md: Regenerate.
+ * doc/invoke.texi: Add phecda core.
+
+2018-08-08 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ PR target/85295
+ * config/s390/constraints.md ("NxHD0", "NxSD0"): New constraint
+ definitions.
+ * config/s390/s390.md ("movti"): Add more alternatives for
+ constant to GPR copies.
+
+2018-08-08 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * config/s390/s390.c: Fix whitespace damage throughout the file.
+ * config/s390/s390.h: Likewise.
+ * config/s390/tpf.h: Likewise.
+
+2018-08-08 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * config/s390/s390.c (s390_loadrelative_operand_p):
+ Remove TARGET_CPU_ZARCH usages.
+ (s390_rtx_costs): Likewise.
+ (s390_legitimate_constant_p): Likewise.
+ (s390_cannot_force_const_mem): Likewise.
+ (legitimate_reload_constant_p): Likewise.
+ (s390_preferred_reload_class): Likewise.
+ (legitimize_pic_address): Likewise.
+ (legitimize_tls_address): Likewise.
+ (s390_split_branches): Removed.
+ (s390_add_execute): Removed.
+ (s390_dump_pool): Remove TARGET_CPU_ZARCH usages.
+ (s390_mainpool_start): Likewise.
+ (s390_mainpool_finish): Likewise.
+ (s390_mainpool_cancel): Removed.
+ (s390_chunkify_start): Remove TARGET_CPU_ZARCH usages.
+ (s390_chunkify_cancel): Likewise.
+ (s390_return_addr_rtx): Likewise.
+ (s390_register_info): Remove split_branches_pending_p uages.
+ (s390_optimize_register_info): Likewise.
+ (s390_init_frame_layout): Remove TARGET_CPU_ZARCH and
+ split_branches_pending_p usages.
+ (s390_can_eliminate): Remove TARGET_CPU_ZARCH usages.
+ (s390_load_got): Likewise.
+ (s390_expand_split_stack_prologue): Likewise.
+ (output_asm_nops): Likewise.
+ (s390_function_profiler): Likewise.
+ (s390_emit_call): Likewise.
+ (s390_conditional_register_usage): Likewise.
+ (s390_optimize_prologue): Likewise.
+ (s390_reorg): Remove TARGET_CPU_ZARCH and
+ split_branches_pending_p usages.
+ (s390_option_override_internal): Remove TARGET_CPU_ZARCH
+ usages.
+ (s390_output_indirect_thunk_function): Likewise.
+ * config/s390/s390.h (TARGET_CPU_ZARCH): Removed.
+ (TARGET_CPU_ZARCH_P): Removed.
+ (struct machine_function): Remove split_branches_pending_p.
+ * config/s390/s390.md: Remove TARGET_CPU_ZARCH usages.
+
+2018-08-08 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * common/config/s390/s390-common.c (processor_flags_table):
+ Remove flags.
+ * config.gcc: Remove with_arch/with_tune support.
+ * config/s390/2064.md: Remove cpu attribute comparisons.
+ * config/s390/driver-native.c (s390_host_detect_local_cpu):
+ Remove MTN.
+ * config/s390/linux.h (ASM_SPEC):
+ Remove -march support.
+ * config/s390/s390-c.c (s390_cpu_cpp_builtins_internal):
+ Use a table to get an arch level.
+ * config/s390/s390-opts.h (enum processor_type):
+ Remove enum values.
+ * config/s390/s390.c
+ (processor_table): Remove entries, add arch_level values.
+ (s390_issue_rate): Remove cases.
+ (s390_option_override): Adjust
+ s390_option_override_internal() call.
+ (s390_option_override_internal): Remove deprecation warning.
+ (s390_valid_target_attribute_tree): Adjust
+ s390_option_override_internal() call.
+ * config/s390/s390.h (struct s390_processor):
+ Share with s390-c.c, add arch_level field.
+ * config/s390/s390.md:
+ Remove occurrences in cpu attribute.
+ * config/s390/s390.opt: Remove -march/-mtune support.
+ * config/s390/tpf.h (ASM_SPEC): Remove -march support.
+ * doc/invoke.texi: Remove deprecation warning.
+
+2018-08-08 Luis Machado <luis.machado@linaro.org>
+
+ * config/aarch64/aarch64.c (qdf24xx_vector_cost): New static
+ global.
+ (qdf24xx_tunings): Set vector cost structure to
+ qdf24xx_vector_cost.
+
+ * config/aarch64/aarch64.c (qdf24xx_addrcost_table)
+ <register_sextend>: Set to 3.
+
+2018-08-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR target/86838
+ * config/aarch64/iterators.md (FRECP, frecp_suffix): Delete.
+ * config/aarch64/aarch64-simd.md
+ (aarch64_frecp<FRECP:frecp_suffix><mode>): Fold FRECPE into...
+ (@aarch64_frecpe<mode>): ...here and the move FRECPX to...
+ (aarch64_frecpx<mode>): ...this new pattern.
+ * config/aarch64/aarch64-simd-builtins.def: Remove comment
+ about aarch64_frecp<FRECP:frecp_suffix><mode>.
+
+2018-08-07 Martin Liska <mliska@suse.cz>
+
+ PR middle-end/83023
+ * predict.c (expr_expected_value_1): Handle DECL_IS_MALLOC,
+ BUILT_IN_REALLOC and DECL_IS_OPERATOR_NEW.
+ * predict.def (PRED_MALLOC_NONNULL): New predictor.
+ * doc/extend.texi: Document that malloc attribute adds
+ hit to compiler.
+
+2018-08-06 John David Anglin <danglin@gcc.gnu.org>
+
+ PR target/86785
+ * config/pa/pa.c (TARGET_HAVE_SPECULATION_SAFE_VALUE):
+ Define to speculation_safe_value_not_needed.
+
+2018-08-06 Jeff Law <law@redhat.com>
+
+ * tree-ssa-dom.c (dom_opt_dom_walker::optimize_stmt): Pass down
+ the vr_values instance to cprop_into_stmt.
+ (cprop_into_stmt): Pass vr_values instance down to cprop_operand.
+ (cprop_operand): Also query EVRP to determine if OP is a constant.
+
+2018-08-06 Nathan Sidwell <nathan@acm.org>
+
+ * diagnostic.c (diagnostic_report_current_module): Reroll
+ included-at loop. Translate text.
+
+2018-08-06 David Malcolm <dmalcolm@redhat.com>
+
+ * function-tests.c (selftest::test_expansion_to_rtl): Call
+ free_after_compilation.
+
+2018-08-06 Alan Hayward <alan.hayward@arm.com>
+
+ * config/aarch64/aarch64.md: Add clobber highs to tls_desc.
+
+2018-08-06 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * config/s390/s390.c (s390_loop_unroll_adjust): Prevent small
+ loops with memory block operations from getting unrolled.
+
+2018-08-06 Ulrich Weigand <uweigand@de.ibm.com>
+
+ PR target/86807
+ * config/spu/spu.c (TARGET_HAVE_SPECULATION_SAFE_VALUE):
+ Define to speculation_safe_value_not_needed.
+
+2018-08-06 Jeff Law <law@redhat.com>
+
+ * reload1.c (forget_old_reloads_1): Adjust CLOBBER_HIGH
+ assert.
+
+2018-08-06 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ PR target/86662
+ * gcc/tree.c (build_common_tree_nodes): Initialize integer_types array
+ with all enabled __intN types.
+
+ * gcc/testsuite/gcc.target/msp430/pr86662.c: New test.
+
+2018-08-06 Alan Hayward <alan.hayward@arm.com>
+
+ * alias.c (record_set): Check for clobber high.
+ * cfgexpand.c (expand_gimple_stmt): Likewise.
+ * combine-stack-adj.c (single_set_for_csa): Likewise.
+ * combine.c (find_single_use_1): Likewise.
+ (set_nonzero_bits_and_sign_copies): Likewise.
+ (get_combine_src_dest): Likewise.
+ (is_parallel_of_n_reg_sets): Likewise.
+ (try_combine): Likewise.
+ (record_dead_and_set_regs_1): Likewise.
+ (reg_dead_at_p_1): Likewise.
+ (reg_dead_at_p): Likewise.
+ * dce.c (deletable_insn_p): Likewise.
+ (mark_nonreg_stores_1): Likewise.
+ (mark_nonreg_stores_2): Likewise.
+ * df-scan.c (df_find_hard_reg_defs): Likewise.
+ (df_uses_record): Likewise.
+ (df_get_call_refs): Likewise.
+ * dwarf2out.c (mem_loc_descriptor): Likewise.
+ * haifa-sched.c (haifa_classify_rtx): Likewise.
+ * ira-build.c (create_insn_allocnos): Likewise.
+ * ira-costs.c (scan_one_insn): Likewise.
+ * ira.c (equiv_init_movable_p): Likewise.
+ (rtx_moveable_p): Likewise.
+ (interesting_dest_for_shprep): Likewise.
+ * jump.c (mark_jump_label_1): Likewise.
+ * postreload-gcse.c (record_opr_changes): Likewise.
+ * postreload.c (reload_cse_simplify): Likewise.
+ (struct reg_use): Add source expr.
+ (reload_combine): Check for clobber high.
+ (reload_combine_note_use): Likewise.
+ (reload_cse_move2add): Likewise.
+ (move2add_note_store): Likewise.
+ * print-rtl.c (print_pattern): Likewise.
+ * recog.c (decode_asm_operands): Likewise.
+ (store_data_bypass_p): Likewise.
+ (if_test_bypass_p): Likewise.
+ * regcprop.c (kill_clobbered_value): Likewise.
+ (kill_set_value): Likewise.
+ * reginfo.c (reg_scan_mark_refs): Likewise.
+ * reload1.c (maybe_fix_stack_asms): Likewise.
+ (eliminate_regs_1): Likewise.
+ (elimination_effects): Likewise.
+ (mark_not_eliminable): Likewise.
+ (scan_paradoxical_subregs): Likewise.
+ (forget_old_reloads_1): Likewise.
+ * reorg.c (find_end_label): Likewise.
+ (try_merge_delay_insns): Likewise.
+ (redundant_insn): Likewise.
+ (own_thread_p): Likewise.
+ (fill_simple_delay_slots): Likewise.
+ (fill_slots_from_thread): Likewise.
+ (dbr_schedule): Likewise.
+ * resource.c (update_live_status): Likewise.
+ (mark_referenced_resources): Likewise.
+ (mark_set_resources): Likewise.
+ * rtl.c (copy_rtx): Likewise.
+ * rtlanal.c (reg_referenced_p): Likewise.
+ (single_set_2): Likewise.
+ (noop_move_p): Likewise.
+ (note_stores): Likewise.
+ * sched-deps.c (sched_analyze_reg): Likewise.
+ (sched_analyze_insn): Likewise.
+
+2018-08-06 Alan Hayward <alan.hayward@arm.com>
+
+ * cse.c (invalidate_reg): New function extracted from...
+ (invalidate): ...here.
+ (canonicalize_insn): Check for clobber high.
+ (invalidate_from_clobbers): invalidate clobber highs.
+ (invalidate_from_sets_and_clobbers): Likewise.
+ (count_reg_usage): Check for clobber high.
+ (insn_live_p): Likewise.
+ * cselib.c (cselib_expand_value_rtx_1):Likewise.
+ (cselib_invalidate_regno): Check for clobber in setter.
+ (cselib_invalidate_rtx): Pass through setter.
+ (cselib_invalidate_rtx_note_stores):
+ (cselib_process_insn): Check for clobber high.
+ * cselib.h (cselib_invalidate_rtx): Add operand.
+
+2018-08-06 Alan Hayward <alan.hayward@arm.com>
+
+ * lra-eliminations.c (lra_eliminate_regs_1): Check for clobber high.
+ (mark_not_eliminable): Likewise.
+ * lra-int.h (struct lra_insn_reg): Add clobber high marker.
+ * lra-lives.c (process_bb_lives): Check for clobber high.
+ * lra.c (new_insn_reg): Remember clobber highs.
+ (collect_non_operand_hard_regs): Check for clobber high.
+ (lra_set_insn_recog_data): Likewise.
+ (add_regs_to_insn_regno_info): Likewise.
+ (lra_update_insn_regno_info): Likewise.
+
+2018-08-06 Alan Hayward <alan.hayward@arm.com>
+
+ * rtl.h (reg_is_clobbered_by_clobber_high): Add declarations.
+ * rtlanal.c (reg_is_clobbered_by_clobber_high): Add function.
+
+2018-08-06 Alan Hayward <alan.hayward@arm.com>
+
+ * emit-rtl.c (verify_rtx_sharing): Check for CLOBBER_HIGH.
+ (copy_insn_1): Likewise.
+ (gen_hard_reg_clobber_high): New gen function.
+ * genconfig.c (walk_insn_part): Check for CLOBBER_HIGH.
+ * genemit.c (gen_exp): Likewise.
+ (gen_emit_seq): Pass through info.
+ (gen_insn): Check for CLOBBER_HIGH.
+ (gen_expand): Pass through info.
+ (gen_split): Likewise.
+ (output_add_clobbers): Likewise.
+ * genrecog.c (validate_pattern): Check for CLOBBER_HIGH.
+ (remove_clobbers): Likewise.
+ * rtl.h (gen_hard_reg_clobber_high): New declaration.
+
+2018-08-06 Alan Hayward <alan.hayward@arm.com>
+
+ * doc/rtl.texi (clobber_high): Add.
+ (parallel): Add in clobber high
+ * rtl.c (rtl_check_failed_code3): Add function.
+ * rtl.def (CLOBBER_HIGH): Add expression.
+ * rtl.h (RTL_CHECKC3): Add macro.
+ (rtl_check_failed_code3): Add declaration.
+ (XC3EXP): Add macro.
+
+2018-08-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/86386
+ * config/i386/i386.c (ix86_finalize_stack_frame_flags): Set
+ cfun->machine->max_used_stack_alignment if needed.
+
+2018-08-04 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/86571
+ * gimple-ssa-sprintf.c (format_floating): Extend upper bound of
+ NaN output to 4.
+
+2018-08-03 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR target/86799
+ * config/nios2/nios2.c (TARGET_HAVE_SPECULATION_SAFE_VALUE):
+ Define.
+
+2018-08-03 Jeff Law <law@redhat.com>
+
+ PR target/86795
+ * config/mn10300/mn10300.c (TARGET_HAVE_SPECULATION_SAFE_VALUE):
+ Define to speculation_safe_value_not_needed.
+
+2018-08-03 David Malcolm <dmalcolm@redhat.com>
+
+ * doc/gcov.texi (-x): Remove duplicate "to".
+ * doc/invoke.texi (-Wnoexcept-type): Remove duplicate "calls".
+ (-Wif-not-aligned): Remove duplicate "is".
+ (-flto): Remove duplicate "the".
+ (MicroBlaze Options): In examples of "-mcpu=cpu-type", remove
+ duplicate "v5.00.b".
+ (MSP430 Options): Remove duplicate "and" from the description
+ of "-mgprel-sec=regexp".
+ (x86 Options): Remove duplicate copies of "vmldLog102" and
+ vmlsLog104 from description of "-mveclibabi=type".
+
+2018-08-03 Richard Sandiford <richard.sandiford@arm.com>
+
+ * internal-fn.h (first_commutative_argument): Declare.
+ * internal-fn.c (first_commutative_argument): New function.
+ * tree-vect-slp.c (vect_get_and_check_slp_defs): Remove extra
+ restrictions for pattern statements. Use first_commutative_argument
+ to look for commutative operands in calls to internal functions.
+
+2018-08-03 Aldy Hernandez <aldyh@redhat.com>
+
+ * Makefile.in (wide-int-range.o): New.
+ * tree-vrp.c: Move all the wide_int_* functions to...
+ * wide-int-range.cc: ...here.
+ * tree-vrp.h: Move all the wide_int_* prototypes to...
+ * wide-int-range.h: ...here.
+
+2018-08-03 Tom de Vries <tdevries@suse.de>
+
+ * common/config/nvptx/nvptx-common.c (nvptx_except_unwind_info): Return
+ UI_NONE.
+ * config/nvptx/nvptx.c (TARGET_ASM_BYTE_OP): Remove define.
+ * except.c (output_function_exception_table): Do early exit if
+ targetm_common.except_unwind_info (&global_options) == UI_NONE.
+
+2018-08-03 Martin Liska <mliska@suse.cz>
+
+ * predict.c (dump_prediction): Change to 2 digits
+ in fraction part.
+
+2018-08-03 Siddhesh Poyarekar <siddhesh@sourceware.org>
+
+ * config/aarch64/falkor.md (falkor_am_1_vxvy_vxvy): Move
+ neon_dup_q to...
+ (falkor_am_1_gtov_gtov): ... a new insn reservation.
+
+2018-07-19 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * config/nds32/nds32.c (nds32_hard_regno_mode_ok): Replace > with >=.
+ * df-problems.c (df_remove_dead_eq_notes): Replace > with >=.
+ * dwarf2out.c (mem_loc_descriptor): Replace > with >=.
+ * lra-constraints.c (spill_hard_reg_in_range): Replace <= with <.
+ * lra-remat.c (call_used_input_regno_present_p): Replace <= with <.
+
+2018-08-02 David Malcolm <dmalcolm@redhat.com>
+
+ * diagnostic-show-locus.c (diagnostic_show_locus): Use
+ pp_take_prefix when saving the existing prefix.
+ * diagnostic.c (diagnostic_append_note): Likewise.
+ * langhooks.c (lhd_print_error_function): Likewise.
+ * pretty-print.c (pp_set_prefix): Drop the "const" from "prefix"
+ param's type. Free the existing prefix.
+ (pp_take_prefix): New function.
+ (pretty_printer::pretty_printer): Drop the prefix parameter.
+ Rename the length parameter to match the comment.
+ (pretty_printer::~pretty_printer): Free the prefix.
+ * pretty-print.h (pretty_printer::pretty_printer): Drop the prefix
+ parameter.
+ (struct pretty_printer): Drop the "const" from "prefix" field's
+ type and clarify memory management.
+ (pp_set_prefix): Drop the "const" from the 2nd param.
+ (pp_take_prefix): New decl.
+
+2018-08-02 Aaron Sawdey <acsawdey@linux.ibm.com>
+
+ * config/rs6000/rs6000-string.c (select_block_compare_mode): Move test
+ for word_mode_ok here instead of passing as argument.
+ (expand_block_compare): Change select_block_compare_mode() call.
+ (expand_strncmp_gpr_sequence): New function.
+ (expand_strn_compare): Make use of expand_strncmp_gpr_sequence.
+
+2018-08-02 Jeff Law <law@redhat.com>
+
+ PR target/86790
+ * config/m68k/m68k.c (TARGET_HAVE_SPECULATION_SAFE_VALUE):
+ Define to speculation_safe_value_not_needed.
+
+ PR target/86784
+ * config/h8300/h8300.c (TARGET_HAVE_SPECULATION_SAFE_VALUE):
+ Define to speculation_safe_value_not_needed.
+
+2018-08-02 Tom de Vries <tdevries@suse.de>
+
+ PR target/86660
+ * common/config/nvptx/nvptx-common.c (nvptx_except_unwind_info): New
+ function. Return UI_TARGET unconditionally.
+ (TARGET_EXCEPT_UNWIND_INFO): Redefine to nvptx_except_unwind_info.
+ * config/nvptx/nvptx.c (TARGET_ASM_BYTE_OP): Emit commented out '.byte'.
+
+2018-08-02 Richard Sandiford <richard.sandiford@arm.com>
+
+ * genemit.c (print_overload_test): Fix typo.
+
+2018-08-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/86816
+ * tree-ssa-tail-merge.c (tail_merge_valueize): New function
+ which checks for value availability before querying it.
+ (gvn_uses_equal): Use it.
+ (same_succ_hash): Likewise.
+ (gimple_equal_p): Likewise.
+
+2018-08-02 Nick Clifton <nickc@redhat.com>
+
+ PR target/86813
+ * config/stormy16/stormy16.c (TARGET_HAVE_SPECULATION_SAFE_VALUE):
+ Define to speculation_safe_value_not_needed.
+
+ PR target/86810
+ * config/v850/v850.c (TARGET_HAVE_SPECULATION_SAFE_VALUE):
+ Define to speculation_safe_value_not_needed.
+
+ PR target/86810
+ * config/v850/v850.c (TARGET_HAVE_SPECULATION_SAFE_VALUE):
+ Define to speculation_safe_value_not_needed.
+
+ PR target/86803
+ * config/rx/rx.c (TARGET_HAVE_SPECULATION_SAFE_VALUE):
+ Define to speculation_safe_value_not_needed.
+
+ PR target/86797
+ * config/msp430/msp430.c (TARGET_HAVE_SPECULATION_SAFE_VALUE):
+ Define to speculation_safe_value_not_needed.
+
+ PR target/86791
+ * config/mcore/mcore.c (TARGET_HAVE_SPECULATION_SAFE_VALUE):
+ Define to speculation_safe_value_not_needed.
+
+ PR target/86789
+ * config/m32r/m32r.c (TARGET_HAVE_SPECULATION_SAFE_VALUE):
+ Define to speculation_safe_value_not_needed.
+
+ PR target/86787
+ * config/iq2000/iq2000.c (TARGET_HAVE_SPECULATION_SAFE_VALUE):
+ Define to speculation_safe_value_not_needed.
+
+ PR target/86782
+ * config/frv/frv.c (TARGET_HAVE_SPECULATION_SAFE_VALUE): Define to
+ speculation_safe_value_not_needed.
+
+ PR target/86781
+ * config/fr30/fr30.c (TARGET_HAVE_SPECULATION_SAFE_VALUE): Define
+ to speculation_safe_value_not_needed.
+
+2018-08-02 Richard Sandiford <richard.sandiford@arm.com>
+
+ * doc/md.texi: Expand the documentation of instruction names
+ to mention port-local uses. Document '@' in pattern names.
+ * read-md.h (overloaded_instance, overloaded_name): New structs.
+ (mapping): Declare.
+ (md_reader::handle_overloaded_name): New member function.
+ (md_reader::get_overloads): Likewise.
+ (md_reader::m_first_overload): New member variable.
+ (md_reader::m_next_overload_ptr): Likewise.
+ (md_reader::m_overloads_htab): Likewise.
+ * read-md.c (md_reader::md_reader): Initialize m_first_overload,
+ m_next_overload_ptr and m_overloads_htab.
+ * read-rtl.c (iterator_group): Add "type" and "get_c_token" fields.
+ (get_mode_token, get_code_token, get_int_token): New functions.
+ (map_attr_string): Add an optional argument that passes back
+ the associated iterator.
+ (overloaded_name_hash, overloaded_name_eq_p, named_rtx_p):
+ (md_reader::handle_overloaded_name, add_overload_instance): New
+ functions.
+ (apply_iterators): Handle '@' names. Report an error if '@'
+ is used without iterators.
+ (initialize_iterators): Initialize the new iterator_group fields.
+ * genopinit.c (handle_overloaded_code_for)
+ (handle_overloaded_gen): New functions.
+ (main): Use them to print declarations of maybe_code_for_* and
+ maybe_gen_* functions, and inline definitions of code_for_* and gen_*.
+ * genemit.c (print_overload_arguments, print_overload_test)
+ (handle_overloaded_code_for, handle_overloaded_gen): New functions.
+ (main): Use it to print definitions of maybe_code_for_* and
+ maybe_gen_* functions.
+ * config/aarch64/aarch64.c (aarch64_split_128bit_move): Use
+ gen_aarch64_mov{low,high}_di and gen_aarch64_movdi_{low,high}
+ instead of explicit mode checks.
+ (aarch64_split_simd_combine): Likewise gen_aarch64_simd_combine.
+ (aarch64_split_simd_move): Likewise gen_aarch64_split_simd_mov.
+ (aarch64_emit_load_exclusive): Likewise gen_aarch64_load_exclusive.
+ (aarch64_emit_store_exclusive): Likewise gen_aarch64_store_exclusive.
+ (aarch64_expand_compare_and_swap): Likewise
+ gen_aarch64_compare_and_swap and gen_aarch64_compare_and_swap_lse
+ (aarch64_gen_atomic_cas): Likewise gen_aarch64_atomic_cas.
+ (aarch64_emit_atomic_swap): Likewise gen_aarch64_atomic_swp.
+ (aarch64_constant_pool_reload_icode): Delete.
+ (aarch64_secondary_reload): Use code_for_aarch64_reload_movcp
+ instead of aarch64_constant_pool_reload_icode. Use
+ code_for_aarch64_reload_mov instead of explicit mode checks.
+ (rsqrte_type, get_rsqrte_type, rsqrts_type, get_rsqrts_type): Delete.
+ (aarch64_emit_approx_sqrt): Use gen_aarch64_rsqrte instead of
+ get_rsqrte_type and gen_aarch64_rsqrts instead of gen_rqrts_type.
+ (recpe_type, get_recpe_type, recps_type, get_recps_type): Delete.
+ (aarch64_emit_approx_div): Use gen_aarch64_frecpe instead of
+ get_recpe_type and gen_aarch64_frecps instead of get_recps_type.
+ (aarch64_atomic_load_op_code): Delete.
+ (aarch64_emit_atomic_load_op): Likewise.
+ (aarch64_gen_atomic_ldop): Use UNSPECV_ATOMIC_* instead of
+ aarch64_atomic_load_op_code. Use gen_aarch64_atomic_load
+ instead of aarch64_emit_atomic_load_op.
+ * config/aarch64/aarch64.md (aarch64_reload_movcp<GPF_TF:mode><P:mode>)
+ (aarch64_reload_movcp<VALL:mode><P:mode>, aarch64_reload_mov<mode>)
+ (aarch64_movdi_<mode>low, aarch64_movdi_<mode>high)
+ (aarch64_mov<mode>high_di, aarch64_mov<mode>low_di): Add a '@'
+ character before the pattern name.
+ * config/aarch64/aarch64-simd.md (aarch64_split_simd_mov<mode>)
+ (aarch64_rsqrte<mode>, aarch64_rsqrts<mode>)
+ (aarch64_simd_combine<mode>, aarch64_frecpe<mode>)
+ (aarch64_frecps<mode>): Likewise.
+ * config/aarch64/atomics.md (atomic_compare_and_swap<mode>)
+ (aarch64_compare_and_swap<mode>, aarch64_compare_and_swap<mode>_lse)
+ (aarch64_load_exclusive<mode>, aarch64_store_exclusive<mode>)
+ (aarch64_atomic_swp<mode>, aarch64_atomic_cas<mode>)
+ (aarch64_atomic_load<atomic_ldop><mode>): Likewise.
+
+2018-08-02 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_float_const_representable_p):
+ Allow HFmode constants if TARGET_FP_F16INST.
+
+2018-08-02 Jackson Woodruff <jackson.woodruff@arm.com>
+
+ PR target/86014
+ * config/aarch64/aarch64.c (aarch64_operands_adjust_ok_for_ldpstp):
+ No longer check last store for clobber of address register.
+
+2018-08-02 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/86817
+ * gcov.c (process_all_functions): New function.
+ (main): Call it.
+ (process_file): Move functions processing to
+ process_all_functions.
+
+2018-08-02 David Malcolm <dmalcolm@redhat.com>
+
+ * dumpfile.c (dump_user_location_t::dump_user_location_t): Add
+ "const" to the "gimple *" and "rtx_insn *" parameters.
+ * dumpfile.h (dump_user_location_t::dump_user_location_t):
+ Likewise.
+ (dump_location_t::dump_location_t): Likewise.
+
+2018-08-01 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/86650
+ * gimple-pretty-print.c (percent_G_format): Accept a "gimple *"
+ rather than a "gcall *". Directly pass the data of interest
+ to percent_K_format, rather than building a temporary CALL_EXPR
+ to hold it.
+ * gimple-fold.c (gimple_fold_builtin_strncpy): Adjust.
+ (gimple_fold_builtin_strncat): Adjust.
+ * gimple-ssa-warn-restrict.h (check_bounds_or_overlap): Replace
+ gcall* argument with gimple*.
+ * gimple-ssa-warn-restrict.c (check_call): Same.
+ (wrestrict_dom_walker::before_dom_children): Same.
+ (builtin_access::builtin_access): Same.
+ (check_bounds_or_overlap): Same
+ (maybe_diag_overlap): Same.
+ (maybe_diag_offset_bounds): Same.
+ * tree-diagnostic.c (default_tree_printer): Move usage of
+ EXPR_LOCATION (t) and TREE_BLOCK (t) from within percent_K_format
+ to this callsite.
+ * tree-pretty-print.c (percent_K_format): Add argument.
+ * tree-pretty-print.h: Add argument.
+ * tree-ssa-ccp.c (pass_post_ipa_warn::execute): Adjust.
+ * tree-ssa-strlen.c (maybe_diag_stxncpy_trunc): Adjust.
+ (maybe_diag_stxncpy_trunc): Same.
+ (handle_builtin_stxncpy): Same.
+ (handle_builtin_strcat): Same.
+
+2018-08-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ * match.pd: Optimise pointer range checks.
+
+2018-08-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/86758
+ * tree-vect-stmts.c (vectorizable_simd_clone_call): Don't try
+ to remove pattern statements.
+
+2018-08-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-loop.c (_loop_vec_info::_loop_vec_info): Use the
+ result of dfs_enumerate_from when constructing stmt_vec_infos,
+ instead of additionally calling get_loop_body.
+
+2018-08-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vect_create_data_ref_ptr): Remove inv_p
+ parameter.
+ * tree-vect-data-refs.c (vect_create_data_ref_ptr): Likewise.
+ When creating an iv, assert that the step is not known to be zero.
+ (vect_setup_realignment): Update call accordingly.
+ * tree-vect-stmts.c (vectorizable_store): Likewise.
+ (vectorizable_load): Likewise. Handle VMAT_INVARIANT separately.
+
+2018-08-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vect_stmt_to_vectorize): New function.
+ * tree-vect-loop.c (vect_update_vf_for_slp): Use it.
+ (vectorizable_reduction): Likewise.
+ * tree-vect-slp.c (vect_analyze_slp_instance): Likewise.
+ (vect_detect_hybrid_slp_stmts): Likewise.
+ * tree-vect-stmts.c (vect_is_simple_use): Likewise.
+
+2018-08-01 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-vrp (zero_nonzero_bits_from_bounds): Rename to...
+ (wide_int_set_zero_nonzero_bits): ...this.
+ (zero_nonzero_bits_from_vr): Rename to...
+ (vrp_set_zero_nonzero_bits): ...this.
+ (extract_range_from_multiplicative_op_1): Abstract wide int
+ code...
+ (wide_int_range_multiplicative_op): ...here.
+ (extract_range_from_binary_expr_1): Extract wide int binary
+ operations into their own functions.
+ (wide_int_range_lshift): New.
+ (wide_int_range_can_optimize_bit_op): New.
+ (wide_int_range_shift_undefined_p): New.
+ (wide_int_range_bit_xor): New.
+ (wide_int_range_bit_ior): New.
+ (wide_int_range_bit_and): New.
+ (wide_int_range_trunc_mod): New.
+ (extract_range_into_wide_ints): New.
+ (vrp_shift_undefined_p): New.
+ (extract_range_from_multiplicative_op): New.
+ (vrp_can_optimize_bit_op): New.
+ * tree-vrp.h (value_range::dump): New.
+ (wide_int_range_multiplicative_op): New.
+ (wide_int_range_lshift):New.
+ (wide_int_range_shift_undefined_p): New.
+ (wide_int_range_bit_xor): New.
+ (wide_int_range_bit_ior): New.
+ (wide_int_range_bit_and): New.
+ (wide_int_range_trunc_mod): New.
+ (zero_nonzero_bits_from_bounds): Rename to...
+ (wide_int_set_zero_nonzero_bits): ...this.
+ (zero_nonzero_bits_from_vr): Rename to...
+ (vrp_set_zero_nonzero_bits): ...this.
+ (range_easy_mask_min_max): Rename to...
+ (wide_int_range_can_optimize_bit_op): this.
+ * vr-values.c (simplify_bit_ops_using_ranges): Rename
+ zero_nonzero_bits_from_vr into vrp_set_zero_nonzero_bits.
+
+2018-08-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vect_orig_stmt): New function.
+ * tree-vect-data-refs.c (vect_preserves_scalar_order_p): Use it.
+ * tree-vect-loop.c (vect_model_reduction_cost): Likewise.
+ (vect_create_epilog_for_reduction): Likewise.
+ (vectorizable_live_operation): Likewise.
+ * tree-vect-slp.c (vect_find_last_scalar_stmt_in_slp): Likewise.
+ (vect_detect_hybrid_slp_stmts, vect_schedule_slp): Likewise.
+ * tree-vect-stmts.c (vectorizable_call): Likewise.
+ (vectorizable_simd_clone_call, vect_remove_stores): Likewise.
+
+2018-08-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vect_transform_stmt): Remove grouped_store
+ argument.
+ * tree-vect-stmts.c (vect_transform_stmt): Likewise.
+ * tree-vect-loop.c (vect_transform_loop_stmt): Update call accordingly.
+ (vect_transform_loop): Likewise.
+ * tree-vect-slp.c (vect_schedule_slp_instance): Likewise.
+
+2018-08-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vect_schedule_slp): Return void.
+ * tree-vect-slp.c (vect_schedule_slp_instance): Likewise.
+ (vect_schedule_slp): Likewise.
+
+2018-08-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-loop.c (vect_transform_loop_stmt): Remove slp_scheduled
+ argument.
+ (vect_transform_loop): Update calls accordingly. Schedule SLP
+ instances before the main loop, if any exist.
+
+2018-08-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/86749
+ * tree-vect-patterns.c (vect_determine_min_output_precision_1):
+ If the lhs is used in a COND_EXPR, check that it is being used
+ as the "then" or "else" value.
+
+2018-08-01 Tom de Vries <tdevries@suse.de>
+
+ PR target/86800
+ * config/nvptx/nvptx.c (TARGET_HAVE_SPECULATION_SAFE_VALUE): Define to
+ speculation_safe_value_not_needed.
+
+2018-08-01 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-sccvn.c (visit_phi): Compare invariant addresses
+ as base and offset.
+
+2018-08-01 Martin Liska <mliska@suse.cz>
+
+ * value-prof.c (gimple_divmod_fixed_value_transform): Unify
+ format how successful transformation is dumped.
+ (gimple_mod_pow2_value_transform): Likewise.
+ (gimple_mod_subtract_transform): Likewise.
+ (gimple_stringops_transform): Likewise.
+
+2018-08-01 Martin Liska <mliska@suse.cz>
+
+ PR value-prof/35543
+ * value-prof.c (interesting_stringop_to_profile_p):
+ Simplify the code and add BUILT_IN_MEMMOVE.
+ (gimple_stringops_transform): Likewise.
+
+2018-08-01 Sam Tebbs <sam.tebbs@arm.com>
+
+ * config/aarch64/aarch64-simd.md
+ (*aarch64_get_lane_zero_extendsi<mode>): Rename to...
+ (*aarch64_get_lane_zero_extend<GPI:mode><VDQQH:mode>): ... This and
+ use GPI iterator instead of SI mode.
+
+2018-08-01 Richard Earnshaw <rearnsha@arm.com>
+
+ * config/rs6000/rs6000.md (speculation_barrier): Renamed from
+ rs6000_speculation_barrier.
+ * config/rs6000/rs6000.c (rs6000_expand_builtin): Adjust for
+ new barrier pattern name.
+
+2018-08-01 Richard Earnshaw <rearnsha@arm.com>
+
+ * config/i386/i386.md (unspecv): Add UNSPECV_SPECULATION_BARRIER.
+ (speculation_barrier): New insn.
+
+2018-08-01 Richard Biener <rguenther@suse.de>
+
+ PR bootstrap/86724
+ * graphite.h: Include isl/id.h and isl/space.h to allow build
+ with ISL 0.20.
+
+2018-08-01 Jan Willem Jagersma <jwjagersma@gmail.com>
+
+ PR target/86651
+ * dwarf2out.c (dwarf2out_early_finish): Do not generate assembly in LTO
+ mode for COFF targets.
+ * defaults.h (TARGET_COFF): Define.
+ * config/i386/djgpp.h (TARGET_ASM_LTO_START, TARGET_ASM_LTO_END,
+ TARGET_COFF): Define.
+ (i386_djgpp_asm_lto_start, i386_djgpp_asm_lto_end): Declare.
+ * config/i386/djgpp.c (saved_debug_info_level): New static variable.
+ (i386_djgpp_asm_lto_start, i386_djgpp_asm_lto_end): New functions.
+
+2018-07-31 Alexandre Oliva <oliva@adacore.com>
+
+ * gimple-streamer-in.c (input_bb): Restore BB discriminator.
+ * gimple-streamer-out.c (output_bb): Save it.
+ * lto-streamer-in.c (input_struct_function_base): Restore
+ instance discriminator if available. Create map on demand.
+ * lto-streamer-out.c (output_struct_function_base): Save it if
+ available.
+ * final.c (decl_to_instance_map): Document LTO strategy.
+
+2018-07-31 Alexandre Oliva <oliva@adacore.com>
+ Olivier Hainque <hainque@adacore.com>
+
+ * debug.h (decl_to_instance_map_t): New type.
+ (decl_to_instance_map): Declare.
+ (maybe_create_decl_to_instance_map): New inline function.
+ * final.c (bb_discriminator, last_bb_discriminator): New statics,
+ to track basic block discriminators.
+ (final_start_function_1): Initialize them.
+ (final_scan_insn_1): On NOTE_INSN_BASIC_BLOCK, track
+ bb_discriminator.
+ (decl_to_instance_map): New variable.
+ (map_decl_to_instance, maybe_set_discriminator): New functions.
+ (notice_source_line): Set discriminator.
+
+2018-07-31 Ian Lance Taylor <iant@golang.org>
+
+ * targhooks.c (default_have_speculation_safe_value): Add
+ ATTRIBUTE_UNUSED.
+
+2018-07-31 David Malcolm <dmalcolm@redhat.com>
+
+ * dump-context.h: Include "pretty-print.h".
+ (dump_context::refresh_dumps_are_enabled): New decl.
+ (dump_context::emit_item): New decl.
+ (class dump_context): Add fields "m_test_pp" and
+ "m_test_pp_flags".
+ (temp_dump_context::temp_dump_context): Add param "test_pp_flags".
+ (temp_dump_context::get_dumped_text): New decl.
+ (class temp_dump_context): Add field "m_pp".
+ * dumpfile.c (refresh_dumps_are_enabled): Convert to...
+ (dump_context::refresh_dumps_are_enabled): ...and add a test for
+ m_test_pp.
+ (set_dump_file): Update for above change.
+ (set_alt_dump_file): Likewise.
+ (dump_loc): New overload, taking a pretty_printer *.
+ (dump_context::dump_loc): Call end_any_optinfo. Dump the location
+ to any test pretty-printer.
+ (make_item_for_dump_gimple_stmt): New function, adapted from
+ optinfo::add_gimple_stmt.
+ (dump_context::dump_gimple_stmt): Call it, and use the result,
+ eliminating the direct usage of dump_file and alt_dump_file in
+ favor of indirectly using them via emit_item.
+ (make_item_for_dump_gimple_expr): New function, adapted from
+ optinfo::add_gimple_expr.
+ (dump_context::dump_gimple_expr): Call it, and use the result,
+ eliminating the direct usage of dump_file and alt_dump_file in
+ favor of indirectly using them via emit_item.
+ (make_item_for_dump_generic_expr): New function, adapted from
+ optinfo::add_tree.
+ (dump_context::dump_generic_expr): Call it, and use the result,
+ eliminating the direct usage of dump_file and alt_dump_file in
+ favor of indirectly using them via emit_item.
+ (make_item_for_dump_printf_va): New function, adapted from
+ optinfo::add_printf_va.
+ (make_item_for_dump_printf): New function.
+ (dump_context::dump_printf_va): Call make_item_for_dump_printf_va,
+ and use the result, eliminating the direct usage of dump_file and
+ alt_dump_file in favor of indirectly using them via emit_item.
+ (make_item_for_dump_dec): New function.
+ (dump_context::dump_dec): Call it, and use the result,
+ eliminating the direct usage of dump_file and alt_dump_file in
+ favor of indirectly using them via emit_item.
+ (make_item_for_dump_symtab_node): New function, adapted from
+ optinfo::add_symtab_node.
+ (dump_context::dump_symtab_node): Call it, and use the result,
+ eliminating the direct usage of dump_file and alt_dump_file in
+ favor of indirectly using them via emit_item.
+ (dump_context::begin_scope): Reimplement, avoiding direct usage
+ of dump_file and alt_dump_file in favor of indirectly using them
+ via emit_item.
+ (dump_context::emit_item): New member function.
+ (temp_dump_context::temp_dump_context): Add param "test_pp_flags".
+ Set up test pretty-printer on the underlying context. Call
+ refresh_dumps_are_enabled.
+ (temp_dump_context::~temp_dump_context): Call
+ refresh_dumps_are_enabled.
+ (temp_dump_context::get_dumped_text): New member function.
+ (selftest::verify_dumped_text): New function.
+ (ASSERT_DUMPED_TEXT_EQ): New macro.
+ (selftest::test_capture_of_dump_calls): Run all tests twice, with
+ and then without optinfo enabled. Add uses of
+ ASSERT_DUMPED_TEXT_EQ to all tests. Add test of nested scopes.
+ * dumpfile.h: Update comment for the dump_* API.
+ * optinfo-emit-json.cc
+ (selftest::test_building_json_from_dump_calls): Update for new
+ param for temp_dump_context ctor.
+ * optinfo.cc (optinfo_item::optinfo_item): Remove "owned" param
+ and "m_owned" field.
+ (optinfo_item::~optinfo_item): Likewise.
+ (optinfo::add_item): New member function.
+ (optinfo::emit): Update comment.
+ (optinfo::add_string): Delete.
+ (optinfo::add_printf): Delete.
+ (optinfo::add_printf_va): Delete.
+ (optinfo::add_gimple_stmt): Delete.
+ (optinfo::add_gimple_expr): Delete.
+ (optinfo::add_tree): Delete.
+ (optinfo::add_symtab_node): Delete.
+ (optinfo::add_dec): Delete.
+ * optinfo.h (class dump_context): New forward decl.
+ (optinfo::add_item): New decl.
+ (optinfo::add_string): Delete.
+ (optinfo::add_printf): Delete.
+ (optinfo::add_printf_va): Delete.
+ (optinfo::add_gimple_stmt): Delete.
+ (optinfo::add_gimple_expr): Delete.
+ (optinfo::add_tree): Delete.
+ (optinfo::add_symtab_node): Delete.
+ (optinfo::add_dec): Delete.
+ (optinfo::add_poly_int): Delete.
+ (optinfo_item::optinfo_item): Remove "owned" param.
+ (class optinfo_item): Remove field "m_owned".
+
+2018-07-31 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ PR middle-end/86705
+ * gcc/cfgexpand.c (set_parm_rtl): Use the alignment of Pmode when
+ MAX_SUPPORTED_STACK_ALIGNMENT would otherwise be exceeded by the
+ requested variable alignment.
+ (expand_one_ssa_partition): Likewise.
+ (expand_one_var): Likewise.
+
+2018-07-31 Richard Earnshaw <rearnsha@arm.com>
+
+ * config/pdp11/pdp11.c (TARGET_HAVE_SPECULATION_SAFE_VALUE): Redefine
+ to speculation_safe_value_not_needed.
+
+2018-07-31 Richard Earnshaw <rearnsha@arm.com>
+
+ * targhooks.h (speculation_safe_value_not_needed): New prototype.
+ * targhooks.c (speculation_safe_value_not_needed): New function.
+ * target.def (have_speculation_safe_value): Update documentation.
+ * doc/tm.texi: Regenerated.
+
+2018-07-31 Richard Earnshaw <rearnsha@arm.com>
+
+ * config/aarch64/iterators.md (ALLI_TI): New iterator.
+ * config/aarch64/aarch64.md (despeculate_copy<ALLI_TI:mode>): New
+ expand.
+ (despeculate_copy<ALLI:mode>_insn): New insn.
+ (despeculate_copyti_insn): New insn.
+ (despeculate_simple<ALLI:mode>): New insn
+ (despeculate_simpleti): New insn.
+ * config/aarch64/aarch64.c (aarch64_speculation_safe_value): New
+ function.
+ (TARGET_SPECULATION_SAFE_VALUE): Redefine to
+ aarch64_speculation_safe_value.
+ (aarch64_print_operand): Handle const0_rtx in modifier 'H'.
+
+2018-07-31 Richard Earnshaw <rearnsha@arm.com>
+
+ * config/aarch64/aarch64-speculation.cc: New file.
+ * config/aarch64/aarch64-passes.def (pass_track_speculation): Add
+ before pass_reorder_blocks.
+ * config/aarch64/aarch64-protos.h (make_pass_track_speculation): Add
+ prototype.
+ * config/aarch64/aarch64.c (aarch64_conditional_register_usage): Fix
+ X14 and X15 when tracking speculation.
+ * config/aarch64/aarch64.md (register name constants): Add
+ SPECULATION_TRACKER_REGNUM and SPECULATION_SCRATCH_REGNUM.
+ (unspec): Add UNSPEC_SPECULATION_TRACKER.
+ (speculation_barrier): New insn attribute.
+ (cmp<mode>): Allow SP in comparisons.
+ (speculation_tracker): New insn.
+ (speculation_barrier): Add speculation_barrier attribute.
+ * config/aarch64/t-aarch64: Add make rule for aarch64-speculation.o.
+ * config.gcc (aarch64*-*-*): Add aarch64-speculation.o to extra_objs.
+ * doc/invoke.texi (AArch64 Options): Document -mtrack-speculation.
+
+2018-07-31 Richard Earnshaw <rearnsha@arm.com>
+
+ * config/aarch64/aarch64.md (cb<optab><mode>1): Disable when
+ aarch64_track_speculation is true.
+ (tb<optab><mode>1): Likewise.
+ * config/aarch64/aarch64.c (aarch64_split_compare_regs): Do not
+ generate CB[N]Z when tracking speculation.
+ (aarch64_split_compare_and_swap): Likewise.
+ (aarch64_split_atomic_op): Likewise.
+
+2018-07-31 Richard Earnshaw <rearnsha@arm.com>
+
+ * config/aarch64/aarch64.opt (mtrack-speculation): New target option.
+
+2018-07-31 Richard Earnshaw <rearnsha@arm.com>
+
+ * config/aarch64.md (unspecv): Add UNSPECV_SPECULAION_BARRIER.
+ (speculation_barrier): New insn.
+
+2018-07-31 Richard Earnshaw <rearnsha@arm.com>
+
+ * config/arm/unspecs.md (unspecv): Add VUNSPEC_SPECULATION_BARRIER.
+ * config/arm/arm.md (speculation_barrier): New expand.
+ (speculation_barrier_insn): New pattern.
+
+2018-07-31 Richard Earnshaw <rearnsha@arm.com>
+
+ * builtin-types.def (BT_FN_PTR_PTR_VAR): New function type.
+ (BT_FN_I1_I1_VAR, BT_FN_I2_I2_VAR, BT_FN_I4_I4_VAR): Likewise.
+ (BT_FN_I8_I8_VAR, BT_FN_I16_I16_VAR): Likewise.
+ * builtin-attrs.def (ATTR_NOVOPS_NOTHROW_LEAF_LIST): New attribute
+ list.
+ * builtins.def (BUILT_IN_SPECULATION_SAFE_VALUE_N): New builtin.
+ (BUILT_IN_SPECULATION_SAFE_VALUE_PTR): New internal builtin.
+ (BUILT_IN_SPECULATION_SAFE_VALUE_1): Likewise.
+ (BUILT_IN_SPECULATION_SAFE_VALUE_2): Likewise.
+ (BUILT_IN_SPECULATION_SAFE_VALUE_4): Likewise.
+ (BUILT_IN_SPECULATION_SAFE_VALUE_8): Likewise.
+ (BUILT_IN_SPECULATION_SAFE_VALUE_16): Likewise.
+ * builtins.c (expand_speculation_safe_value): New function.
+ (expand_builtin): Call it.
+ * doc/cpp.texi: Document predefine __HAVE_SPECULATION_SAFE_VALUE.
+ * doc/extend.texi: Document __builtin_speculation_safe_value.
+ * doc/md.texi: Document "speculation_barrier" pattern.
+ * doc/tm.texi.in: Pull in TARGET_SPECULATION_SAFE_VALUE and
+ TARGET_HAVE_SPECULATION_SAFE_VALUE.
+ * doc/tm.texi: Regenerated.
+ * target.def (have_speculation_safe_value, speculation_safe_value): New
+ hooks.
+ * targhooks.c (default_have_speculation_safe_value): New function.
+ (default_speculation_safe_value): New function.
+ * targhooks.h (default_have_speculation_safe_value): Add prototype.
+ (default_speculation_safe_value): Add prototype.
+
+2018-07-31 David Malcolm <dmalcolm@redhat.com>
+
+ * dump-context.h (dump_context::dump_loc): New decl.
+ * dumpfile.c (dump_context::dump_loc): New member function.
+ (dump_context::dump_gimple_stmt_loc): Reimplement using dump_loc
+ and dump_gimple_stmt.
+ (dump_context::dump_gimple_expr_loc): Likewise, using
+ dump_gimple_expr.
+ (dump_context::dump_generic_expr_loc): Likewise, using
+ dump_generic_expr.
+ (dump_context::dump_printf_loc_va): Likewise, using
+ dump_printf_va.
+ (dump_context::begin_scope): Explicitly using the global function
+ "dump_loc", rather than the member function.
+
+2018-07-31 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/86741
+ * tree-vrp.c (vrp_prop::check_mem_ref): Avoid incomplete types.
+
+2018-07-31 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * config/s390/s390.c (s390_expand_setmem): Make the unrolling to
+ depend on whether prefetch instructions will be emitted or not.
+ Use TARGET_SETMEM_PFD for checking whether prefetch instructions
+ will be emitted or not.
+ * config/s390/s390.h (TARGET_SETMEM_PREFETCH_DISTANCE)
+ (TARGET_SETMEM_PFD): New macros.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (stmt_vec_info): Turn back into a typedef.
+ (NULL_STMT_VEC_INFO): Delete.
+ (stmt_vec_info::operator*): Likewise.
+ (stmt_vec_info::operator gimple *): Likewise.
+ * tree-vect-loop.c (vectorizable_reduction): Use NULL instead
+ of NULL_STMT_VEC_INFO.
+ * tree-vect-patterns.c (vect_init_pattern_stmt): Likewise.
+ (vect_reassociating_reduction_p): Likewise.
+ * tree-vect-stmts.c (vect_build_gather_load_calls): Likewise.
+ (vectorizable_store): Likewise.
+ * tree-vectorizer.c (vec_info::set_vinfo_for_stmt): Likewise.
+ (vec_info::free_stmt_vec_infos): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vect_stmt_in_region_p): Delete.
+ * tree-vectorizer.c (vect_stmt_in_region_p): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vec_info::new_vinfo_for_stmt)
+ (vec_info::set_vinfo_for_stmt, vec_info::free_stmt_vec_infos)
+ (vec_info::free_stmt_vec_info): New private member functions.
+ (set_stmt_vec_info_vec, free_stmt_vec_infos, vinfo_for_stmt)
+ (set_vinfo_for_stmt, new_stmt_vec_info, free_stmt_vec_info): Delete.
+ * tree-parloops.c (gather_scalar_reductions): Remove calls to
+ set_stmt_vec_info_vec and free_stmt_vec_infos.
+ * tree-vect-loop.c (_loop_vec_info): Remove call to
+ set_stmt_vec_info_vec.
+ * tree-vect-stmts.c (new_stmt_vec_info, set_stmt_vec_info_vec)
+ (free_stmt_vec_infos, free_stmt_vec_info): Delete in favor of...
+ * tree-vectorizer.c (vec_info::new_stmt_vec_info)
+ (vec_info::set_vinfo_for_stmt, vec_info::free_stmt_vec_infos)
+ (vec_info::free_stmt_vec_info): ...these new functions. Remove
+ assignments in {vec_info::,}new_stmt_vec_info that are redundant
+ with the clearing in the xcalloc.
+ (stmt_vec_info_vec): Delete.
+ (vec_info::vec_info): Don't call set_stmt_vec_info_vec.
+ (vectorize_loops): Likewise.
+ (vec_info::~vec_info): Remove argument from call to
+ free_stmt_vec_infos.
+ (vec_info::add_stmt): Remove vinfo argument from call to
+ new_stmt_vec_info.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (free_stmt_vec_info): Take a stmt_vec_info
+ rather than a gimple stmt.
+ * tree-vect-stmts.c (free_stmt_vec_info): Likewise. Don't free
+ information for pattern statements when passed the original
+ statement; instead wait to be passed the pattern statement itself.
+ Don't call set_vinfo_for_stmt here.
+ (free_stmt_vec_infos): Update call to free_stmt_vec_info.
+ * tree-vect-loop.c (_loop_vec_info::~loop_vec_info): Don't free
+ stmt_vec_infos here.
+ * tree-vect-slp.c (_bb_vec_info::~bb_vec_info): Likewise.
+ * tree-vectorizer.c (vec_info::remove_stmt): Nullify the statement's
+ stmt_vec_infos entry.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vec_info::replace_stmt): Declare.
+ * tree-vectorizer.c (vec_info::replace_stmt): New function.
+ * tree-vect-slp.c (vect_remove_slp_scalar_calls): Use it.
+ * tree-vect-stmts.c (vectorizable_call): Likewise.
+ (vectorizable_simd_clone_call): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vec_info::remove_stmt): Declare.
+ * tree-vectorizer.c (vec_info::remove_stmt): New function.
+ * tree-vect-loop-manip.c (vect_set_loop_condition): Use it.
+ * tree-vect-loop.c (vect_transform_loop): Likewise.
+ * tree-vect-slp.c (vect_schedule_slp): Likewise.
+ * tree-vect-stmts.c (vect_remove_stores): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vec_info::lookup_dr): New member function.
+ (vect_dr_stmt): Delete.
+ * tree-vectorizer.c (vec_info::lookup_dr): New function.
+ * tree-vect-loop-manip.c (vect_update_inits_of_drs): Use it instead
+ of DR_VECT_AUX.
+ * tree-vect-data-refs.c (vect_analyze_possibly_independent_ddr)
+ (vect_analyze_data_ref_dependence, vect_record_base_alignments)
+ (vect_verify_datarefs_alignment, vect_peeling_supportable)
+ (vect_analyze_data_ref_accesses, vect_prune_runtime_alias_test_list)
+ (vect_analyze_data_refs): Likewise.
+ (vect_slp_analyze_data_ref_dependence): Likewise. Take a vec_info
+ argument.
+ (vect_find_same_alignment_drs): Likewise.
+ (vect_slp_analyze_node_dependences): Update calls accordingly.
+ (vect_analyze_data_refs_alignment): Likewise. Use vec_info::lookup_dr
+ instead of DR_VECT_AUX.
+ (vect_get_peeling_costs_all_drs): Take a loop_vec_info instead
+ of a vector data references. Use vec_info::lookup_dr instead of
+ DR_VECT_AUX.
+ (vect_peeling_hash_get_lowest_cost): Update calls accordingly.
+ (vect_enhance_data_refs_alignment): Likewise. Use vec_info::lookup_dr
+ instead of DR_VECT_AUX.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (_loop_vec_info::unaligned_dr): Change to
+ dr_vec_info.
+ * tree-vect-data-refs.c (vect_enhance_data_refs_alignment): Update
+ accordingly.
+ * tree-vect-loop.c (vect_analyze_loop_2): Likewise.
+ * tree-vect-loop-manip.c (get_misalign_in_elems): Likewise.
+ (vect_gen_prolog_loop_niters): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (set_dr_misalignment, dr_misalignment)
+ (DR_TARGET_ALIGNMENT, aligned_access_p, known_alignment_for_access_p)
+ (vect_known_alignment_in_bytes, vect_dr_behavior)
+ (vect_get_scalar_dr_size): Take references as dr_vec_infos
+ instead of data_references. Update calls to other routines for
+ which the same change has been made.
+ * tree-vect-data-refs.c (vect_preserves_scalar_order_p): Take
+ dr_vec_infos instead of stmt_vec_infos.
+ (vect_analyze_data_ref_dependence): Update call accordingly.
+ (vect_slp_analyze_data_ref_dependence)
+ (vect_record_base_alignments): Use DR_VECT_AUX.
+ (vect_calculate_target_alignment, vect_compute_data_ref_alignment)
+ (vect_update_misalignment_for_peel, verify_data_ref_alignment)
+ (vector_alignment_reachable_p, vect_get_data_access_cost)
+ (vect_peeling_supportable, vect_analyze_group_access_1)
+ (vect_analyze_group_access, vect_analyze_data_ref_access)
+ (vect_vfa_segment_size, vect_vfa_access_size, vect_vfa_align)
+ (vect_compile_time_alias, vect_small_gap_p)
+ (vectorizable_with_step_bound_p, vect_duplicate_ssa_name_ptr_info):
+ (vect_supportable_dr_alignment): Take references as dr_vec_infos
+ instead of data_references. Update calls to other routines for
+ which the same change has been made.
+ (vect_verify_datarefs_alignment, vect_get_peeling_costs_all_drs)
+ (vect_find_same_alignment_drs, vect_analyze_data_refs_alignment)
+ (vect_slp_analyze_and_verify_node_alignment)
+ (vect_analyze_data_ref_accesses, vect_prune_runtime_alias_test_list)
+ (vect_create_addr_base_for_vector_ref, vect_create_data_ref_ptr)
+ (vect_setup_realignment): Use dr_vec_infos. Update calls after
+ above changes.
+ (_vect_peel_info::dr): Replace with...
+ (_vect_peel_info::dr_info): ...this new field.
+ (vect_peeling_hash_get_most_frequent)
+ (vect_peeling_hash_choose_best_peeling): Update accordingly.
+ (vect_peeling_hash_get_lowest_cost):
+ (vect_enhance_data_refs_alignment): Likewise. Update calls to other
+ routines for which the same change has been made.
+ (vect_peeling_hash_insert): Likewise. Take a dr_vec_info instead of a
+ data_reference.
+ * tree-vect-loop-manip.c (get_misalign_in_elems)
+ (vect_gen_prolog_loop_niters): Use dr_vec_infos. Update calls after
+ above changes.
+ * tree-vect-loop.c (vect_analyze_loop_2): Likewise.
+ * tree-vect-stmts.c (vect_get_store_cost, vect_get_load_cost)
+ (vect_truncate_gather_scatter_offset, compare_step_with_zero)
+ (get_group_load_store_type, get_negative_load_store_type)
+ (vect_get_data_ptr_increment, vectorizable_store)
+ (vectorizable_load): Likewise.
+ (ensure_base_align): Take a dr_vec_info instead of a data_reference.
+ Update calls to other routines for which the same change has been made.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vec_info::move_dr): New member function.
+ (dataref_aux): Rename to...
+ (dr_vec_info): ...this and add "dr" and "stmt" fields.
+ (_stmt_vec_info::dr_aux): Update accordingly.
+ (_stmt_vec_info::data_ref_info): Delete.
+ (STMT_VINFO_GROUPED_ACCESS, DR_GROUP_FIRST_ELEMENT)
+ (DR_GROUP_NEXT_ELEMENT, DR_GROUP_SIZE, DR_GROUP_STORE_COUNT)
+ (DR_GROUP_GAP, DR_GROUP_SAME_DR_STMT, REDUC_GROUP_FIRST_ELEMENT):
+ (REDUC_GROUP_NEXT_ELEMENT, REDUC_GROUP_SIZE): Use dr_aux.dr instead
+ of data_ref.
+ (STMT_VINFO_DATA_REF): Likewise. Turn into an lvalue.
+ (STMT_VINFO_DR_INFO): New macro.
+ (DR_VECT_AUX): Use STMT_VINFO_DR_INKFO and vect_dr_stmt.
+ (set_dr_misalignment): Update after rename of dataref_aux.
+ (vect_dr_stmt): Move earlier in file. Return dr_aux.stmt.
+ * tree-vect-stmts.c (new_stmt_vec_info): Remove redundant
+ initialization of STMT_VINFO_DATA_REF.
+ * tree-vectorizer.c (vec_info::move_dr): New function.
+ * tree-vect-patterns.c (vect_recog_bool_pattern)
+ (vect_recog_mask_conversion_pattern)
+ (vect_recog_gather_scatter_pattern): Use it.
+ * tree-vect-data-refs.c (vect_analyze_data_refs): Initialize
+ the "dr" and "stmt" fields of dr_vec_info instead of
+ STMT_VINFO_DATA_REF.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (_stmt_vec_info::pattern_stmt_p): New field.
+ (is_pattern_stmt_p): Use it.
+ * tree-vect-patterns.c (vect_init_pattern_stmt): Set pattern_stmt_p
+ on pattern statements.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-patterns.c (vect_mark_pattern_stmts): Take the
+ original stmt as a stmt_vec_info rather than a gimple stmt.
+ (vect_pattern_recog_1): Take the statement directly as a
+ stmt_vec_info, rather than via a gimple_stmt_iterator.
+ Update call to vect_mark_pattern_stmts.
+ (vect_pattern_recog): Update calls accordingly.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vect_get_vec_defs_for_stmt_copy)
+ (vect_get_vec_def_for_stmt_copy): Take a vec_info rather than
+ a vect_def_type for the first argument.
+ * tree-vect-stmts.c (vect_get_vec_defs_for_stmt_copy): Likewise.
+ (vect_get_vec_def_for_stmt_copy): Likewise. Return the original
+ operand if it isn't defined by a vectorized statement.
+ (vect_build_gather_load_calls): Remove the mask_dt argument and
+ update calls to vect_get_vec_def_for_stmt_copy.
+ (vectorizable_bswap): Likewise the dt argument.
+ (vectorizable_call): Update calls to vectorizable_bswap and
+ vect_get_vec_def_for_stmt_copy.
+ (vectorizable_simd_clone_call, vectorizable_assignment)
+ (vectorizable_shift, vectorizable_operation, vectorizable_condition)
+ (vectorizable_comparison): Update calls to
+ vect_get_vec_def_for_stmt_copy.
+ (vectorizable_store): Likewise. Remove now-unnecessary calls to
+ vect_is_simple_use.
+ (vect_get_loop_based_defs): Remove dt argument and update call
+ to vect_get_vec_def_for_stmt_copy.
+ (vectorizable_conversion): Update calls to vect_get_loop_based_defs
+ and vect_get_vec_def_for_stmt_copy.
+ (vectorizable_load): Update calls to vect_build_gather_load_calls
+ and vect_get_vec_def_for_stmt_copy.
+ * tree-vect-loop.c (vect_create_epilog_for_reduction)
+ (vectorizable_reduction, vectorizable_live_operation): Update calls
+ to vect_get_vec_def_for_stmt_copy.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-data-refs.c (vect_record_base_alignment): Replace vec_info
+ and gimple stmt arguments with a stmt_vec_info.
+ (vect_record_base_alignments): Update calls accordingly.
+ * tree-vect-slp.c (vect_record_max_nunits): Replace vec_info
+ and gimple stmt arguments with a stmt_vec_info.
+ (vect_build_slp_tree_1): Remove vinfo argument and update call
+ to vect_record_max_nunits.
+ (vect_build_slp_tree_2): Update calls to vect_build_slp_tree_1
+ and vect_record_max_nunits.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (nested_in_vect_loop_p): Move further down
+ file and take a stmt_vec_info instead of a gimple stmt.
+ (supportable_widening_operation, vect_finish_replace_stmt)
+ (vect_finish_stmt_generation, vect_get_store_rhs)
+ (vect_get_vec_def_for_operand_1, vect_get_vec_def_for_operand)
+ (vect_get_vec_defs, vect_init_vector, vect_transform_stmt)
+ (vect_remove_stores, vect_analyze_stmt, vectorizable_condition)
+ (vect_get_smallest_scalar_type, vect_check_gather_scatter)
+ (vect_create_data_ref_ptr, bump_vector_ptr)
+ (vect_permute_store_chain, vect_setup_realignment)
+ (vect_transform_grouped_load, vect_record_grouped_load_vectors)
+ (vect_create_addr_base_for_vector_ref, vectorizable_live_operation)
+ (vectorizable_reduction, vectorizable_induction)
+ (get_initial_def_for_reduction, is_simple_and_all_uses_invariant)
+ (vect_get_place_in_interleaving_chain): Take stmt_vec_infos rather
+ than gimple stmts as arguments.
+ * tree-vect-data-refs.c (vect_get_smallest_scalar_type)
+ (vect_preserves_scalar_order_p, vect_slp_analyze_node_dependences)
+ (can_group_stmts_p, vect_check_gather_scatter)
+ (vect_create_addr_base_for_vector_ref, vect_create_data_ref_ptr)
+ (bump_vector_ptr, vect_permute_store_chain, vect_setup_realignment)
+ (vect_permute_load_chain, vect_shift_permute_load_chain)
+ (vect_transform_grouped_load)
+ (vect_record_grouped_load_vectors): Likewise.
+ * tree-vect-loop.c (vect_fixup_reduc_chain)
+ (get_initial_def_for_reduction, vect_create_epilog_for_reduction)
+ (vectorize_fold_left_reduction, is_nonwrapping_integer_induction)
+ (vectorizable_reduction, vectorizable_induction)
+ (vectorizable_live_operation, vect_loop_kill_debug_uses): Likewise.
+ * tree-vect-patterns.c (type_conversion_p, adjust_bool_stmts)
+ (vect_get_load_store_mask): Likewise.
+ * tree-vect-slp.c (vect_get_place_in_interleaving_chain)
+ (vect_analyze_slp_instance, vect_mask_constant_operand_p): Likewise.
+ * tree-vect-stmts.c (vect_mark_relevant)
+ (is_simple_and_all_uses_invariant)
+ (exist_non_indexing_operands_for_use_p, process_use)
+ (vect_init_vector_1, vect_init_vector, vect_get_vec_def_for_operand_1)
+ (vect_get_vec_def_for_operand, vect_get_vec_defs)
+ (vect_finish_stmt_generation_1, vect_finish_replace_stmt)
+ (vect_finish_stmt_generation, vect_truncate_gather_scatter_offset)
+ (compare_step_with_zero, vect_get_store_rhs, get_group_load_store_type)
+ (get_negative_load_store_type, get_load_store_type)
+ (vect_check_load_store_mask, vect_check_store_rhs)
+ (vect_build_gather_load_calls, vect_get_strided_load_store_ops)
+ (vectorizable_bswap, vectorizable_call, vectorizable_simd_clone_call)
+ (vect_create_vectorized_demotion_stmts, vectorizable_conversion)
+ (vectorizable_assignment, vectorizable_shift, vectorizable_operation)
+ (get_group_alias_ptr_type, vectorizable_store, hoist_defs_of_uses)
+ (vectorizable_load, vectorizable_condition, vectorizable_comparison)
+ (vect_analyze_stmt, vect_transform_stmt, vect_remove_stores)
+ (supportable_widening_operation): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-data-refs.c (vect_describe_gather_scatter_call): Take
+ a stmt_vec_info instead of a gcall.
+ (vect_check_gather_scatter): Update call accordingly.
+ * tree-vect-loop-manip.c (iv_phi_p): Take a stmt_vec_info instead
+ of a gphi.
+ (vect_can_advance_ivs_p, vect_update_ivs_after_vectorizer)
+ (slpeel_update_phi_nodes_for_loops):): Update calls accordingly.
+ * tree-vect-loop.c (vect_transform_loop_stmt): Take a stmt_vec_info
+ instead of a gimple stmt.
+ (vect_transform_loop): Update calls accordingly.
+ * tree-vect-slp.c (vect_split_slp_store_group): Take and return
+ stmt_vec_infos instead of gimple stmts.
+ (vect_analyze_slp_instance): Update use accordingly.
+ * tree-vect-stmts.c (read_vector_array, write_vector_array)
+ (vect_clobber_variable, vect_stmt_relevant_p, permute_vec_elements)
+ (vect_use_strided_gather_scatters_p, vect_build_all_ones_mask)
+ (vect_build_zero_merge_argument, vect_get_gather_scatter_ops)
+ (vect_gen_widened_results_half, vect_get_loop_based_defs)
+ (vect_create_vectorized_promotion_stmts, can_vectorize_live_stmts):
+ Take a stmt_vec_info instead of a gimple stmt and pass stmt_vec_infos
+ down to subroutines.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-loop.c (vect_analyze_scalar_cycles_1): Change the type
+ of the worklist from a vector of gimple stmts to a vector of
+ stmt_vec_infos.
+ * tree-vect-stmts.c (vect_mark_relevant, process_use)
+ (vect_mark_stmts_to_be_vectorized): Likewise
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-loop.c (vect_analyze_loop_operations): Look up the
+ statement before passing it to vect_analyze_stmt.
+ (vect_create_epilog_for_reduction): Use a stmt_vec_info to walk
+ the chain of phi vector definitions. Track the exit phi via its
+ stmt_vec_info.
+ (vectorizable_reduction): Set cond_stmt_vinfo directly from the
+ STMT_VINFO_REDUC_DEF.
+ * tree-vect-slp.c (vect_get_place_in_interleaving_chain): Use
+ stmt_vec_infos to handle the statement chains.
+ (vect_get_slp_defs): Record the first statement in the node
+ using a stmt_vec_info.
+ * tree-vect-stmts.c (vect_mark_stmts_to_be_vectorized): Look up
+ statements here and pass their stmt_vec_info down to subroutines.
+ (vect_init_vector_1): Hoist call to vinfo_for_stmt and pass it
+ down to vect_finish_stmt_generation.
+ (vect_init_vector, vect_get_vec_defs, vect_finish_replace_stmt)
+ (vect_finish_stmt_generation): Call vinfo_for_stmt and pass
+ stmt_vec_infos to subroutines.
+ (vect_remove_stores): Use stmt_vec_infos to handle the statement
+ chains.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-data-refs.c (vect_slp_analyze_node_dependences):
+ (vect_check_gather_scatter, vect_create_data_ref_ptr, bump_vector_ptr)
+ (vect_permute_store_chain, vect_setup_realignment)
+ (vect_permute_load_chain, vect_shift_permute_load_chain)
+ (vect_transform_grouped_load): Use stmt_vec_info rather than gimple
+ stmts internally, and when passing values to other vectorizer routines.
+ * tree-vect-loop-manip.c (vect_can_advance_ivs_p): Likewise.
+ * tree-vect-loop.c (vect_analyze_scalar_cycles_1)
+ (vect_analyze_loop_operations, get_initial_def_for_reduction)
+ (vect_create_epilog_for_reduction, vectorize_fold_left_reduction)
+ (vectorizable_reduction, vectorizable_induction)
+ (vectorizable_live_operation, vect_transform_loop_stmt)
+ (vect_transform_loop): Likewise.
+ * tree-vect-patterns.c (vect_reassociating_reduction_p)
+ (vect_recog_widen_op_pattern, vect_recog_mixed_size_cond_pattern)
+ (vect_recog_bool_pattern, vect_recog_gather_scatter_pattern): Likewise.
+ * tree-vect-slp.c (vect_analyze_slp_instance): Likewise.
+ (vect_slp_analyze_node_operations_1): Likewise.
+ * tree-vect-stmts.c (vect_mark_relevant, process_use)
+ (exist_non_indexing_operands_for_use_p, vect_init_vector_1)
+ (vect_mark_stmts_to_be_vectorized, vect_get_vec_def_for_operand)
+ (vect_finish_stmt_generation_1, get_group_load_store_type)
+ (get_load_store_type, vect_build_gather_load_calls)
+ (vectorizable_bswap, vectorizable_call, vectorizable_simd_clone_call)
+ (vect_create_vectorized_demotion_stmts, vectorizable_conversion)
+ (vectorizable_assignment, vectorizable_shift, vectorizable_operation)
+ (vectorizable_store, vectorizable_load, vectorizable_condition)
+ (vectorizable_comparison, vect_analyze_stmt, vect_transform_stmt)
+ (supportable_widening_operation): Likewise.
+ (vect_get_vector_types_for_stmt): Likewise.
+ * tree-vectorizer.h (vect_dr_behavior): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-data-refs.c (vect_analyze_data_ref_dependence)
+ (vect_slp_analyze_node_dependences, vect_analyze_data_ref_accesses)
+ (vect_permute_store_chain, vect_permute_load_chain)
+ (vect_shift_permute_load_chain, vect_transform_grouped_load): Avoid
+ repeated stmt_vec_info lookups.
+ * tree-vect-loop-manip.c (vect_can_advance_ivs_p): Likewise.
+ (vect_update_ivs_after_vectorizer): Likewise.
+ * tree-vect-loop.c (vect_is_simple_reduction): Likewise.
+ (vect_create_epilog_for_reduction, vectorizable_reduction): Likewise.
+ * tree-vect-patterns.c (adjust_bool_stmts): Likewise.
+ * tree-vect-slp.c (vect_analyze_slp_instance): Likewise.
+ (vect_bb_slp_scalar_cost): Likewise.
+ * tree-vect-stmts.c (get_group_alias_ptr_type): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-data-refs.c (vect_check_gather_scatter): Pass the
+ gcall rather than the generic gimple stmt to gimple_call_internal_fn.
+ (vect_get_smallest_scalar_type, can_group_stmts_p): Use dyn_cast
+ to get gassigns and gcalls, rather than operating on generc gimple
+ stmts.
+ * tree-vect-stmts.c (exist_non_indexing_operands_for_use_p)
+ (vect_mark_stmts_to_be_vectorized, vectorizable_store)
+ (vectorizable_load, vect_analyze_stmt): Likewise.
+ * tree-vect-loop.c (vectorizable_reduction): Likewise gphi.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (get_earlier_stmt, get_later_stmt): Take and
+ return stmt_vec_infos rather than gimple stmts. Do not accept
+ null arguments.
+ (vect_find_last_scalar_stmt_in_slp): Return a stmt_vec_info instead
+ of a gimple stmt.
+ * tree-vect-slp.c (vect_find_last_scalar_stmt_in_slp): Likewise.
+ Update use of get_later_stmt.
+ (vect_get_constant_vectors): Update call accordingly.
+ (vect_schedule_slp_instance): Likewise
+ * tree-vect-data-refs.c (vect_slp_analyze_node_dependences): Likewise.
+ (vect_slp_analyze_instance_dependence): Likewise.
+ (vect_preserves_scalar_order_p): Update use of get_earlier_stmt.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (stmt_info_for_cost::stmt): Replace with...
+ (stmt_info_for_cost::stmt_info): ...this new field.
+ (add_stmt_costs): Update accordingly.
+ * tree-vect-loop.c (vect_compute_single_scalar_iteration_cost)
+ (vect_get_known_peeling_cost): Likewise.
+ (vect_estimate_min_profitable_iters): Likewise.
+ * tree-vect-stmts.c (record_stmt_cost): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (_loop_vec_info::may_misalign_stmts): Change
+ from an auto_vec<gimple *> to an auto_vec<stmt_vec_info>.
+ * tree-vect-data-refs.c (vect_enhance_data_refs_alignment): Update
+ accordingly.
+ * tree-vect-loop-manip.c (vect_create_cond_for_align_checks): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (_stmt_vec_info::same_dr_stmt): Change from
+ a gimple stmt to a stmt_vec_info.
+ * tree-vect-stmts.c (vectorizable_load): Update accordingly.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vec_info::grouped_stores): Change from
+ an auto_vec<gimple *> to an auto_vec<stmt_vec_info>.
+ (_loop_vec_info::reduction_chains): Likewise.
+ * tree-vect-loop.c (vect_fixup_scalar_cycles_with_patterns): Update
+ accordingly.
+ * tree-vect-slp.c (vect_analyze_slp): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (_stmt_vec_info::first_element): Change from
+ a gimple stmt to a stmt_vec_info.
+ (_stmt_vec_info::next_element): Likewise.
+ * tree-vect-data-refs.c (vect_update_misalignment_for_peel)
+ (vect_slp_analyze_and_verify_node_alignment)
+ (vect_analyze_group_access_1, vect_analyze_group_access)
+ (vect_small_gap_p, vect_prune_runtime_alias_test_list)
+ (vect_create_data_ref_ptr, vect_record_grouped_load_vectors)
+ (vect_supportable_dr_alignment): Update accordingly.
+ * tree-vect-loop.c (vect_fixup_reduc_chain): Likewise.
+ (vect_fixup_scalar_cycles_with_patterns, vect_is_slp_reduction)
+ (vect_is_simple_reduction, vectorizable_reduction): Likewise.
+ * tree-vect-patterns.c (vect_reassociating_reduction_p): Likewise.
+ * tree-vect-slp.c (vect_build_slp_tree_1)
+ (vect_attempt_slp_rearrange_stmts, vect_supported_load_permutation_p)
+ (vect_split_slp_store_group, vect_analyze_slp_instance)
+ (vect_analyze_slp, vect_transform_slp_perm_load): Likewise.
+ * tree-vect-stmts.c (vect_model_store_cost, vect_model_load_cost)
+ (get_group_load_store_type, get_load_store_type)
+ (get_group_alias_ptr_type, vectorizable_store, vectorizable_load)
+ (vect_transform_stmt, vect_remove_stores): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vect_dr_stmt): Return a stmt_vec_info rather
+ than a gimple stmt.
+ * tree-vect-data-refs.c (vect_analyze_data_ref_dependence)
+ (vect_slp_analyze_data_ref_dependence, vect_record_base_alignments)
+ (vect_calculate_target_alignmentm, vect_compute_data_ref_alignment)
+ (vect_update_misalignment_for_peel, vect_verify_datarefs_alignment)
+ (vector_alignment_reachable_p, vect_get_data_access_cost)
+ (vect_get_peeling_costs_all_drs, vect_peeling_hash_get_lowest_cost)
+ (vect_peeling_supportable, vect_enhance_data_refs_alignment)
+ (vect_find_same_alignment_drs, vect_analyze_data_refs_alignment)
+ (vect_analyze_group_access_1, vect_analyze_group_access)
+ (vect_analyze_data_ref_access, vect_analyze_data_ref_accesses)
+ (vect_vfa_access_size, vect_small_gap_p, vect_analyze_data_refs)
+ (vect_supportable_dr_alignment): Remove vinfo_for_stmt from the
+ result of vect_dr_stmt and use the stmt_vec_info instead of
+ the associated gimple stmt.
+ * tree-vect-loop-manip.c (get_misalign_in_elems): Likewise.
+ (vect_gen_prolog_loop_niters): Likewise.
+ * tree-vect-loop.c (vect_analyze_loop_2): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (_slp_tree::stmts): Change from a vec<gimple *>
+ to a vec<stmt_vec_info>.
+ * tree-vect-slp.c (vect_free_slp_tree): Update accordingly.
+ (vect_create_new_slp_node): Take a vec<gimple *> instead of a
+ vec<stmt_vec_info>.
+ (_slp_oprnd_info::def_stmts): Change from a vec<gimple *>
+ to a vec<stmt_vec_info>.
+ (bst_traits::value_type, bst_traits::value_type): Likewise.
+ (bst_traits::hash): Update accordingly.
+ (vect_get_and_check_slp_defs): Change the stmts parameter from
+ a vec<gimple *> to a vec<stmt_vec_info>.
+ (vect_two_operations_perm_ok_p, vect_build_slp_tree_1): Likewise.
+ (vect_build_slp_tree): Likewise.
+ (vect_build_slp_tree_2): Likewise. Update uses of
+ SLP_TREE_SCALAR_STMTS.
+ (vect_print_slp_tree): Update uses of SLP_TREE_SCALAR_STMTS.
+ (vect_mark_slp_stmts, vect_mark_slp_stmts_relevant)
+ (vect_slp_rearrange_stmts, vect_attempt_slp_rearrange_stmts)
+ (vect_supported_load_permutation_p, vect_find_last_scalar_stmt_in_slp)
+ (vect_detect_hybrid_slp_stmts, vect_slp_analyze_node_operations_1)
+ (vect_slp_analyze_node_operations, vect_slp_analyze_operations)
+ (vect_bb_slp_scalar_cost, vect_slp_analyze_bb_1)
+ (vect_get_constant_vectors, vect_get_slp_defs)
+ (vect_transform_slp_perm_load, vect_schedule_slp_instance)
+ (vect_remove_slp_scalar_calls, vect_schedule_slp): Likewise.
+ (vect_analyze_slp_instance): Build up a vec of stmt_vec_infos
+ instead of gimple stmts.
+ * tree-vect-data-refs.c (vect_slp_analyze_node_dependences): Change
+ the stores parameter for a vec<gimple *> to a vec<stmt_vec_info>.
+ (vect_slp_analyze_instance_dependence): Update uses of
+ SLP_TREE_SCALAR_STMTS.
+ (vect_slp_analyze_and_verify_node_alignment): Likewise.
+ (vect_slp_analyze_and_verify_instance_alignment): Likewise.
+ * tree-vect-loop.c (neutral_op_for_slp_reduction): Likewise.
+ (get_initial_defs_for_reduction): Likewise.
+ (vect_create_epilog_for_reduction): Likewise.
+ (vectorize_fold_left_reduction): Likewise.
+ * tree-vect-stmts.c (vect_prologue_cost_for_slp_op): Likewise.
+ (vect_model_simple_cost, vectorizable_shift, vectorizable_load)
+ (can_vectorize_live_stmts): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (_loop_vec_info::reductions): Change from an
+ auto_vec<gimple *> to an auto_vec<stmt_vec_info>.
+ (vect_force_simple_reduction): Take and return stmt_vec_infos rather
+ than gimple stmts.
+ * tree-parloops.c (valid_reduction_p): Take a stmt_vec_info instead
+ of a gimple stmt.
+ (gather_scalar_reductions): Update after above interface changes.
+ * tree-vect-loop.c (vect_analyze_scalar_cycles_1): Likewise.
+ (vect_is_simple_reduction): Take and return stmt_vec_infos rather
+ than gimple stmts.
+ (vect_force_simple_reduction): Likewise.
+ * tree-vect-patterns.c (vect_pattern_recog_1): Update use of
+ LOOP_VINFO_REDUCTIONS.
+ * tree-vect-slp.c (vect_analyze_slp_instance): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (_stmt_vec_info::reduc_def): Change from
+ a gimple stmt to a stmt_vec_info.
+ * tree-vect-loop.c (vect_active_double_reduction_p)
+ (vect_force_simple_reduction, vectorizable_reduction): Update
+ accordingly.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (_slp_tree::vec_stmts): Change from a
+ vec<gimple *> to a vec<stmt_vec_info>.
+ * tree-vect-loop.c (vect_create_epilog_for_reduction): Change
+ the reduction_phis argument from a vec<gimple *> to a
+ vec<stmt_vec_info>.
+ (vectorizable_reduction): Likewise the phis local variable that
+ is passed to vect_create_epilog_for_reduction. Update for new type
+ of SLP_TREE_VEC_STMTS.
+ (vectorizable_induction): Update for new type of SLP_TREE_VEC_STMTS.
+ (vectorizable_live_operation): Likewise.
+ * tree-vect-slp.c (vect_get_slp_vect_defs): Likewise.
+ (vect_transform_slp_perm_load, vect_schedule_slp_instance): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (_stmt_vec_info::vectorized_stmt): Change from
+ a gimple stmt to a stmt_vec_info.
+ (vectorizable_condition, vectorizable_live_operation)
+ (vectorizable_reduction, vectorizable_induction): Pass back the
+ vectorized statement as a stmt_vec_info.
+ * tree-vect-data-refs.c (vect_record_grouped_load_vectors): Update
+ use of STMT_VINFO_VEC_STMT.
+ * tree-vect-loop.c (vect_create_epilog_for_reduction): Likewise,
+ accumulating the inner phis that feed the STMT_VINFO_VEC_STMT
+ as stmt_vec_infos rather than gimple stmts.
+ (vectorize_fold_left_reduction): Change vec_stmt from a gimple stmt
+ to a stmt_vec_info.
+ (vectorizable_live_operation): Likewise.
+ (vectorizable_reduction, vectorizable_induction): Likewise,
+ updating use of STMT_VINFO_VEC_STMT.
+ * tree-vect-stmts.c (vect_get_vec_def_for_operand_1): Update use
+ of STMT_VINFO_VEC_STMT.
+ (vect_build_gather_load_calls, vectorizable_bswap, vectorizable_call)
+ (vectorizable_simd_clone_call, vectorizable_conversion)
+ (vectorizable_assignment, vectorizable_shift, vectorizable_operation)
+ (vectorizable_store, vectorizable_load, vectorizable_condition)
+ (vectorizable_comparison, can_vectorize_live_stmts): Change vec_stmt
+ from a gimple stmt to a stmt_vec_info.
+ (vect_transform_stmt): Update use of STMT_VINFO_VEC_STMT. Pass a
+ pointer to a stmt_vec_info to the vectorizable_* routines.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (_stmt_vec_info::related_stmt): Change from
+ a gimple stmt to a stmt_vec_info.
+ (is_pattern_stmt_p): Update accordingly.
+ * tree-vect-data-refs.c (vect_preserves_scalar_order_p): Likewise.
+ (vect_record_grouped_load_vectors): Likewise.
+ * tree-vect-loop.c (vect_determine_vf_for_stmt): Likewise.
+ (vect_fixup_reduc_chain, vect_update_vf_for_slp): Likewise.
+ (vect_model_reduction_cost): Likewise.
+ (vect_create_epilog_for_reduction): Likewise.
+ (vectorizable_reduction, vectorizable_induction): Likewise.
+ * tree-vect-patterns.c (vect_init_pattern_stmt): Likewise.
+ Return the stmt_vec_info for the pattern statement.
+ (vect_set_pattern_stmt): Update use of STMT_VINFO_RELATED_STMT.
+ (vect_split_statement, vect_mark_pattern_stmts): Likewise.
+ * tree-vect-slp.c (vect_detect_hybrid_slp_stmts): Likewise.
+ (vect_detect_hybrid_slp, vect_get_slp_defs): Likewise.
+ * tree-vect-stmts.c (vect_mark_relevant): Likewise.
+ (vect_get_vec_def_for_operand_1, vectorizable_call): Likewise.
+ (vectorizable_simd_clone_call, vect_analyze_stmt, new_stmt_vec_info)
+ (free_stmt_vec_info, vect_is_simple_use): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vect_finish_replace_stmt): Return a stmt_vec_info
+ (vect_finish_stmt_generation): Likewise.
+ * tree-vect-stmts.c (vect_finish_stmt_generation_1): Likewise.
+ (vect_finish_replace_stmt, vect_finish_stmt_generation): Likewise.
+ (vect_build_gather_load_calls): Use the return value of the above
+ functions instead of a separate call to vinfo_for_stmt. Use narrow
+ scopes for the input gimple stmt and wider scopes for the associated
+ stmt_vec_info. Use vec_info::lookup_def when setting these
+ stmt_vec_infos from an SSA_NAME definition.
+ (vectorizable_bswap, vectorizable_call, vectorizable_simd_clone_call)
+ (vect_create_vectorized_demotion_stmts, vectorizable_conversion)
+ (vectorizable_assignment, vectorizable_shift, vectorizable_operation)
+ (vectorizable_store, vectorizable_load, vectorizable_condition)
+ (vectorizable_comparison): Likewise.
+ * tree-vect-loop.c (vectorize_fold_left_reduction): Likewise.
+ (vectorizable_reduction): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vect_is_simple_use): Add an optional
+ stmt_vec_info * parameter before the optional gimple **.
+ * tree-vect-stmts.c (vect_is_simple_use): Likewise.
+ (process_use, vect_get_vec_def_for_operand_1): Update callers.
+ (vect_get_vec_def_for_operand, vectorizable_shift): Likewise.
+ * tree-vect-loop.c (vectorizable_reduction): Likewise.
+ (vectorizable_live_operation): Likewise.
+ * tree-vect-patterns.c (type_conversion_p): Likewise.
+ (vect_look_through_possible_promotion): Likewise.
+ (vect_recog_rotate_pattern): Likewise.
+ * tree-vect-slp.c (vect_get_and_check_slp_defs): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (stmt_vec_info): Temporarily change from
+ a typedef to a wrapper class.
+ (NULL_STMT_VEC_INFO): New macro.
+ (vec_info::stmt_infos): Change to vec<stmt_vec_info>.
+ (stmt_vec_info::operator*): New function.
+ (stmt_vec_info::operator gimple *): Likewise.
+ (set_vinfo_for_stmt): Use NULL_STMT_VEC_INFO.
+ (add_stmt_costs): Likewise.
+ * tree-vect-loop-manip.c (iv_phi_p): Likewise.
+ * tree-vect-loop.c (vect_compute_single_scalar_iteration_cost)
+ (vect_get_known_peeling_cost): Likewise.
+ (vect_estimate_min_profitable_iters): Likewise.
+ * tree-vect-patterns.c (vect_init_pattern_stmt): Likewise.
+ * tree-vect-slp.c (vect_remove_slp_scalar_calls): Likewise.
+ * tree-vect-stmts.c (vect_build_gather_load_calls): Likewise.
+ (vectorizable_store, free_stmt_vec_infos): Likewise.
+ (new_stmt_vec_info): Change return type of xcalloc to
+ _stmt_vec_info *.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vec_info::lookup_single_use): Declare.
+ * tree-vectorizer.c (vec_info::lookup_single_use): New function.
+ * tree-vect-loop.c (vectorizable_reduction): Use it instead of
+ a single_imm_use-based sequence.
+ * tree-vect-stmts.c (supportable_widening_operation): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vec_info::lookup_def): Declare.
+ * tree-vectorizer.c (vec_info::lookup_def): New function.
+ * tree-vect-patterns.c (vect_get_internal_def): Use it.
+ (vect_widened_op_tree): Likewise.
+ * tree-vect-stmts.c (vect_is_simple_use): Likewise.
+ * tree-vect-loop.c (vect_analyze_loop_operations): Likewise.
+ (vectorizable_reduction): Likewise.
+ (vect_valid_reduction_input_p): Take a stmt_vec_info instead
+ of a gimple *.
+ (vect_is_slp_reduction): Update calls accordingly. Use
+ vec_info::lookup_def.
+ (vect_is_simple_reduction): Likewise
+ * tree-vect-slp.c (vect_detect_hybrid_slp_1): Use vec_info::lookup_def.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vec_info::lookup_stmt): Declare.
+ * tree-vectorizer.c (vec_info::lookup_stmt): New function.
+ * tree-vect-loop.c (vect_determine_vf_for_stmt): Use it instead
+ of vinfo_for_stmt.
+ (vect_determine_vectorization_factor, vect_analyze_scalar_cycles_1)
+ (vect_compute_single_scalar_iteration_cost, vect_analyze_loop_form)
+ (vect_update_vf_for_slp, vect_analyze_loop_operations)
+ (vect_is_slp_reduction, vectorizable_induction)
+ (vect_transform_loop_stmt, vect_transform_loop): Likewise.
+ * tree-vect-patterns.c (vect_init_pattern_stmt):
+ (vect_determine_min_output_precision_1, vect_determine_precisions)
+ (vect_pattern_recog): Likewise.
+ * tree-vect-stmts.c (vect_analyze_stmt, vect_transform_stmt): Likewise.
+ * config/powerpcspe/powerpcspe.c (rs6000_density_test): Likewise.
+ * config/rs6000/rs6000.c (rs6000_density_test): Likewise.
+ * tree-vect-slp.c (vect_detect_hybrid_slp_stmts): Likewise.
+ (vect_detect_hybrid_slp_1, vect_detect_hybrid_slp_2)
+ (vect_detect_hybrid_slp): Likewise. Change the walk_stmt_info
+ info field from a loop to a loop_vec_info.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (stmt_vec_info): Move typedef earlier in file.
+ (vec_info::add_stmt): Declare.
+ * tree-vectorizer.c (vec_info::add_stmt): New function.
+ * tree-vect-data-refs.c (vect_create_data_ref_ptr): Use it.
+ * tree-vect-loop.c (_loop_vec_info::_loop_vec_info): Likewise.
+ (vect_create_epilog_for_reduction, vectorizable_reduction): Likewise.
+ (vectorizable_induction): Likewise.
+ * tree-vect-slp.c (_bb_vec_info::_bb_vec_info): Likewise.
+ * tree-vect-stmts.c (vect_finish_stmt_generation_1): Likewise.
+ (vectorizable_simd_clone_call, vectorizable_store): Likewise.
+ (vectorizable_load): Likewise.
+ * tree-vect-patterns.c (vect_init_pattern_stmt): Likewise.
+ (vect_recog_bool_pattern, vect_recog_mask_conversion_pattern)
+ (vect_recog_gather_scatter_pattern): Likewise.
+ (append_pattern_def_seq): Likewise. Remove a check that is
+ performed by add_stmt itself.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-loop.c (vectorizable_reduction): Fix an instance in
+ which make_ssa_name was called with new_stmt before new_stmt
+ had been created.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-loop.c (vect_valid_reduction_input_p): New function,
+ split out from...
+ (vect_is_slp_reduction): ...here...
+ (vect_is_simple_reduction): ...and here. Remove repetition of tests
+ that are already known to be false.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (vect_free_slp_instance): Add a final_p parameter.
+ * tree-vect-slp.c (vect_free_slp_tree): Likewise. Don't update
+ STMT_VINFO_NUM_SLP_USES when it's true.
+ (vect_free_slp_instance): Add a final_p parameter and pass it to
+ vect_free_slp_tree.
+ (vect_build_slp_tree_2): Update call to vect_free_slp_instance.
+ (vect_analyze_slp_instance): Likewise.
+ (vect_slp_analyze_operations): Likewise.
+ (vect_slp_analyze_bb_1): Likewise.
+ * tree-vectorizer.c (vec_info): Likewise.
+ * tree-vect-loop.c (vect_transform_loop): Likewise.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-loop.c (vectorizable_reduction): Assert that the
+ function is not called for second and subsequent members of
+ a reduction group.
+
+2018-07-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-loop.c (get_initial_def_for_reduction): Move special
+ cases for nested loops from here to ...
+ (vect_create_epilog_for_reduction): ...here. Only call
+ vect_is_simple_use for inner-loop reductions.
+
2018-07-31 Martin Liska <mliska@suse.cz>
- PR gcov-profile/85338
- PR gcov-profile/85350
- PR gcov-profile/85372
- * profile.c (struct location_triplet): New.
+ PR gcov-profile/85338
+ PR gcov-profile/85350
+ PR gcov-profile/85372
+ * profile.c (struct location_triplet): New.
(struct location_triplet_hash): Likewise.
(output_location): Do not output a BB that
- is already recorded for a line.
+ is already recorded for a line.
(branch_prob): Use streamed_locations.
2018-07-31 Martin Liska <mliska@suse.cz>
- PR gcov-profile/85370
+ PR gcov-profile/85370
* coverage.c (coverage_begin_function): Do not mark target
- clones as artificial functions.
+ clones as artificial functions.
2018-07-31 Martin Liska <mliska@suse.cz>
- PR gcov-profile/83813
- PR gcov-profile/84758
- PR gcov-profile/85217
- PR gcov-profile/85332
+ PR gcov-profile/83813
+ PR gcov-profile/84758
+ PR gcov-profile/85217
+ PR gcov-profile/85332
* profile.c (branch_prob): Do not record GOTO expressions
- for GIMPLE statements which locations are already streamed.
+ for GIMPLE statements which locations are already streamed.
2018-07-31 Olivier Hainque <hainque@adacore.com>
@@ -97,7 +5504,7 @@
2018-07-30 Ilya Leoshkevich <iii@linux.ibm.com>
- PR target/86547
+ PR target/86547
* lra-constraints.c (spill_hard_reg_in_range): When selecting the
hard_regno, make sure no insn between `from` and `to` clobbers it.
@@ -198,9 +5605,9 @@
2018-07-26 Martin Liska <mliska@suse.cz>
- PR lto/86548
+ PR lto/86548
* lto-wrapper.c: Add linker_output as prefix
- for ltrans_output_file.
+ for ltrans_output_file.
2018-07-26 Segher Boessenkool <segher@kernel.crashing.org>
@@ -248,7 +5655,7 @@
2018-07-25 Martin Liska <mliska@suse.cz>
* config/powerpcspe/powerpcspe-protos.h (rs6000_loop_align): Fix
- return type.
+ return type.
2018-07-25 Richard Biener <rguenther@suse.de>
@@ -264,22 +5671,22 @@
2018-07-25 Martin Liska <mliska@suse.cz>
- PR middle-end/86645
+ PR middle-end/86645
* dumpfile.c: And excluded values with TDF_ALL_VALUES.
* dumpfile.h (enum dump_flag): Defince TDF_ALL_VALUES.
2018-07-25 Martin Liska <mliska@suse.cz>
- PR sanitizer/79635
+ PR sanitizer/79635
* params.def: Explain ASan abbreviation and provide
- a documentation link.
+ a documentation link.
2018-07-24 Martin Sebor <msebor@redhat.com>
PR tree-optimization/86622
PR tree-optimization/86532
* builtins.h (string_length): Declare.
- * builtins.c (c_strlen): Correct handling of non-constant offsets.
+ * builtins.c (c_strlen): Correct handling of non-constant offsets.
(check_access): Be prepared for non-constant length ranges.
(string_length): Make extern.
* expr.c (string_constant): Only handle the minor non-constant
@@ -454,7 +5861,7 @@
to unsigned_char_type_node for strcmp/strncmp, add conversions to the
two operands.
(inline_expand_builtin_string_cmp): Delete the last parameter, give up
- the inlining expansion on target where the type of the call has same or
+ the inlining expansion on target where the type of the call has same or
narrower precision than unsigned char.
2018-07-20 David Malcolm <dmalcolm@redhat.com>
@@ -780,8 +6187,8 @@
2018-07-18 Kugan Vivekanandarajah <kuganv@linaro.org>
PR middle-end/86544
- * tree-ssa-phiopt.c (cond_removal_in_popcount_pattern): Handle comparision with EQ_EXPR
- in last stmt.
+ * tree-ssa-phiopt.c (cond_removal_in_popcount_pattern): Handle
+ comparision with EQ_EXPR in last stmt.
2018-07-18 Kelvin Nilsen <kelvin@gcc.gnu.org>
@@ -881,7 +6288,7 @@
2018-07-17 Martin Liska <mliska@suse.cz>
* config/i386/att.h (ASM_OUTPUT_ALIGN): Fix spacing
- in order to fulfil coding style.
+ in order to fulfil coding style.
* config/i386/cygming.h (ASM_OUTPUT_ALIGN): Likewise.
* config/i386/gas.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Likewise.
* config/i386/x86-64.h (ASM_OUTPUT_MAX_SKIP_PAD): Likewise.
@@ -895,11 +6302,12 @@
2018-07-17 Martin Liska <mliska@suse.cz>
* align.h: New file.
- * config/alpha/alpha.c (alpha_align_insns_1): Use align_functions directly.
+ * config/alpha/alpha.c (alpha_align_insns_1): Use align_functions
+ directly.
* config/i386/i386.c (ix86_avoid_jump_mispredicts): Use new return type
align_flags of label_to_alignment.
- * config/m32r/m32r.h (LOOP_ALIGN): Wrap returned values into align_flags
- class.
+ * config/m32r/m32r.h (LOOP_ALIGN): Wrap returned values into
+ align_flags class.
* config/m68k/m68k.c: Do not use removed align_labels_value and
align_loops_value.
* config/nds32/nds32.h (JUMP_ALIGN): Wrap result into align_flags class.
@@ -917,11 +6325,11 @@
(rs6000_loop_align_max_skip): Remove.
* config/rx/rx.h (JUMP_ALIGN): Wrap integer values
* config/rx/rx-protos.h (rx_align_for_label): Make it
- static function.
+ static function.
* config/rx/rx.c (rx_align_for_label): Change return type
- to align_flags.
+ to align_flags.
(rx_max_skip_for_label): Remove TARGET_ASM_*_ALIGN_MAX_SKIP
- macro definitions.
+ macro definitions.
into align_flags class.
(LABEL_ALIGN): Likewise.
(LOOP_ALIGN): Likewise.
@@ -944,7 +6352,7 @@
* coretypes.h: Include align.h header file.
* doc/tm.texi: Remove TARGET_ASM_JUMP_ALIGN_MAX_SKIP,
TARGET_ASM_LOOP_ALIGN_MAX_SKIP, TARGET_ASM_LABEL_ALIGN_MAX_SKIP
- and TARGET_ASM_LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP macros.
+ and TARGET_ASM_LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP macros.
* doc/tm.texi.in: Likewise.
* final.c (struct label_alignment): Remove not used structure.
(LABEL_ALIGN): Change type to align_flags.
@@ -1086,9 +6494,9 @@
2018-07-16 Martin Liska <mliska@suse.cz>
- PR ipa/86529
+ PR ipa/86529
* ipa-pure-const.c (malloc_candidate_p): Revert ::get
- to ::get_create.
+ to ::get_create.
2017-07-16 Claudiu Zissulescu <claziss@synopsys.com>
@@ -1137,19 +6545,19 @@
2018-07-16 Aldy Hernandez <aldyh@redhat.com>
- * fold-const.c (int_const_binop_1): Abstract...
- (wide_int_binop): ...wide int code here.
+ * fold-const.c (int_const_binop_1): Abstract...
+ (wide_int_binop): ...wide int code here.
(poly_int_binop): ...poly int code here.
Abstract the rest of int_const_binop_1 into int_const_binop.
- * fold-const.h (wide_int_binop): New.
- * tree-vrp.c (vrp_int_const_binop): Call wide_int_binop.
+ * fold-const.h (wide_int_binop): New.
+ * tree-vrp.c (vrp_int_const_binop): Call wide_int_binop.
Remove useless PLUS/MINUS_EXPR case.
- (zero_nonzero_bits_from_vr): Move wide int code...
- (zero_nonzero_bits_from_bounds): ...here.
- (extract_range_from_binary_expr_1): Move mask optimization code...
- (range_easy_mask_min_max): ...here.
- * tree-vrp.h (zero_nonzero_bits_from_bounds): New.
- (range_easy_mask_min_max): New.
+ (zero_nonzero_bits_from_vr): Move wide int code...
+ (zero_nonzero_bits_from_bounds): ...here.
+ (extract_range_from_binary_expr_1): Move mask optimization code...
+ (range_easy_mask_min_max): ...here.
+ * tree-vrp.h (zero_nonzero_bits_from_bounds): New.
+ (range_easy_mask_min_max): New.
2018-07-15 Jeff Law <law@redhat.com>
@@ -1241,14 +6649,14 @@
2018-07-12 Kito Cheng <kito.cheng@gmail.com>
- * config/riscv/riscv.c (enum riscv_privilege_levels): Add UNKNOWN_MODE.
- (riscv_expand_epilogue): Add assertion to check interrupt mode.
- (riscv_set_current_function): Extract getting interrupt type to new
- function.
- (riscv_get_interrupt_type): New function.
- (riscv_merge_decl_attributes): New function, checking interrupt type is
- same.
- (TARGET_MERGE_DECL_ATTRIBUTES): Define.
+ * config/riscv/riscv.c (enum riscv_privilege_levels): Add UNKNOWN_MODE.
+ (riscv_expand_epilogue): Add assertion to check interrupt mode.
+ (riscv_set_current_function): Extract getting interrupt type to new
+ function.
+ (riscv_get_interrupt_type): New function.
+ (riscv_merge_decl_attributes): New function, checking interrupt type is
+ same.
+ (TARGET_MERGE_DECL_ATTRIBUTES): Define.
2018-07-12 Paul Koning <ni1d@arrl.net>
@@ -1561,7 +6969,7 @@
2018-07-11 Aldy Hernandez <aldyh@redhat.com>
- * tree-ssa-threadupdate.c (thread_through_all_blocks): Do not jump
+ * tree-ssa-threadupdate.c (thread_through_all_blocks): Do not jump
thread twice from the same starting edge.
2018-07-11 Aldy Hernandez <aldyh@redhat.com>
@@ -1878,7 +7286,7 @@
2018-07-04 Martin Liska <mliska@suse.cz>
* tree-switch-conversion.c: Define
- max_ratio_for_speed and max_ratio_for_size constants.
+ max_ratio_for_speed and max_ratio_for_size constants.
2018-07-04 Denys Vlasenko <dvlasenk@redhat.com>
Martin Liska <mliska@suse.cz>
@@ -1924,13 +7332,13 @@
max skip conditionally.
(ASM_OUTPUT_MAX_SKIP_PAD): Likewise.
* config/ia64/ia64.c (ia64_option_override): Set default values
- for alignment options.
+ for alignment options.
* config/m68k/m68k.c: Handle new str_align_* options.
* config/mips/mips.c (mips_set_compression_mode): Change
type of constants.
(mips_option_override): Set default values for options.
* config/powerpcspe/powerpcspe.c (rs6000_option_override_internal):
- Likewise.
+ Likewise.
* config/rs6000/rs6000.c (rs6000_option_override_internal):
Likewise.
* config/rx/rx.c (rx_option_override): Likewise.
@@ -1938,15 +7346,15 @@
(LABEL_ALIGN): Use align_labels_log.
(LOOP_ALIGN): Use align_loops_align.
* config/s390/s390.c (s390_asm_output_function_label): Use new
- macros.
+ macros.
* config/sh/sh.c (sh_override_options_after_change):
Change type of constants.
* config/spu/spu.c (spu_sched_init): Likewise.
* config/sparc/sparc.c (sparc_option_override): Set default
- values for options.
+ values for options.
* config/visium/visium.c (visium_option_override): Likewise.
* config/visium/visium.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Do not
- emit p2align format with last argument if it's not needed.
+ emit p2align format with last argument if it's not needed.
* doc/invoke.texi: Document extended format of -falign-*.
* final.c: Use align_labels alignment.
* flags.h (struct target_flag_state): Change type to use
@@ -2016,7 +7424,7 @@
* config/i386/x86-64.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Likewise.
2018-07-04 Martin Liska <mliska@suse.cz>
- Jonathan Wakely <jwakely@redhat.com>
+ Jonathan Wakely <jwakely@redhat.com>
* coverage.c: Use correct type.
* doc/invoke.texi: Language correction.
@@ -2350,13 +7758,13 @@
2018-07-02 Martin Liska <mliska@suse.cz>
- PR ipa/86279
+ PR ipa/86279
* ipa-pure-const.c (malloc_candidate_p): Revert usage of ::get.
(propagate_nothrow): Likewise.
2018-07-02 Martin Liska <mliska@suse.cz>
- PR ipa/86323
+ PR ipa/86323
* ipa-inline.c (early_inliner): Revert wrongly added ::get call.
2018-07-02 David Malcolm <dmalcolm@redhat.com>
@@ -2583,9 +7991,9 @@
2018-06-29 Martin Liska <mliska@suse.cz>
- PR tree-optimization/86263
+ PR tree-optimization/86263
* tree-switch-conversion.c (switch_decision_tree::try_switch_expansion):
- Make edge redirection.
+ Make edge redirection.
2018-06-29 David Malcolm <dmalcolm@redhat.com>
@@ -2678,33 +8086,33 @@
2018-06-28 Martin Liska <mliska@suse.cz>
* tree-switch-conversion.c (jump_table_cluster::can_be_handled):
- Use newly introduced constants.
+ Use newly introduced constants.
* tree-switch-conversion.h (struct jump_table_cluster):
- Define max_ratio_for_size and max_ratio_for_speed.
+ Define max_ratio_for_size and max_ratio_for_speed.
2018-06-28 Martin Liska <mliska@suse.cz>
* tree-switch-conversion.c (jump_table_cluster::find_jump_tables):
- Add new checking assert to catch invalid state.
+ Add new checking assert to catch invalid state.
(jump_table_cluster::can_be_handled): Handle single case
- clusters.
+ clusters.
(jump_table_cluster::is_beneficial): Bail out for such case.
(bit_test_cluster::find_bit_tests):
- Add new checking assert to catch invalid state.
+ Add new checking assert to catch invalid state.
(bit_test_cluster::can_be_handled): Handle single case
- clusters.
+ clusters.
(bit_test_cluster::is_beneficial): Bail out for such case.
(switch_decision_tree::analyze_switch_statement):
- Fix comment.
+ Fix comment.
2018-06-28 Martin Liska <mliska@suse.cz>
* common.opt: Introduce -completion option.
* gcc.c (driver_handle_option): Handle it.
(driver::main): Print completions if completion
- is set.
+ is set.
* opt-suggestions.c (option_proposer::get_completions):
- New function.
+ New function.
(option_proposer::suggest_completion): Likewise.
(option_proposer::find_param_completions): Likewise.
(verify_autocompletions): Likewise.
@@ -2718,7 +8126,7 @@
* opt-suggestions.h: Declare new functions.
* opts.c (common_handle_option): Handle OPT__completion_.
* selftest-run-tests.c (selftest::run_tests): Add
- opt_proposer_c_tests.
+ opt_proposer_c_tests.
* selftest.c (assert_str_startswith): New.
* selftest.h (assert_str_startswith): Likewise.
(opt_proposer_c_tests): New.
@@ -2950,7 +8358,7 @@
* doc/invoke.texi (ARM Options): Document cortex-a76 and
cortex-a76.cortex-a55.
-2018-06-27 Tamar Christina <tamar.christina@arm.com>
+2018-06-27 Tamar Christina <tamar.christina@arm.com>
PR target/85769
* config/aarch64/aarch64.md (*movhf_aarch64): Add dup v0.4h pattern.
@@ -3111,8 +8519,8 @@
2018-06-26 Robin Dapp <rdapp@linux.vnet.ibm.com>
- * config/s390/s390.h (enum processor_flags): Do not use
- default tune parameter when -march was specified.
+ * config/s390/s390.h (enum processor_flags): Do not use
+ default tune parameter when -march was specified.
2018-06-26 Jakub Jelinek <jakub@redhat.com>
@@ -3336,11 +8744,11 @@
2018-06-22 Martin Liska <mliska@suse.cz>
- PR tree-optimization/86263
+ PR tree-optimization/86263
* tree-switch-conversion.c (jump_table_cluster::find_jump_tables):
- Bail out if is_enabled is false.
+ Bail out if is_enabled is false.
* tree-switch-conversion.h (jump_table_cluster::is_enabled):
- New declaration.
+ New declaration.
(jump_table_cluster::is_enabled): New function.
2018-06-22 Jan Hubicka <hubicka@ucw.cz>
@@ -3360,9 +8768,9 @@
2018-06-22 Martin Liska <mliska@suse.cz>
* symbol-summary.h (get): Make it pure and inline move
- functionality from ::get function.
- (get): Remove and inline into ::get and ::get_create.
- (get_create): Move code from ::get function.
+ functionality from ::get function.
+ (get): Remove and inline into ::get and ::get_create.
+ (get_create): Move code from ::get function.
2018-06-22 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
@@ -3416,7 +8824,7 @@
2018-06-21 Martin Liska <mliska@suse.cz>
* ipa-pure-const.c (propagate_nothrow): Use
- funct_state_summaries->get.
+ funct_state_summaries->get.
(dump_malloc_lattice): Likewise.
(propagate_malloc): Likewise.
@@ -3560,21 +8968,21 @@
2018-06-20 Martin Liska <mliska@suse.cz>
* tree-switch-conversion.c (jump_table_cluster::can_be_handled):
- Change default ratio from 10 to 8.
+ Change default ratio from 10 to 8.
2018-06-20 Martin Liska <mliska@suse.cz>
* tree-switch-conversion.c (jump_table_cluster::find_jump_tables):
- New.
+ New.
(bit_test_cluster::find_bit_tests): Likewise.
(switch_decision_tree::analyze_switch_statement): Find clusters.
* tree-switch-conversion.h (struct jump_table_cluster): Document
- hierarchy.
+ hierarchy.
2018-06-20 Martin Liska <mliska@suse.cz>
* tree-switch-conversion.c (switch_conversion::collect):
- Record m_uniq property.
+ Record m_uniq property.
(switch_conversion::expand): Bail out for special conditions.
(group_cluster::~group_cluster): New.
(group_cluster::group_cluster): Likewise.
@@ -3811,9 +9219,9 @@
2018-06-19 Martin Liska <mliska@suse.cz>
* config/i386/i386.c (ix86_can_inline_p): Do not use
- ipa_fn_summaries::get_create.
+ ipa_fn_summaries::get_create.
* ipa-cp.c (ipcp_cloning_candidate_p): Replace get_create with
- get.
+ get.
(devirtualization_time_bonus): Likewise.
(ipcp_propagate_stage): Likewise.
* ipa-fnsummary.c (redirect_to_unreachable): Likewise.
@@ -3827,13 +9235,13 @@
(ipa_fn_summary_t::remove): Rename to ...
(ipa_fn_summary_t::remove_callees): ... this.
(ipa_fn_summary_t::duplicate): Use placement new
- instead of memory copy.
+ instead of memory copy.
(ipa_call_summary_t::duplicate): Likewise.
(ipa_call_summary_t::remove): Remove.
(dump_ipa_call_summary): Change get_create to get.
(ipa_dump_fn_summary): Dump only when summary exists.
(analyze_function_body): Use symbol_summary::get instead
- of get_create.
+ of get_create.
(compute_fn_summary): Likewise.
(estimate_edge_devirt_benefit): Likewise.
(estimate_edge_size_and_time): Likewise.
@@ -3847,7 +9255,7 @@
* ipa-fnsummary.h (struct GTY): Add new ctor and copy ctor.
(struct ipa_call_summary): Likewise.
* ipa-icf.c (sem_function::merge): Use symbol_summary::get instead
- of get_create.
+ of get_create.
* ipa-inline-analysis.c (do_estimate_edge_time): Likewise.
(estimate_size_after_inlining): Likewise.
(estimate_growth): Likewise.
@@ -4580,7 +9988,7 @@
* config/i386/i386.opt: Make MPX-related options as Deprecated.
* opt-functions.awk: Handle Deprecated flag.
* opts-common.c (decode_cmdline_option): Handle cl_deprecated
- and report error.
+ and report error.
(read_cmdline_option): Report warning for a deprecated option.
* opts.h (struct cl_option): Add new field cl_deprecated.
(CL_ERR_DEPRECATED): New.
@@ -4702,7 +10110,7 @@
* PR tree-optimization/86083
* tree-ssa-strlen.c (handle_char_store): Use tree_expr_nonzero_p.
-2018-06-11 Zhouyi Zhou <zhouzhouyi@gmail.com>
+2018-06-11 Zhouyi Zhou <zhouzhouyi@gmail.com>
* tree-eh.c (lower_eh_constructs_2): Add a comma to comment.
@@ -4715,7 +10123,7 @@
2018-06-11 Martin Liska <mliska@suse.cz>
- PR tree-optimization/86089
+ PR tree-optimization/86089
* tree-ssa-strlen.c (get_string_length): Move back removed hunk.
2018-06-11 Julia Koval <julia.koval@intel.com>
@@ -4747,12 +10155,12 @@
2018-06-08 Martin Liska <mliska@suse.cz>
* tree-cfg.h (debug_function): Fix argument type to match
- implementation.
+ implementation.
2018-06-08 Martin Liska <mliska@suse.cz>
* config/powerpcspe/powerpcspe.c (rs6000_xcoff_visibility):
- Remove usage of MPX-related (and removed) fields.
+ Remove usage of MPX-related (and removed) fields.
* config/rs6000/rs6000.c (rs6000_xcoff_visibility): Likewise.
2018-06-08 David Malcolm <dmalcolm@redhat.com>
@@ -4846,7 +10254,7 @@
2018-06-08 Martin Liska <mliska@suse.cz>
* ipa-pure-const.c (propagate_pure_const): Use ::get at places
- where we expect an existing summary.
+ where we expect an existing summary.
2018-06-08 Martin Liska <mliska@suse.cz>
@@ -6064,7 +11472,7 @@
* omp-low.c (lower_omp_target): Avoid reference-type processing
on pointers for firstprivate clause.
-2018-05-31 Sameera Deshpande <sameera.deshpande@linaro.org>
+2018-05-31 Sameera Deshpande <sameera.deshpande@linaro.org>
* config/aarch64/aarch64-simd-builtins.def (ld1x3): New.
(st1x2): Likewise.
@@ -6185,7 +11593,7 @@
(expand_builtin_stpcpy): Call it, and call maybe_warn_nonstring_arg
only if the former succeeds.
-2018-05-31 Sameera Deshpande <sameera.deshpande@linaro.org>
+2018-05-31 Sameera Deshpande <sameera.deshpande@linaro.org>
* config/aarch64/aarch64-cores.def (saphira) : Add support for ARMv8.4
in saphira.
@@ -9249,7 +14657,7 @@
* doc/invoke.texi (Developer Options): Document dump filename
determination early. Document stdin/stdout selection.
-2018-04-30 Andrew Sadek <andrew.sadek.se@gmail.com>
+2018-04-30 Andrew Sadek <andrew.sadek.se@gmail.com>
Microblaze Target: PIC data text relative
@@ -11349,7 +16757,7 @@
(DIVDE): Use it.
(DIVDEU): Likewise.
-2018-03-28 Carl Love <cel@us.ibm.com>
+2018-03-28 Carl Love <cel@us.ibm.com>
Revert
2017-09-27 Carl Love <cel@us.ibm.com>
@@ -16191,7 +21599,7 @@
Limit immediates.
* config/aarch64/predicates.md (Uti): Add new constraint.
-2018-01-17 Carl Love <cel@us.ibm.com>
+2018-01-17 Carl Love <cel@us.ibm.com>
* config/rs6000/vsx.md (define_expand xl_len_r,
define_expand stxvl, define_expand *stxvl): Add match_dup argument.
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 29a6c27..89c02b0 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20180731
+20180924
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index b871640..4b7cec8 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -978,8 +978,7 @@ CPPLIB_H = $(srcdir)/../libcpp/include/line-map.h \
INPUT_H = $(srcdir)/../libcpp/include/line-map.h input.h
OPTS_H = $(INPUT_H) $(VEC_H) opts.h $(OBSTACK_H)
SYMTAB_H = $(srcdir)/../libcpp/include/symtab.h $(OBSTACK_H)
-CPP_ID_DATA_H = $(CPPLIB_H) $(srcdir)/../libcpp/include/cpp-id-data.h
-CPP_INTERNAL_H = $(srcdir)/../libcpp/internal.h $(CPP_ID_DATA_H)
+CPP_INTERNAL_H = $(srcdir)/../libcpp/internal.h
TREE_DUMP_H = tree-dump.h $(SPLAY_TREE_H) $(DUMPFILE_H)
TREE_PASS_H = tree-pass.h $(TIMEVAR_H) $(DUMPFILE_H)
TREE_SSA_H = tree-ssa.h tree-ssa-operands.h \
@@ -1601,6 +1600,7 @@ OBJS = \
web.o \
wide-int.o \
wide-int-print.o \
+ wide-int-range.o \
xcoffout.o \
$(out_object_file) \
$(EXTRA_OBJS) \
@@ -2503,7 +2503,7 @@ s-tm-texi: build/genhooks$(build_exeext) $(srcdir)/doc/tm.texi.in
else \
echo >&2 ; \
echo Verify that you have permission to grant a GFDL license for all >&2 ; \
- echo new text in tm.texi, then copy it to $(srcdir)/doc/tm.texi. >&2 ; \
+ echo new text in $(objdir)/tm.texi, then copy it to $(srcdir)/doc/tm.texi. >&2 ; \
false; \
fi
@@ -2521,7 +2521,7 @@ s-match: build/genmatch$(build_exeext) $(srcdir)/match.pd cfn-operators.pd
generic-match.c
$(STAMP) s-match
-GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
+GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
$(host_xm_file_list) \
$(tm_file_list) $(HASHTAB_H) $(SPLAY_TREE_H) $(srcdir)/bitmap.h \
$(srcdir)/wide-int.h $(srcdir)/alias.h \
@@ -2665,7 +2665,7 @@ build/version.o: version.c version.h \
build/errors.o : errors.c $(BCONFIG_H) $(SYSTEM_H) errors.h
build/gensupport.o: gensupport.c $(BCONFIG_H) $(SYSTEM_H) \
$(CORETYPES_H) $(GTM_H) $(RTL_BASE_H) $(OBSTACK_H) errors.h \
- $(HASHTAB_H) $(READ_MD_H) $(GENSUPPORT_H)
+ $(HASHTAB_H) $(READ_MD_H) $(GENSUPPORT_H) $(HASH_TABLE_H)
build/ggc-none.o : ggc-none.c $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) \
$(GGC_H)
build/min-insn-modes.o : min-insn-modes.c $(BCONFIG_H) $(SYSTEM_H) \
@@ -2680,7 +2680,7 @@ build/read-rtl.o: read-rtl.c $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) \
build/rtl.o: rtl.c $(BCONFIG_H) $(CORETYPES_H) $(GTM_H) $(SYSTEM_H) \
$(RTL_H) $(GGC_H) errors.h
build/vec.o : vec.c $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) $(VEC_H) \
- $(GGC_H) toplev.h $(DIAGNOSTIC_CORE_H)
+ $(GGC_H) toplev.h $(DIAGNOSTIC_CORE_H) $(HASH_TABLE_H)
build/hash-table.o : hash-table.c $(BCONFIG_H) $(SYSTEM_H) \
$(CORETYPES_H) $(HASH_TABLE_H) $(GGC_H) toplev.h $(DIAGNOSTIC_CORE_H)
build/sort.o : sort.cc $(BCONFIG_H) $(SYSTEM_H)
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index c6f1911..e51a2a3 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,325 @@
+2018-09-24 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR ada/87396
+ * fe.h (Get_Attribute_Definition_Clause): Use 'unsigned char' instead
+ of 'char' as the type of the second parameter.
+
+2018-09-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ * Makefile.rtl (arm% linux-gnueabi%): Always set EH_MECHANISM to -arm.
+
+2018-09-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR ada/81103
+ * terminals.c: Do not include termio.h.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ * gcc-interface/decl.c (update_profile): Use new function
+ fndecl_built_in_p and remove check for FUNCTION_DECL if
+ possible.
+ * gcc-interface/gigi.h (call_is_atomic_load): Likewise.
+ * gcc-interface/utils.c (gnat_pushdecl): Likewise.
+
+2018-08-23 Giuliano Belinassi <giuliano.belinassi@usp.br>
+
+ * exp_unst.ads: Fix typo 'exapnded' to 'expanded'.
+
+2018-08-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * checks.adb, contracts.adb, exp_aggr.adb, exp_attr.adb,
+ exp_ch6.adb, exp_ch7.adb, exp_ch9.adb, exp_unst.adb,
+ exp_util.adb, freeze.adb, gnatlink.adb, layout.adb,
+ lib-writ.adb, lib-xref-spark_specific.adb, sem_ch13.adb,
+ sem_ch3.adb, sem_ch6.adb, sem_res.adb, sem_util.adb, sinfo.ads,
+ sprint.adb: Minor reformatting.
+
+2018-08-21 Jerome Lambourg <lambourg@adacore.com>
+
+ * vxlink-bind.adb, vxlink-bind.ads, vxlink-link.adb,
+ vxlink-link.ads, vxlink-main.adb, vxlink.adb, vxlink.ads: Add a
+ new tool vxlink to handle VxWorks constructors in DKMs.
+ * gcc-interface/Makefile.in: add rules to build vxlink
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch6.adb (Analyze_Subprogram_Body_Helper, Mask_Type):
+ Refine the handling of freezing types for expression functions
+ that are not completions, when analyzing the generated body for
+ the function: the body is inserted at the end of the enclosing
+ declarative part, and its analysis may freeze types declared in
+ the same scope that have not been frozen yet.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch6.adb: Remove Freeze_Expr_Types.
+ * freeze.ads, freeze.adb (Freeze_Expr_Types): Moved from
+ sem_ch6.adb, and extended to handle other expressions that may
+ contain unfrozen types that must be frozen in their proper
+ scopes.
+ * contracts.adb (Analyze_Entry_Or_Subprogram_Contract): If the
+ contract is for the generated body of an expression function
+ that is a completion, traverse the expressions for pre- and
+ postconditions to freeze all types before adding the contract
+ code within the subprogram body.
+
+2018-08-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_ch10.adb: Remove the with and use clause for unit Ghost.
+ (Analyze_With_Clause): Do not mark a with clause which mentions
+ an ignored Ghost code for elimination.
+
+2018-08-21 Javier Miranda <miranda@adacore.com>
+
+ * lib-writ.adb (Write_Unit_Information): Handle pragmas removed
+ by the expander.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch6.adb (Check_Synchronized_Overriding): The conformance
+ between an overriding protected operation and the overridden
+ abstract progenitor operation requires subtype conformance;
+ requiring equality of return types in the case of a function is
+ too restrictive and leads to spurious errors when the return
+ type is a generic actual.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_ch9.adb (Expand_N_Timed_Entry_Call,
+ Expand_Conditional_Entry_Call): Use Reset_Scopes_Of to set
+ properly the scope of all entities created in blocks generated
+ by the expansion of these constructs.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch13.adb (Build_Predicate_Functioss): Apply
+ Reset_Quantified_Variables_Scope after predicate function has
+ been analyzed, so that the scope can be reset on the generated
+ loop statements that have replaced the quantified expressions.
+
+2018-08-21 Bob Duff <duff@adacore.com>
+
+ * einfo.ads, einfo.adb (Private_View, Shadow_Entities): Remove
+ obsolete code.
+
+2018-08-21 Maroua Maalej <maalej@adacore.com>
+
+ * sem_spark.adb (Check_Call_Statement): Check global and formal
+ parameter permissions at call sites.
+ (Check_Callable_Body): Assume permissions on globals and
+ parameters depending on their modes then analyse the body
+ operations.
+ (Check_Declaration): Consider both deep (including elementary
+ access) object declarations and normal variables. First check
+ whether the deep object is of Ownership Aspec True or not, then,
+ depending on its initialization, assign the appropriate state.
+ Check related to non access type variables deal with
+ initialization value permissions.
+ (Check_Expression): Check nodes used in the expression being
+ analyzed.
+ (Check_Globals): Call by Check_Call_Statement to perform the
+ check on globals.
+ (Check_List): Call Check_Node on each element of the list.
+ (Check_Loop_Statement): Check the Iteration_Scheme and loop
+ statements.
+ (Check_Node): Main traversal procedure to check safe pointer usage.
+ (Check_Package_Body): Check subprogram's body.
+ (Check_Param_In): Take a formal and an actual parameter and
+ Check the permission of every in-mode parameter.
+ (Check_Param_Out): Take a formal and an actual parameter and
+ check the state of out-mode and in out-mode parameters.
+ (Check_Statement): Check statements other than procedure call.
+ (Get_Perm, Get_Perm_Or_Tree, Get_Perm_Tree): Find out the state
+ related to the given name.
+ (Is_Deep): Return True if an object is of access type or has
+ subfields of access type.
+ (Perm_Error, Perm_Error_Subprogram_End): Add an error message
+ whenever the found state on the given name is different from the
+ one expected (in the statement being analyzed).
+ (Process_Path): Given an operation and a current state, call
+ Perm_Error if there is any mismatch.
+ (Return_Declarations, Return_Globals, Return_The_Global): Check
+ the state of a given name at the end of the subprogram. These
+ procedures may change depending on how we shall finally deal
+ with globals and the rhs state in a move operation.
+ (Set_Perm_Extensions, Set_Perm_Prefixes_Borrow,
+ Set_Perm_Prefixes, Setup_Globals, Setup_Parameter_Or_Global,
+ Setup_Parameters): Set up the new states to the given node and
+ up and down the tree after an operation.
+ (Has_Ownership_Aspect_True): This function may disappear later
+ when the Ownership Aspect will be implemented in the FE.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_res.adb (Resolve_Call): Resolve correctly a parameterless
+ call that returns an access type whose designated type is the
+ component type of an array, when the function has no defaulted
+ parameters.
+
+2018-08-21 Yannick Moy <moy@adacore.com>
+
+ * doc/gnat_ugn/building_executable_programs_with_gnat.rst:
+ Document entries of the target parametrization file.
+ * gnat_ugn.texi: Regenerate.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_attr.adb: Set scope of elaboration flag for 'Access.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sprint.adb: Add guard on printing aspects.
+
+2018-08-21 Javier Miranda <miranda@adacore.com>
+
+ * exp_cg.adb (Generate_CG_Output): Handle calls removed by the
+ expander.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * layout.adb: Do not set size of access subprogram if unnesting.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * freeze.adb: Remove warnings for access to subprograms when
+ unnesting is active.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_aggr.adb (Expand_Array_Aggregate): If the component type
+ is limited, the array must be constructed in place, so set flag
+ In_Place_Assign_OK_For_Declaration accordingly. This prevents
+ improper copying of an array of tasks during initialization.
+
+2018-08-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (Call_to_gnu): Always suppress an
+ unchecked conversion around the actual for an In parameter
+ passed by copy.
+
+2018-08-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_util.adb (Is_Possibly_Unaligned_Object): For the case of a
+ selected component inherited in a record extension and subject
+ to a representation clause, retrieve the position and size from
+ the original record component.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_util.ads, sem_util.adb (New_External_Entity): Type of
+ Suffix_Index must be Int, not Nat, so that a negative value can
+ be used to generate a unique name for an external object, as
+ specified in Tbuild.New_External_Name.
+ (Scope_Within): Handle private type whose completion is a
+ synchronized type (For unnesting).
+ * itypes.ads, itypes.adb (Create_Itype): Ditto
+ * sem_ch3.adb (Constrain_Corresponding_Record): Generate a
+ unique name for the created subtype, because there may be
+ several discriminated tasks present in the same scope, and each
+ needs its distinct corresponding record subtype.
+
+2018-08-21 Yannick Moy <moy@adacore.com>
+
+ * doc/gnat_ugn/gnat_and_program_execution.rst: Update
+ documentation of dimensionality analysis.
+ * gnat_ugn.texi: Regenerate.
+ * Makefile.rtl, impunit.adb: Consider the new units.
+ * libgnat/s-dfmkio.ads, libgnat/s-dfmopr.ads,
+ libgnat/s-diflmk.ads: New units based on Float.
+ * libgnat/s-dilomk.ads, libgnat/s-dlmkio.ads,
+ libgnat/s-dlmopr.ads: New units based on Long_Float.
+ * libgnat/s-dmotpr.ads: Rename to libgnat/s-dgmgop.ads and turn
+ into an instance of
+ System.Dim.Generic_Mks.Generic_Other_Prefixes.
+ * libgnat/s-dimmks.ads: Rename to libgnat/s-digemk.ads and turn
+ into an instance of System.Dim.Generic_Mks.
+
+2018-08-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * impunit.adb: Add g-lists to the set of non-implementation
+ units.
+ * libgnat/g-lists.adb, libgnat/g-lists.ads: New unit.
+ * Makefile.rtl: Add g-lists to the set of non-tasking units.
+ * gcc-interface/Make-lang.in: Add g-lists to the set of files
+ used by gnat1.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_ch9.adb (Reset_Scopes): Do not recurse into type
+ declarations when resetting the scope of entities declared the
+ procedures generated for entry bodies and accept alternatives.
+ Use the entity of the procedure declaration, not its body, as
+ the new scope.
+
+2018-08-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * einfo.adb (Elaboration_Entity): Include entries and entry
+ families in the set of legal entities.
+ (Elaboration_Entity_Required): Include entries and entry
+ families in the set of legal entities.
+ (Set_Elaboration_Entity): Include entries and entry families in
+ the set of legal entities.
+ (Set_Elaboration_Entity_Required): Include entries and entry
+ families in the set of legal entities.
+ (Write_Field13_Name): Update the output of attribute
+ Elaboration_Entity.
+ * einfo.ads: Attributes Elaboration_Entity and
+ Elaboration_Entity_Required now apply to entries and entry
+ families.
+
+2018-08-21 Arnaud Charlet <charlet@adacore.com>
+
+ * set_targ.adb: Mark some CodePeer message as Intentional.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_res.adb (Resolve_Call): Force the freezing of an
+ expression function that is called to provide a default value
+ for a defaulted discriminant in an object initialization.
+
+2018-08-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * libgnat/g-dynhta.adb, libgnat/g-dynhta.ads: New package
+ Dynamic_HTable.
+
+2018-08-21 Javier Miranda <miranda@adacore.com>
+
+ * checks.ads (Determine_Range): Adding documentation.
+ * checks.adb (Determine_Range): Don't deal with enumerated types
+ with non-standard representation.
+ (Convert_And_Check_Range): For conversion of enumeration types
+ with non standard representation to an integer type perform a
+ direct conversion to the target integer type.
+
+2018-08-21 Piotr Trojanek <trojanek@adacore.com>
+
+ * lib-xref.ads, lib-xref-spark_specific.adb
+ (Enclosing_Subprogram_Or_Library_Package): Now roughtly works
+ for pragmas that come from aspect specifications.
+
+2018-08-21 Pierre-Marie de Rodat <derodat@adacore.com>
+
+ * sa_messages.ads, sa_messages.adb: New source files.
+
+2018-08-03 Pierre-Marie de Rodat <derodat@adacore.com>
+
+ Reverts
+ 2018-07-06 Jim Wilson <jimw@sifive.com>
+
+ * Make-generated.in (treeprs.ads): Use $(GNATMAKE) instead of gnatmake.
+ (einfo.h, sinfo.h, stamp-snames, stamp-nmake): Likewise.
+ * gcc-interface/Makefile.in (xoscons): Likewise.
+
+2018-07-31 Alexandre Oliva <oliva@adacore.com>
+ Olivier Hainque <hainque@adacore.com>
+
+ * gcc-interface/trans.c: Include debug.h.
+ (file_map): New static variable.
+ (gigi): Set it. Create decl_to_instance_map when needed.
+ (Subprogram_Body_to_gnu): Pass gnu_subprog_decl to...
+ (Sloc_to_locus): ... this. Add decl parm, map it to instance.
+ * gcc-interface/gigi.h (Sloc_to_locus): Adjust declaration.
+
2018-07-31 Arnaud Charlet <charlet@adacore.com>
* clean.adb, gnatchop.adb, gnatfind.adb, gnatls.adb,
@@ -60,7 +382,7 @@
2018-07-31 Eric Botcazou <ebotcazou@adacore.com>
- * libgnarl/s-osinte__solaris.ads (upad64_t): New private type.
+ * libgnarl/s-osinte__solaris.ads (upad64_t): New private type.
(mutex_t): Use it for 'lock' and 'data' components.
(cond_t): Likewise for 'data' and use single 'flags' component.
diff --git a/gcc/ada/Make-generated.in b/gcc/ada/Make-generated.in
index bdcb62c..757eaa8 100644
--- a/gcc/ada/Make-generated.in
+++ b/gcc/ada/Make-generated.in
@@ -28,21 +28,21 @@ $(ADA_GEN_SUBDIR)/treeprs.ads : $(ADA_GEN_SUBDIR)/treeprs.adt $(ADA_GEN_SUBDIR)/
-$(MKDIR) $(ADA_GEN_SUBDIR)/bldtools/treeprs
$(RM) $(addprefix $(ADA_GEN_SUBDIR)/bldtools/treeprs/,$(notdir $^))
$(CP) $^ $(ADA_GEN_SUBDIR)/bldtools/treeprs
- (cd $(ADA_GEN_SUBDIR)/bldtools/treeprs; $(GNATMAKE) -q xtreeprs ; ./xtreeprs treeprs.ads )
+ (cd $(ADA_GEN_SUBDIR)/bldtools/treeprs; gnatmake -q xtreeprs ; ./xtreeprs treeprs.ads )
$(MOVE_IF_CHANGE) $(ADA_GEN_SUBDIR)/bldtools/treeprs/treeprs.ads $(ADA_GEN_SUBDIR)/treeprs.ads
$(ADA_GEN_SUBDIR)/einfo.h : $(ADA_GEN_SUBDIR)/einfo.ads $(ADA_GEN_SUBDIR)/einfo.adb $(ADA_GEN_SUBDIR)/xeinfo.adb $(ADA_GEN_SUBDIR)/ceinfo.adb
-$(MKDIR) $(ADA_GEN_SUBDIR)/bldtools/einfo
$(RM) $(addprefix $(ADA_GEN_SUBDIR)/bldtools/einfo/,$(notdir $^))
$(CP) $^ $(ADA_GEN_SUBDIR)/bldtools/einfo
- (cd $(ADA_GEN_SUBDIR)/bldtools/einfo; $(GNATMAKE) -q xeinfo ; ./xeinfo einfo.h )
+ (cd $(ADA_GEN_SUBDIR)/bldtools/einfo; gnatmake -q xeinfo ; ./xeinfo einfo.h )
$(MOVE_IF_CHANGE) $(ADA_GEN_SUBDIR)/bldtools/einfo/einfo.h $(ADA_GEN_SUBDIR)/einfo.h
$(ADA_GEN_SUBDIR)/sinfo.h : $(ADA_GEN_SUBDIR)/sinfo.ads $(ADA_GEN_SUBDIR)/sinfo.adb $(ADA_GEN_SUBDIR)/xsinfo.adb $(ADA_GEN_SUBDIR)/csinfo.adb
-$(MKDIR) $(ADA_GEN_SUBDIR)/bldtools/sinfo
$(RM) $(addprefix $(ADA_GEN_SUBDIR)/bldtools/sinfo/,$(notdir $^))
$(CP) $^ $(ADA_GEN_SUBDIR)/bldtools/sinfo
- (cd $(ADA_GEN_SUBDIR)/bldtools/sinfo; $(GNATMAKE) -q xsinfo ; ./xsinfo sinfo.h )
+ (cd $(ADA_GEN_SUBDIR)/bldtools/sinfo; gnatmake -q xsinfo ; ./xsinfo sinfo.h )
$(MOVE_IF_CHANGE) $(ADA_GEN_SUBDIR)/bldtools/sinfo/sinfo.h $(ADA_GEN_SUBDIR)/sinfo.h
$(ADA_GEN_SUBDIR)/snames.h $(ADA_GEN_SUBDIR)/snames.ads $(ADA_GEN_SUBDIR)/snames.adb : $(ADA_GEN_SUBDIR)/stamp-snames ; @true
@@ -50,7 +50,7 @@ $(ADA_GEN_SUBDIR)/stamp-snames : $(ADA_GEN_SUBDIR)/snames.ads-tmpl $(ADA_GEN_SUB
-$(MKDIR) $(ADA_GEN_SUBDIR)/bldtools/snamest
$(RM) $(addprefix $(ADA_GEN_SUBDIR)/bldtools/snamest/,$(notdir $^))
$(CP) $^ $(ADA_GEN_SUBDIR)/bldtools/snamest
- (cd $(ADA_GEN_SUBDIR)/bldtools/snamest; $(GNATMAKE) -q xsnamest ; ./xsnamest )
+ (cd $(ADA_GEN_SUBDIR)/bldtools/snamest; gnatmake -q xsnamest ; ./xsnamest )
$(MOVE_IF_CHANGE) $(ADA_GEN_SUBDIR)/bldtools/snamest/snames.ns $(ADA_GEN_SUBDIR)/snames.ads
$(MOVE_IF_CHANGE) $(ADA_GEN_SUBDIR)/bldtools/snamest/snames.nb $(ADA_GEN_SUBDIR)/snames.adb
$(MOVE_IF_CHANGE) $(ADA_GEN_SUBDIR)/bldtools/snamest/snames.nh $(ADA_GEN_SUBDIR)/snames.h
@@ -61,7 +61,7 @@ $(ADA_GEN_SUBDIR)/stamp-nmake: $(ADA_GEN_SUBDIR)/sinfo.ads $(ADA_GEN_SUBDIR)/nma
-$(MKDIR) $(ADA_GEN_SUBDIR)/bldtools/nmake
$(RM) $(addprefix $(ADA_GEN_SUBDIR)/bldtools/nmake/,$(notdir $^))
$(CP) $^ $(ADA_GEN_SUBDIR)/bldtools/nmake
- (cd $(ADA_GEN_SUBDIR)/bldtools/nmake; $(GNATMAKE) -q xnmake ; ./xnmake -b nmake.adb ; ./xnmake -s nmake.ads)
+ (cd $(ADA_GEN_SUBDIR)/bldtools/nmake; gnatmake -q xnmake ; ./xnmake -b nmake.adb ; ./xnmake -s nmake.ads)
$(MOVE_IF_CHANGE) $(ADA_GEN_SUBDIR)/bldtools/nmake/nmake.ads $(ADA_GEN_SUBDIR)/nmake.ads
$(MOVE_IF_CHANGE) $(ADA_GEN_SUBDIR)/bldtools/nmake/nmake.adb $(ADA_GEN_SUBDIR)/nmake.adb
touch $(ADA_GEN_SUBDIR)/stamp-nmake
diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl
index 7eaa9ba..936a16d 100644
--- a/gcc/ada/Makefile.rtl
+++ b/gcc/ada/Makefile.rtl
@@ -427,6 +427,7 @@ GNATRTL_NONTASKING_OBJS= \
g-htable$(objext) \
g-io$(objext) \
g-io_aux$(objext) \
+ g-lists$(objext) \
g-locfil$(objext) \
g-mbdira$(objext) \
g-mbflra$(objext) \
@@ -522,12 +523,20 @@ GNATRTL_NONTASKING_OBJS= \
s-conca9$(objext) \
s-crc32$(objext) \
s-crtl$(objext) \
+ s-dfmkio$(objext) \
+ s-dfmopr$(objext) \
+ s-dgmgop$(objext) \
+ s-dlmopr$(objext) \
s-diflio$(objext) \
+ s-diflmk$(objext) \
+ s-digemk$(objext) \
s-diinio$(objext) \
+ s-dilomk$(objext) \
s-dim$(objext) \
s-dimkio$(objext) \
s-dimmks$(objext) \
s-direio$(objext) \
+ s-dlmkio$(objext) \
s-dmotpr$(objext) \
s-dsaser$(objext) \
s-elaall$(objext) \
@@ -2131,15 +2140,10 @@ ifeq ($(strip $(filter-out arm% linux-gnueabi%,$(target_cpu) $(target_os))),)
$(ATOMICS_BUILTINS_TARGET_PAIRS) \
system.ads<libgnat/system-linux-arm.ads
- ifeq ($(strip $(filter-out arm%b,$(target_cpu))),)
- EH_MECHANISM=
- else
- EH_MECHANISM=-arm
- endif
-
TOOLS_TARGET_PAIRS = indepsw.adb<indepsw-gnu.adb
EXTRA_GNATRTL_TASKING_OBJS=s-linux.o
+ EH_MECHANISM=-arm
THREADSLIB = -lpthread
GNATLIB_SHARED = gnatlib-shared-dual
GMEM_LIB = gmemlib
@@ -2761,4 +2765,3 @@ a-tags.o : a-tags.adb a-tags.ads
s-memory.o : s-memory.adb s-memory.ads
$(ADAC) -c $(ALL_ADAFLAGS) $(NO_SIBLING_ADAFLAGS) $(ADA_INCLUDES) \
$< $(OUTPUT_OPTION)
-
diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb
index 871f1f7..1704a2f 100644
--- a/gcc/ada/checks.adb
+++ b/gcc/ada/checks.adb
@@ -4490,6 +4490,11 @@ package body Checks is
or else not Is_Discrete_Type (Typ)
+ -- Don't deal with enumerated types with non-standard representation
+
+ or else (Is_Enumeration_Type (Typ)
+ and then Present (Enum_Pos_To_Rep (Base_Type (Typ))))
+
-- Ignore type for which an error has been posted, since range in
-- this case may well be a bogosity deriving from the error. Also
-- ignore if error posted on the reference node.
@@ -6758,9 +6763,36 @@ package body Checks is
-----------------------------
procedure Convert_And_Check_Range is
- Tnn : constant Entity_Id := Make_Temporary (Loc, 'T', N);
+ Tnn : constant Entity_Id := Make_Temporary (Loc, 'T', N);
+ Conv_Node : Node_Id;
begin
+ -- For enumeration types with non-standard representation this is a
+ -- direct conversion from the enumeration type to the target integer
+ -- type, which is treated by the back end as a normal integer type
+ -- conversion, treating the enumeration type as an integer, which is
+ -- exactly what we want. We set Conversion_OK to make sure that the
+ -- analyzer does not complain about what otherwise might be an
+ -- illegal conversion.
+
+ if Is_Enumeration_Type (Source_Base_Type)
+ and then Present (Enum_Pos_To_Rep (Source_Base_Type))
+ and then Is_Integer_Type (Target_Base_Type)
+ then
+ Conv_Node :=
+ OK_Convert_To
+ (Typ => Target_Base_Type,
+ Expr => Duplicate_Subexpr (N));
+
+ -- Common case
+
+ else
+ Conv_Node :=
+ Make_Type_Conversion (Loc,
+ Subtype_Mark => New_Occurrence_Of (Target_Base_Type, Loc),
+ Expression => Duplicate_Subexpr (N));
+ end if;
+
-- We make a temporary to hold the value of the converted value
-- (converted to the base type), and then do the test against this
-- temporary. The conversion itself is replaced by an occurrence of
@@ -6776,10 +6808,7 @@ package body Checks is
Defining_Identifier => Tnn,
Object_Definition => New_Occurrence_Of (Target_Base_Type, Loc),
Constant_Present => True,
- Expression =>
- Make_Type_Conversion (Loc,
- Subtype_Mark => New_Occurrence_Of (Target_Base_Type, Loc),
- Expression => Duplicate_Subexpr (N))),
+ Expression => Conv_Node),
Make_Raise_Constraint_Error (Loc,
Condition =>
diff --git a/gcc/ada/checks.ads b/gcc/ada/checks.ads
index 85affc4..f2eed3d 100644
--- a/gcc/ada/checks.ads
+++ b/gcc/ada/checks.ads
@@ -310,14 +310,16 @@ package Checks is
-- then OK is True on return, and Lo and Hi are set to a conservative
-- estimate of the possible range of values of N. Thus if OK is True on
-- return, the value of the subexpression N is known to lie in the range
- -- Lo .. Hi (inclusive). If the expression is not of a discrete type, or
- -- some kind of error condition is detected, then OK is False on exit, and
- -- Lo/Hi are set to No_Uint. Thus the significance of OK being False on
- -- return is that no useful information is available on the range of the
- -- expression. Assume_Valid determines whether the processing is allowed to
- -- assume that values are in range of their subtypes. If it is set to True,
- -- then this assumption is valid, if False, then processing is done using
- -- base types to allow invalid values.
+ -- Lo .. Hi (inclusive). For enumeration and character literals the values
+ -- returned are the Pos value in the relevant enumeration type. If the
+ -- expression is not of a discrete type, or some kind of error condition
+ -- is detected, then OK is False on exit, and Lo/Hi are set to No_Uint.
+ -- Thus the significance of OK being False on return is that no useful
+ -- information is available on the range of the expression. Assume_Valid
+ -- determines whether the processing is allowed to assume that values are
+ -- in range of their subtypes. If it is set to True, then this assumption
+ -- is valid, if False, then processing is done using base types to allow
+ -- invalid values.
procedure Determine_Range_R
(N : Node_Id;
diff --git a/gcc/ada/contracts.adb b/gcc/ada/contracts.adb
index 5577604..26a8d28 100644
--- a/gcc/ada/contracts.adb
+++ b/gcc/ada/contracts.adb
@@ -32,6 +32,7 @@ with Errout; use Errout;
with Exp_Prag; use Exp_Prag;
with Exp_Tss; use Exp_Tss;
with Exp_Util; use Exp_Util;
+with Freeze; use Freeze;
with Namet; use Namet;
with Nlists; use Nlists;
with Nmake; use Nmake;
@@ -47,6 +48,7 @@ with Sem_Prag; use Sem_Prag;
with Sem_Util; use Sem_Util;
with Sinfo; use Sinfo;
with Snames; use Snames;
+with Stand; use Stand;
with Stringt; use Stringt;
with SCIL_LL; use SCIL_LL;
with Tbuild; use Tbuild;
@@ -589,14 +591,45 @@ package body Contracts is
if Skip_Assert_Exprs then
null;
- -- Otherwise analyze the pre/postconditions
+ -- Otherwise analyze the pre/postconditions. Their expressions
+ -- might include references to types that are not frozen yet, in the
+ -- case where the body is a rewritten expression function that is a
+ -- completion, so freeze all types within before constructing the
+ -- contract code.
else
- Prag := Pre_Post_Conditions (Items);
- while Present (Prag) loop
- Analyze_Pre_Post_Condition_In_Decl_Part (Prag, Freeze_Id);
- Prag := Next_Pragma (Prag);
- end loop;
+ declare
+ Bod : Node_Id;
+ Freeze_Types : Boolean := False;
+
+ begin
+ if Present (Freeze_Id) then
+ Bod := Unit_Declaration_Node (Freeze_Id);
+
+ if Nkind (Bod) = N_Subprogram_Body
+ and then Was_Expression_Function (Bod)
+ and then Ekind (Subp_Id) = E_Function
+ and then Chars (Subp_Id) = Chars (Freeze_Id)
+ and then Subp_Id /= Freeze_Id
+ then
+ Freeze_Types := True;
+ end if;
+ end if;
+
+ Prag := Pre_Post_Conditions (Items);
+ while Present (Prag) loop
+ if Freeze_Types then
+ Freeze_Expr_Types
+ (Def_Id => Subp_Id,
+ Typ => Standard_Boolean,
+ Expr => Expression (Corresponding_Aspect (Prag)),
+ N => Bod);
+ end if;
+
+ Analyze_Pre_Post_Condition_In_Decl_Part (Prag, Freeze_Id);
+ Prag := Next_Pragma (Prag);
+ end loop;
+ end;
end if;
-- Analyze contract-cases and test-cases
diff --git a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
index e79f630..1455087 100644
--- a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
+++ b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
@@ -1692,13 +1692,44 @@ Alphabetical List of All Switches
Maximum_Alignment : Pos; -- Maximum permitted alignment
Max_Unaligned_Field : Pos; -- Maximum size for unaligned bit field
Pointer_Size : Pos; -- System.Address'Size
- Short_Enums : Nat; -- Short foreign convention enums?
+ Short_Enums : Nat; -- Foreign enums use short size?
Short_Size : Pos; -- Standard.Short_Integer'Size
Strict_Alignment : Nat; -- Strict alignment?
System_Allocator_Alignment : Nat; -- Alignment for malloc calls
Wchar_T_Size : Pos; -- Interfaces.C.wchar_t'Size
Words_BE : Nat; -- Words stored big-endian?
+ ``Bits_Per_Unit`` is the number of bits in a storage unit, the equivalent of
+ GCC macro ``BITS_PER_UNIT`` documented as follows: `Define this macro to be
+ the number of bits in an addressable storage unit (byte); normally 8.`
+
+ ``Bits_Per_Word`` is the number of bits in a machine word, the equivalent of
+ GCC macro ``BITS_PER_WORD`` documented as follows: `Number of bits in a word;
+ normally 32.`
+
+ ``Double_Scalar_Alignment`` is the alignment for a scalar whose size is two
+ machine words. It should be the same as the alignment for C ``long_long`` on
+ most targets.
+
+ ``Maximum_Alignment`` is the maximum alignment that the compiler might choose
+ by default for a type or object, which is also the maximum alignment that can
+ be specified in GNAT. It is computed for GCC backends as ``BIGGEST_ALIGNMENT
+ / BITS_PER_UNIT`` where GCC macro ``BIGGEST_ALIGNMENT`` is documented as
+ follows: `Biggest alignment that any data type can require on this machine,
+ in bits.`
+
+ ``Max_Unaligned_Field`` is the maximum size for unaligned bit field, which is
+ 64 for the majority of GCC targets (but can be different on some targets like
+ AAMP).
+
+ ``Strict_Alignment`` is the equivalent of GCC macro ``STRICT_ALIGNMENT``
+ documented as follows: `Define this macro to be the value 1 if instructions
+ will fail to work if given data not on the nominal alignment. If instructions
+ will merely go slower in that case, define this macro as 0.`
+
+ ``System_Allocator_Alignment`` is the guaranteed alignment of data returned
+ by calls to ``malloc``.
+
The format of the input file is as follows. First come the values of
the variables defined above, with one line per value:
diff --git a/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst b/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst
index 3e0c6ff..9cbdb15 100644
--- a/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst
+++ b/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst
@@ -3280,19 +3280,18 @@ to use the proper subtypes in object declarations.
.. index:: MKS_Type type
The simplest way to impose dimensionality checking on a computation is to make
-use of the package ``System.Dim.Mks``,
-which is part of the GNAT library. This
-package defines a floating-point type ``MKS_Type``,
-for which a sequence of
-dimension names are specified, together with their conventional abbreviations.
-The following should be read together with the full specification of the
-package, in file :file:`s-dimmks.ads`.
+use of one of the instantiations of the package ``System.Dim.Generic_Mks``, which
+are part of the GNAT library. This generic package defines a floating-point
+type ``MKS_Type``, for which a sequence of dimension names are specified,
+together with their conventional abbreviations. The following should be read
+together with the full specification of the package, in file
+:file:`s-digemk.ads`.
- .. index:: s-dimmks.ads file
+ .. index:: s-digemk.ads file
.. code-block:: ada
- type Mks_Type is new Long_Long_Float
+ type Mks_Type is new Float_Type
with
Dimension_System => (
(Unit_Name => Meter, Unit_Symbol => 'm', Dim_Symbol => 'L'),
@@ -3336,10 +3335,16 @@ as well as useful multiples of these units:
day : constant Time := 60.0 * 24.0 * min;
...
-Using this package, you can then define a derived unit by
-providing the aspect that
-specifies its dimensions within the MKS system, as well as the string to
-be used for output of a value of that unit:
+There are three instantiations of ``System.Dim.Generic_Mks`` defined in the
+GNAT library:
+
+* ``System.Dim.Float_Mks`` based on ``Float`` defined in :file:`s-diflmk.ads`.
+* ``System.Dim.Long_Mks`` based on ``Long_Float`` defined in :file:`s-dilomk.ads`.
+* ``System.Dim.Mks`` based on ``Long_Long_Float`` defined in :file:`s-dimmks.ads`.
+
+Using one of these packages, you can then define a derived unit by providing
+the aspect that specifies its dimensions within the MKS system, as well as the
+string to be used for output of a value of that unit:
.. code-block:: ada
diff --git a/gcc/ada/einfo.adb b/gcc/ada/einfo.adb
index e89ea5a..52a9435 100644
--- a/gcc/ada/einfo.adb
+++ b/gcc/ada/einfo.adb
@@ -118,7 +118,6 @@ package body Einfo is
-- Alignment Uint14
-- Normalized_Position Uint14
-- Postconditions_Proc Node14
- -- Shadow_Entities List14
-- Discriminant_Number Uint15
-- DT_Position Uint15
@@ -199,7 +198,6 @@ package body Einfo is
-- Corresponding_Remote_Type Node22
-- Enumeration_Rep_Expr Node22
-- Original_Record_Component Node22
- -- Private_View Node22
-- Protected_Formal Node22
-- Scope_Depth_Value Uint22
-- Shared_Var_Procs_Instance Node22
@@ -1182,7 +1180,7 @@ package body Einfo is
pragma Assert
(Is_Subprogram (Id)
or else
- Ekind (Id) = E_Package
+ Ekind_In (Id, E_Entry, E_Entry_Family, E_Package)
or else
Is_Generic_Unit (Id));
return Node13 (Id);
@@ -1193,7 +1191,7 @@ package body Einfo is
pragma Assert
(Is_Subprogram (Id)
or else
- Ekind (Id) = E_Package
+ Ekind_In (Id, E_Entry, E_Entry_Family, E_Package)
or else
Is_Generic_Unit (Id));
return Flag174 (Id);
@@ -3126,12 +3124,6 @@ package body Einfo is
return Elist18 (Id);
end Private_Dependents;
- function Private_View (Id : E) return N is
- begin
- pragma Assert (Is_Private_Type (Id));
- return Node22 (Id);
- end Private_View;
-
function Protected_Body_Subprogram (Id : E) return E is
begin
pragma Assert (Is_Subprogram (Id) or else Is_Entry (Id));
@@ -3314,12 +3306,6 @@ package body Einfo is
return Flag167 (Id);
end Sec_Stack_Needed_For_Return;
- function Shadow_Entities (Id : E) return S is
- begin
- pragma Assert (Ekind_In (Id, E_Package, E_Generic_Package));
- return List14 (Id);
- end Shadow_Entities;
-
function Shared_Var_Procs_Instance (Id : E) return E is
begin
pragma Assert (Ekind (Id) = E_Variable);
@@ -4412,7 +4398,7 @@ package body Einfo is
pragma Assert
(Is_Subprogram (Id)
or else
- Ekind (Id) = E_Package
+ Ekind_In (Id, E_Entry, E_Entry_Family, E_Package)
or else
Is_Generic_Unit (Id));
Set_Node13 (Id, V);
@@ -4423,7 +4409,7 @@ package body Einfo is
pragma Assert
(Is_Subprogram (Id)
or else
- Ekind (Id) = E_Package
+ Ekind_In (Id, E_Entry, E_Entry_Family, E_Package)
or else
Is_Generic_Unit (Id));
Set_Flag174 (Id, V);
@@ -6376,12 +6362,6 @@ package body Einfo is
Set_Elist18 (Id, V);
end Set_Private_Dependents;
- procedure Set_Private_View (Id : E; V : N) is
- begin
- pragma Assert (Is_Private_Type (Id));
- Set_Node22 (Id, V);
- end Set_Private_View;
-
procedure Set_Prev_Entity (Id : E; V : E) is
begin
Set_Node36 (Id, V);
@@ -6573,12 +6553,6 @@ package body Einfo is
Set_Flag167 (Id, V);
end Set_Sec_Stack_Needed_For_Return;
- procedure Set_Shadow_Entities (Id : E; V : S) is
- begin
- pragma Assert (Ekind_In (Id, E_Package, E_Generic_Package));
- Set_List14 (Id, V);
- end Set_Shadow_Entities;
-
procedure Set_Shared_Var_Procs_Instance (Id : E; V : E) is
begin
pragma Assert (Ekind (Id) = E_Variable);
@@ -10355,7 +10329,9 @@ package body Einfo is
=>
Write_Str ("Component_Clause");
- when E_Function
+ when E_Entry
+ | E_Entry_Family
+ | E_Function
| E_Procedure
| E_Package
| Generic_Unit_Kind
@@ -10403,11 +10379,6 @@ package body Einfo is
=>
Write_Str ("Postconditions_Proc");
- when E_Generic_Package
- | E_Package
- =>
- Write_Str ("Shadow_Entities");
-
when others =>
Write_Str ("Field14??");
end case;
@@ -10843,15 +10814,6 @@ package body Einfo is
when E_Enumeration_Literal =>
Write_Str ("Enumeration_Rep_Expr");
- when E_Limited_Private_Subtype
- | E_Limited_Private_Type
- | E_Private_Subtype
- | E_Private_Type
- | E_Record_Subtype_With_Private
- | E_Record_Type_With_Private
- =>
- Write_Str ("Private_View");
-
when Formal_Kind =>
Write_Str ("Protected_Formal");
diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads
index 8e5bf65..018684d 100644
--- a/gcc/ada/einfo.ads
+++ b/gcc/ada/einfo.ads
@@ -1090,10 +1090,10 @@ package Einfo is
-- to the spec as possible.
-- Elaboration_Entity (Node13)
--- Defined in generic and non-generic package and subprogram entities.
--- This is a counter associated with the unit that is initially set to
--- zero, is incremented when an elaboration request for the unit is
--- made, and is decremented when a finalization request for the unit
+-- Defined in entry, entry family, [generic] package, and subprogram
+-- entities. This is a counter associated with the unit that is initially
+-- set to zero, is incremented when an elaboration request for the unit
+-- is made, and is decremented when a finalization request for the unit
-- is made. This is used for three purposes. First, it is used to
-- implement access before elaboration checks (the counter must be
-- non-zero to call a subprogram at elaboration time). Second, it is
@@ -1110,9 +1110,9 @@ package Einfo is
-- is elaboration code), but is simply not used for any purpose.
-- Elaboration_Entity_Required (Flag174)
--- Defined in generic and non-generic package and subprogram entities.
--- Set only if Elaboration_Entity is non-Empty to indicate that the
--- counter is required to be non-zero even if there is no other
+-- Defined in entry, entry family, [generic] package, and subprogram
+-- entities. Set only if Elaboration_Entity is non-Empty to indicate that
+-- the counter is required to be non-zero even if there is no other
-- elaboration code. This occurs when the Elaboration_Entity counter
-- is used for access before elaboration checks. If the counter is
-- only used to prevent multiple execution of the elaboration code,
@@ -4005,17 +4005,6 @@ package Einfo is
-- declaration of the type is seen. Subprograms that have such an
-- access parameter are also placed in the list of private_dependents.
--- Private_View (Node22)
--- For each private type, three entities are allocated, the private view,
--- the full view, and the shadow entity. The shadow entity contains a
--- copy of the private view and is used for restoring the proper private
--- view after a region in which the full view is visible (and is copied
--- into the entity normally used for the private view during this period
--- of visibility). The Private_View field is self-referential when the
--- private view lives in its normal entity, but in the copy that is made
--- in the shadow entity, it points to the proper location in which to
--- restore the private view saved in the shadow.
-
-- Protected_Body_Subprogram (Node11)
-- Defined in protected operations. References the entity for the
-- subprogram which implements the body of the operation.
@@ -4264,18 +4253,6 @@ package Einfo is
-- returned value of a function and thus should not be released on scope
-- exit.
--- Shadow_Entities (List14)
--- Defined in package and generic package entities. Points to a list
--- of entities that correspond to private types. For each private type
--- a shadow entity is created that holds a copy of the private view.
--- In regions of the program where the full views of these private
--- entities are visible, the full view is copied into the entity that
--- is normally used to hold the private view, but the shadow entity
--- copy is unchanged. The shadow entities are then used to restore the
--- original private views at the end of the region. This list is a
--- standard format list (i.e. First (Shadow_Entities) is the first
--- entry and subsequent entries are obtained using Next.
-
-- Shared_Var_Procs_Instance (Node22)
-- Defined in variables. Set non-Empty only if Is_Shared_Passive is
-- set, in which case this is the entity for the associated instance of
@@ -6058,6 +6035,7 @@ package Einfo is
-- E_Entry_Family
-- Protected_Body_Subprogram (Node11)
-- Barrier_Function (Node12)
+ -- Elaboration_Entity (Node13)
-- Postconditions_Proc (Node14)
-- Entry_Parameters_Type (Node15)
-- First_Entity (Node17)
@@ -6322,7 +6300,6 @@ package Einfo is
-- Underlying_Full_View (Node19)
-- Last_Entity (Node20)
-- Discriminant_Constraint (Elist21)
- -- Private_View (Node22)
-- Stored_Constraint (Elist23)
-- Has_Completion (Flag26)
-- (plus type attributes)
@@ -6401,7 +6378,6 @@ package Einfo is
-- Generic_Homonym (Node11) (generic case only)
-- Associated_Formal_Package (Node12)
-- Elaboration_Entity (Node13)
- -- Shadow_Entities (List14)
-- Related_Instance (Node15) (non-generic case only)
-- First_Private_Entity (Node16)
-- First_Entity (Node17)
@@ -6479,7 +6455,6 @@ package Einfo is
-- Underlying_Full_View (Node19)
-- Last_Entity (Node20)
-- Discriminant_Constraint (Elist21)
- -- Private_View (Node22)
-- Stored_Constraint (Elist23)
-- Has_Completion (Flag26)
-- Is_Controlled_Active (Flag42) (base type only)
@@ -6660,7 +6635,6 @@ package Einfo is
-- Underlying_Full_View (Node19)
-- Last_Entity (Node20)
-- Discriminant_Constraint (Elist21)
- -- Private_View (Node22)
-- Stored_Constraint (Elist23)
-- Interfaces (Elist25)
-- Predicated_Parent (Node38) (subtype only)
@@ -7475,7 +7449,6 @@ package Einfo is
function Prival (Id : E) return E;
function Prival_Link (Id : E) return E;
function Private_Dependents (Id : E) return L;
- function Private_View (Id : E) return N;
function Protected_Body_Subprogram (Id : E) return E;
function Protected_Formal (Id : E) return E;
function Protected_Subprogram (Id : E) return N;
@@ -7508,7 +7481,6 @@ package Einfo is
function Scale_Value (Id : E) return U;
function Scope_Depth_Value (Id : E) return U;
function Sec_Stack_Needed_For_Return (Id : E) return B;
- function Shadow_Entities (Id : E) return S;
function Shared_Var_Procs_Instance (Id : E) return E;
function Size_Check_Code (Id : E) return N;
function Size_Depends_On_Discriminant (Id : E) return B;
@@ -8181,7 +8153,6 @@ package Einfo is
procedure Set_Prival (Id : E; V : E);
procedure Set_Prival_Link (Id : E; V : E);
procedure Set_Private_Dependents (Id : E; V : L);
- procedure Set_Private_View (Id : E; V : N);
procedure Set_Protected_Body_Subprogram (Id : E; V : E);
procedure Set_Protected_Formal (Id : E; V : E);
procedure Set_Protected_Subprogram (Id : E; V : N);
@@ -8214,7 +8185,6 @@ package Einfo is
procedure Set_Scale_Value (Id : E; V : U);
procedure Set_Scope_Depth_Value (Id : E; V : U);
procedure Set_Sec_Stack_Needed_For_Return (Id : E; V : B := True);
- procedure Set_Shadow_Entities (Id : E; V : S);
procedure Set_Shared_Var_Procs_Instance (Id : E; V : E);
procedure Set_Size_Check_Code (Id : E; V : N);
procedure Set_Size_Depends_On_Discriminant (Id : E; V : B := True);
@@ -9058,7 +9028,6 @@ package Einfo is
pragma Inline (Prival);
pragma Inline (Prival_Link);
pragma Inline (Private_Dependents);
- pragma Inline (Private_View);
pragma Inline (Protected_Body_Subprogram);
pragma Inline (Protected_Formal);
pragma Inline (Protected_Subprogram);
@@ -9092,7 +9061,6 @@ package Einfo is
pragma Inline (Scale_Value);
pragma Inline (Scope_Depth_Value);
pragma Inline (Sec_Stack_Needed_For_Return);
- pragma Inline (Shadow_Entities);
pragma Inline (Shared_Var_Procs_Instance);
pragma Inline (Size_Check_Code);
pragma Inline (Size_Depends_On_Discriminant);
@@ -9551,7 +9519,6 @@ package Einfo is
pragma Inline (Set_Prival);
pragma Inline (Set_Prival_Link);
pragma Inline (Set_Private_Dependents);
- pragma Inline (Set_Private_View);
pragma Inline (Set_Protected_Body_Subprogram);
pragma Inline (Set_Protected_Formal);
pragma Inline (Set_Protected_Subprogram);
@@ -9584,7 +9551,6 @@ package Einfo is
pragma Inline (Set_Scale_Value);
pragma Inline (Set_Scope_Depth_Value);
pragma Inline (Set_Sec_Stack_Needed_For_Return);
- pragma Inline (Set_Shadow_Entities);
pragma Inline (Set_Shared_Var_Procs_Instance);
pragma Inline (Set_Size_Check_Code);
pragma Inline (Set_Size_Depends_On_Discriminant);
diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
index 9d9ab6a..f65230f 100644
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -6195,10 +6195,11 @@ package body Exp_Aggr is
-- Look if in place aggregate expansion is possible
-- For object declarations we build the aggregate in place, unless
- -- the array is bit-packed or the component is controlled.
+ -- the array is bit-packed.
-- For assignments we do the assignment in place if all the component
- -- associations have compile-time known values. For other cases we
+ -- associations have compile-time known values, or are default-
+ -- initialized limited components, e.g. tasks. For other cases we
-- create a temporary. The analysis for safety of on-line assignment
-- is delicate, i.e. we don't know how to do it fully yet ???
@@ -6211,7 +6212,12 @@ package body Exp_Aggr is
Establish_Transient_Scope (N, Manage_Sec_Stack => False);
end if;
- if Has_Default_Init_Comps (N) then
+ -- An array of limited components is built in place
+
+ if Is_Limited_Type (Typ) then
+ Maybe_In_Place_OK := True;
+
+ elsif Has_Default_Init_Comps (N) then
Maybe_In_Place_OK := False;
elsif Is_Bit_Packed_Array (Typ)
@@ -6247,15 +6253,17 @@ package body Exp_Aggr is
-- expected to appear in qualified form. In-place expansion eliminates
-- the qualification and eventually violates this SPARK 05 restiction.
- -- Should document the rest of the guards ???
+ -- Arrays of limited components must be built in place. The code
+ -- previously excluded controlled components but this is an old
+ -- oversight: the rules in 7.6 (17) are clear.
- if not Has_Default_Init_Comps (N)
+ if (not Has_Default_Init_Comps (N)
+ or else Is_Limited_Type (Etype (N)))
and then Comes_From_Source (Parent_Node)
and then Parent_Kind = N_Object_Declaration
and then Present (Expression (Parent_Node))
and then not
Must_Slide (Etype (Defining_Identifier (Parent_Node)), Typ)
- and then not Has_Controlled_Component (Typ)
and then not Is_Bit_Packed_Array (Typ)
and then not Restriction_Check_Required (SPARK_05)
then
@@ -6292,6 +6300,15 @@ package body Exp_Aggr is
Set_Expansion_Delayed (N);
return;
+ -- Limited arrays in return statements are expanded when
+ -- enclosing construct is expanded.
+
+ elsif Maybe_In_Place_OK
+ and then Nkind (Parent (N)) = N_Simple_Return_Statement
+ then
+ Set_Expansion_Delayed (N);
+ return;
+
-- In the remaining cases the aggregate is the RHS of an assignment
elsif Maybe_In_Place_OK
@@ -6365,8 +6382,9 @@ package body Exp_Aggr is
Target := New_Occurrence_Of (Tmp, Loc);
else
- if Has_Default_Init_Comps (N) then
-
+ if Has_Default_Init_Comps (N)
+ and then not Maybe_In_Place_OK
+ then
-- Ada 2005 (AI-287): This case has not been analyzed???
raise Program_Error;
diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb
index 469a90e..d789748 100644
--- a/gcc/ada/exp_attr.adb
+++ b/gcc/ada/exp_attr.adb
@@ -3672,29 +3672,35 @@ package body Exp_Attr is
if Is_Fixed_Point_Type (Etype (N)) then
declare
Loc : constant Source_Ptr := Sloc (N);
- Equiv_T : constant Entity_Id := Make_Temporary (Loc, 'T', N);
- Expr : constant Node_Id := Expression (N);
- Fst : constant Entity_Id := Root_Type (Etype (N));
+ Equiv_T : constant Entity_Id := Make_Temporary (Loc, 'T', N);
+ Expr : constant Node_Id := Expression (N);
+ Fst : constant Entity_Id := Root_Type (Etype (N));
Decl : Node_Id;
begin
- Decl := Make_Full_Type_Declaration (Sloc (N),
- Equiv_T,
- Type_Definition =>
- Make_Signed_Integer_Type_Definition (Loc,
- Low_Bound => Make_Integer_Literal (Loc,
- Intval => Corresponding_Integer_Value
- (Type_Low_Bound (Fst))),
- High_Bound => Make_Integer_Literal (Loc,
- Intval => Corresponding_Integer_Value
- (Type_High_Bound (Fst)))));
+ Decl :=
+ Make_Full_Type_Declaration (Sloc (N),
+ Defining_Identifier => Equiv_T,
+ Type_Definition =>
+ Make_Signed_Integer_Type_Definition (Loc,
+ Low_Bound =>
+ Make_Integer_Literal (Loc,
+ Intval =>
+ Corresponding_Integer_Value
+ (Type_Low_Bound (Fst))),
+ High_Bound =>
+ Make_Integer_Literal (Loc,
+ Intval =>
+ Corresponding_Integer_Value
+ (Type_High_Bound (Fst)))));
Insert_Action (N, Decl);
- -- Verify that the conversion is possible.
- Generate_Range_Check
- (Expr, Equiv_T, CE_Overflow_Check_Failed);
+ -- Verify that the conversion is possible
+
+ Generate_Range_Check (Expr, Equiv_T, CE_Overflow_Check_Failed);
+
+ -- and verify that the result is in range
- -- and verify that the result is in range.
Generate_Range_Check (N, Etype (N), CE_Range_Check_Failed);
end;
end if;
diff --git a/gcc/ada/exp_cg.adb b/gcc/ada/exp_cg.adb
index 00f029b..f40dc7e 100644
--- a/gcc/ada/exp_cg.adb
+++ b/gcc/ada/exp_cg.adb
@@ -121,7 +121,14 @@ package body Exp_CG is
for J in Call_Graph_Nodes.First .. Call_Graph_Nodes.Last loop
N := Call_Graph_Nodes.Table (J);
- if Nkind (N) in N_Subprogram_Call then
+ -- No action needed for subprogram calls removed by the expander
+ -- (for example, calls to ignored ghost entities).
+
+ if Nkind (N) = N_Null_Statement then
+ pragma Assert (Nkind (Original_Node (N)) in N_Subprogram_Call);
+ null;
+
+ elsif Nkind (N) in N_Subprogram_Call then
Write_Call_Info (N);
else pragma Assert (Nkind (N) = N_Defining_Identifier);
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index 224f4c7..e08b748 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -6402,12 +6402,13 @@ package body Exp_Ch6 is
and then Is_Protected_Type (Etype (Prefix (Name (Parent (N)))))
and then Is_Entity_Name (Name (N))
and then Scope (Entity (Name (N))) =
- Etype (Prefix (Name (Parent (N))))
+ Etype (Prefix (Name (Parent (N))))
then
Rewrite (Name (N),
Make_Selected_Component (Sloc (N),
- Prefix => New_Copy_Tree (Prefix (Name (Parent (N)))),
+ Prefix => New_Copy_Tree (Prefix (Name (Parent (N)))),
Selector_Name => Relocate_Node (Name (N))));
+
Analyze_And_Resolve (N);
return;
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index 1b8b8f2..ee04b22 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -4030,8 +4030,8 @@ package body Exp_Ch7 is
-----------------------
function First_Local_Scope (L : List_Id) return Entity_Id is
- Stat : Node_Id;
Scop : Entity_Id;
+ Stat : Node_Id;
begin
Stat := First (L);
@@ -4099,6 +4099,7 @@ package body Exp_Ch7 is
when others =>
null;
end case;
+
Next (Stat);
end loop;
@@ -4119,8 +4120,8 @@ package body Exp_Ch7 is
and then Present (Handled_Statement_Sequence (N))
and then Is_Compilation_Unit (Current_Scope)
then
- Ent := First_Local_Scope
- (Statements (Handled_Statement_Sequence (N)));
+ Ent :=
+ First_Local_Scope (Statements (Handled_Statement_Sequence (N)));
if Present (Ent) then
Elab_Proc :=
diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb
index e7561df..4470c4e 100644
--- a/gcc/ada/exp_ch9.adb
+++ b/gcc/ada/exp_ch9.adb
@@ -476,10 +476,13 @@ package body Exp_Ch9 is
-- ...
-- <actualN> := P.<formalN>;
- procedure Reset_Scopes_To (Proc_Body : Node_Id; E : Entity_Id);
- -- Reset the scope of declarations and blocks at the top level of Proc_Body
- -- to be E. Used after expanding entry bodies into their corresponding
- -- procedures.
+ procedure Reset_Scopes_To (Bod : Node_Id; E : Entity_Id);
+ -- Reset the scope of declarations and blocks at the top level of Bod
+ -- to be E. Bod is either a block or a subprogram body. Used after
+ -- expanding various kinds of entry bodies into their corresponding
+ -- constructs. This is needed during unnesting to determine whether a
+ -- body geenrated for an entry or an accept alternative includes uplevel
+ -- references.
function Trivial_Accept_OK return Boolean;
-- If there is no DO-END block for an accept, or if the DO-END block has
@@ -3807,7 +3810,7 @@ package body Exp_Ch9 is
New_Occurrence_Of
(RTE (RE_Get_GNAT_Exception), Loc)))))))));
- Reset_Scopes_To (Proc_Body, Bod_Id);
+ Reset_Scopes_To (Proc_Body, Protected_Body_Subprogram (Ent));
return Proc_Body;
end if;
end Build_Protected_Entry;
@@ -8238,6 +8241,8 @@ package body Exp_Ch9 is
end if;
Analyze (N);
+
+ Reset_Scopes_To (N, Entity (Identifier (N)));
end Expand_N_Conditional_Entry_Call;
---------------------------------------
@@ -12651,7 +12656,7 @@ package body Exp_Ch9 is
Expression => D_Disc));
-- Do the assignment at this stage only because the evaluation of the
- -- expression must not occur before (see ACVC C97302A).
+ -- expression must not occur earlier (see ACVC C97302A).
Append_To (Stmts,
Make_Assignment_Statement (Loc,
@@ -12848,7 +12853,7 @@ package body Exp_Ch9 is
end loop;
-- Do the assignment at this stage only because the evaluation
- -- of the expression must not occur before (see ACVC C97302A).
+ -- of the expression must not occur earlier (see ACVC C97302A).
Insert_Before (Stmt,
Make_Assignment_Statement (Loc,
@@ -12933,6 +12938,21 @@ package body Exp_Ch9 is
Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
Analyze (N);
+
+ -- Some items in Decls used to be in the N_Block in E_Call that
+ -- is constructed in Expand_Entry_Call, and are now in the new
+ -- Block into which N has been rewritten. Adjust their scopes
+ -- to reflect that.
+
+ if Nkind (E_Call) = N_Block_Statement then
+ Obj := First_Entity (Entity (Identifier (E_Call)));
+ while Present (Obj) loop
+ Set_Scope (Obj, Entity (Identifier (N)));
+ Next_Entity (Obj);
+ end loop;
+ end if;
+
+ Reset_Scopes_To (N, Entity (Identifier (N)));
end Expand_N_Timed_Entry_Call;
----------------------------------------
@@ -14830,11 +14850,12 @@ package body Exp_Ch9 is
-- Reset_Scopes_To --
---------------------
- procedure Reset_Scopes_To (Proc_Body : Node_Id; E : Entity_Id) is
+ procedure Reset_Scopes_To (Bod : Node_Id; E : Entity_Id) is
function Reset_Scope (N : Node_Id) return Traverse_Result;
-- Temporaries may have been declared during expansion of the procedure
- -- alternative. Indicate that their scope is the new body, to prevent
- -- generation of spurious uplevel references for these entities.
+ -- created for an entry body or an accept alternative. Indicate that
+ -- their scope is the new body, to unsure proper generation of uplevel
+ -- references where needed during unnesting.
procedure Reset_Scopes is new Traverse_Proc (Reset_Scope);
@@ -14849,19 +14870,26 @@ package body Exp_Ch9 is
-- If this is a block statement with an Identifier, it forms a scope,
-- so we want to reset its scope but not look inside.
- if Nkind (N) = N_Block_Statement
+ if N /= Bod
+ and then Nkind (N) = N_Block_Statement
and then Present (Identifier (N))
then
Set_Scope (Entity (Identifier (N)), E);
return Skip;
- elsif Nkind (N) = N_Package_Declaration then
+ -- Ditto for a package declaration or a full type declaration, etc.
+
+ elsif Nkind (N) = N_Package_Declaration
+ or else Nkind (N) in N_Declaration
+ or else Nkind (N) in N_Renaming_Declaration
+ then
Set_Scope (Defining_Entity (N), E);
return Skip;
- elsif N = Proc_Body then
+ elsif N = Bod then
- -- Scan declarations
+ -- Scan declarations in new body. Declarations in the statement
+ -- part will be handled during later traversal.
Decl := First (Declarations (N));
while Present (Decl) loop
@@ -14869,10 +14897,8 @@ package body Exp_Ch9 is
Next (Decl);
end loop;
- elsif N /= Proc_Body and then Nkind (N) in N_Proper_Body then
+ elsif N /= Bod and then Nkind (N) in N_Proper_Body then
return Skip;
- elsif Nkind (N) = N_Defining_Identifier then
- Set_Scope (N, E);
end if;
return OK;
@@ -14881,7 +14907,7 @@ package body Exp_Ch9 is
-- Start of processing for Reset_Scopes_To
begin
- Reset_Scopes (Proc_Body);
+ Reset_Scopes (Bod);
end Reset_Scopes_To;
----------------------
diff --git a/gcc/ada/exp_unst.adb b/gcc/ada/exp_unst.adb
index c5b03c4..d688157 100644
--- a/gcc/ada/exp_unst.adb
+++ b/gcc/ada/exp_unst.adb
@@ -260,12 +260,10 @@ package body Exp_Unst is
E := Ultimate_Alias (E);
-- The body of a protected operation has a different name and
- -- has been scanned at this point, and thus has an entry in
- -- the subprogram table.
+ -- has been scanned at this point, and thus has an entry in the
+ -- subprogram table.
- if E = Sub
- and then Convention (E) = Convention_Protected
- then
+ if E = Sub and then Convention (E) = Convention_Protected then
E := Protected_Body_Subprogram (E);
end if;
@@ -551,9 +549,8 @@ package body Exp_Unst is
-- Explicit dereference and selected component case
- elsif Nkind_In (N,
- N_Explicit_Dereference,
- N_Selected_Component)
+ elsif Nkind_In (N, N_Explicit_Dereference,
+ N_Selected_Component)
then
Note_Uplevel_Bound (Prefix (N), Ref);
diff --git a/gcc/ada/exp_unst.ads b/gcc/ada/exp_unst.ads
index 3b67a0d..a5cdf06 100644
--- a/gcc/ada/exp_unst.ads
+++ b/gcc/ada/exp_unst.ads
@@ -477,7 +477,7 @@ package Exp_Unst is
-- subprograms exist. Similarly overloading would cause a naming issue.
-- In fact, the expanded code includes qualified names which eliminate this
- -- problem. We omitted the qualification from the exapnded examples above
+ -- problem. We omitted the qualification from the expanded examples above
-- for simplicity. But to see this in action, consider this example:
-- function Mnames return Boolean is
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index 3bed508..314e3ee 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -8402,9 +8402,23 @@ package body Exp_Util is
declare
Align_In_Bits : constant Nat := M * System_Storage_Unit;
+ Comp : Entity_Id;
+
begin
- if Component_Bit_Offset (C) mod Align_In_Bits /= 0
- or else Esize (C) mod Align_In_Bits /= 0
+ Comp := C;
+
+ -- For a component inherited in a record extension, the
+ -- clause is inherited but position and size are not set.
+
+ if Is_Base_Type (Etype (P))
+ and then Is_Tagged_Type (Etype (P))
+ and then Present (Original_Record_Component (Comp))
+ then
+ Comp := Original_Record_Component (Comp);
+ end if;
+
+ if Component_Bit_Offset (Comp) mod Align_In_Bits /= 0
+ or else Esize (Comp) mod Align_In_Bits /= 0
then
return True;
end if;
diff --git a/gcc/ada/fe.h b/gcc/ada/fe.h
index 1928609..2d07aa5 100644
--- a/gcc/ada/fe.h
+++ b/gcc/ada/fe.h
@@ -85,7 +85,7 @@ extern void Set_RM_Size (Entity_Id, Uint);
extern Boolean Is_Entity_Name (Node_Id);
#define Get_Attribute_Definition_Clause einfo__get_attribute_definition_clause
-extern Node_Id Get_Attribute_Definition_Clause (Entity_Id, char);
+extern Node_Id Get_Attribute_Definition_Clause (Entity_Id, unsigned char);
/* errout: */
diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb
index 9979cbf..5036a79 100644
--- a/gcc/ada/freeze.adb
+++ b/gcc/ada/freeze.adb
@@ -49,6 +49,7 @@ with Rtsfind; use Rtsfind;
with Sem; use Sem;
with Sem_Aux; use Sem_Aux;
with Sem_Cat; use Sem_Cat;
+with Sem_Ch3; use Sem_Ch3;
with Sem_Ch6; use Sem_Ch6;
with Sem_Ch7; use Sem_Ch7;
with Sem_Ch8; use Sem_Ch8;
@@ -3611,10 +3612,14 @@ package body Freeze is
Error_Msg_Qual_Level := 1;
- -- Check suspicious use of fat C pointer
+ -- Check suspicious use of fat C pointer, but do not emit
+ -- a warning on an access to subprogram when unnesting is
+ -- active.
if Is_Access_Type (F_Type)
and then Esize (F_Type) > Ttypes.System_Address_Size
+ and then (not Unnest_Subprogram_Mode
+ or else not Is_Access_Subprogram_Type (F_Type))
then
Error_Msg_N
("?x?type of & does not correspond to C pointer!", Formal);
@@ -7639,6 +7644,208 @@ package body Freeze is
In_Spec_Expression := In_Spec_Exp;
end Freeze_Expression;
+ -----------------------
+ -- Freeze_Expr_Types --
+ -----------------------
+
+ procedure Freeze_Expr_Types
+ (Def_Id : Entity_Id;
+ Typ : Entity_Id;
+ Expr : Node_Id;
+ N : Node_Id)
+ is
+ function Cloned_Expression return Node_Id;
+ -- Build a duplicate of the expression of the return statement that has
+ -- no defining entities shared with the original expression.
+
+ function Freeze_Type_Refs (Node : Node_Id) return Traverse_Result;
+ -- Freeze all types referenced in the subtree rooted at Node
+
+ -----------------------
+ -- Cloned_Expression --
+ -----------------------
+
+ function Cloned_Expression return Node_Id is
+ function Clone_Id (Node : Node_Id) return Traverse_Result;
+ -- Tree traversal routine that clones the defining identifier of
+ -- iterator and loop parameter specification nodes.
+
+ --------------
+ -- Clone_Id --
+ --------------
+
+ function Clone_Id (Node : Node_Id) return Traverse_Result is
+ begin
+ if Nkind_In (Node, N_Iterator_Specification,
+ N_Loop_Parameter_Specification)
+ then
+ Set_Defining_Identifier
+ (Node, New_Copy (Defining_Identifier (Node)));
+ end if;
+
+ return OK;
+ end Clone_Id;
+
+ procedure Clone_Def_Ids is new Traverse_Proc (Clone_Id);
+
+ -- Local variable
+
+ Dup_Expr : constant Node_Id := New_Copy_Tree (Expr);
+
+ -- Start of processing for Cloned_Expression
+
+ begin
+ -- We must duplicate the expression with semantic information to
+ -- inherit the decoration of global entities in generic instances.
+ -- Set the parent of the new node to be the parent of the original
+ -- to get the proper context, which is needed for complete error
+ -- reporting and for semantic analysis.
+
+ Set_Parent (Dup_Expr, Parent (Expr));
+
+ -- Replace the defining identifier of iterators and loop param
+ -- specifications by a clone to ensure that the cloned expression
+ -- and the original expression don't have shared identifiers;
+ -- otherwise, as part of the preanalysis of the expression, these
+ -- shared identifiers may be left decorated with itypes which
+ -- will not be available in the tree passed to the backend.
+
+ Clone_Def_Ids (Dup_Expr);
+
+ return Dup_Expr;
+ end Cloned_Expression;
+
+ ----------------------
+ -- Freeze_Type_Refs --
+ ----------------------
+
+ function Freeze_Type_Refs (Node : Node_Id) return Traverse_Result is
+ procedure Check_And_Freeze_Type (Typ : Entity_Id);
+ -- Check that Typ is fully declared and freeze it if so
+
+ ---------------------------
+ -- Check_And_Freeze_Type --
+ ---------------------------
+
+ procedure Check_And_Freeze_Type (Typ : Entity_Id) is
+ begin
+ -- Skip Itypes created by the preanalysis, and itypes whose
+ -- scope is another type (i.e. component subtypes that depend
+ -- on a discriminant),
+
+ if Is_Itype (Typ)
+ and then (Scope_Within_Or_Same (Scope (Typ), Def_Id)
+ or else Is_Type (Scope (Typ)))
+ then
+ return;
+ end if;
+
+ -- This provides a better error message than generating primitives
+ -- whose compilation fails much later. Refine the error message if
+ -- possible.
+
+ Check_Fully_Declared (Typ, Node);
+
+ if Error_Posted (Node) then
+ if Has_Private_Component (Typ)
+ and then not Is_Private_Type (Typ)
+ then
+ Error_Msg_NE ("\type& has private component", Node, Typ);
+ end if;
+
+ else
+ Freeze_Before (N, Typ);
+ end if;
+ end Check_And_Freeze_Type;
+
+ -- Start of processing for Freeze_Type_Refs
+
+ begin
+ -- Check that a type referenced by an entity can be frozen
+
+ if Is_Entity_Name (Node) and then Present (Entity (Node)) then
+ Check_And_Freeze_Type (Etype (Entity (Node)));
+
+ -- Check that the enclosing record type can be frozen
+
+ if Ekind_In (Entity (Node), E_Component, E_Discriminant) then
+ Check_And_Freeze_Type (Scope (Entity (Node)));
+ end if;
+
+ -- Freezing an access type does not freeze the designated type, but
+ -- freezing conversions between access to interfaces requires that
+ -- the interface types themselves be frozen, so that dispatch table
+ -- entities are properly created.
+
+ -- Unclear whether a more general rule is needed ???
+
+ elsif Nkind (Node) = N_Type_Conversion
+ and then Is_Access_Type (Etype (Node))
+ and then Is_Interface (Designated_Type (Etype (Node)))
+ then
+ Check_And_Freeze_Type (Designated_Type (Etype (Node)));
+ end if;
+
+ -- An implicit dereference freezes the designated type. In the case
+ -- of a dispatching call whose controlling argument is an access
+ -- type, the dereference is not made explicit, so we must check for
+ -- such a call and freeze the designated type.
+
+ if Nkind (Node) in N_Has_Etype
+ and then Present (Etype (Node))
+ and then Is_Access_Type (Etype (Node))
+ and then Nkind (Parent (Node)) = N_Function_Call
+ and then Node = Controlling_Argument (Parent (Node))
+ then
+ Check_And_Freeze_Type (Designated_Type (Etype (Node)));
+ end if;
+
+ -- No point in posting several errors on the same expression
+
+ if Serious_Errors_Detected > 0 then
+ return Abandon;
+ else
+ return OK;
+ end if;
+ end Freeze_Type_Refs;
+
+ procedure Freeze_References is new Traverse_Proc (Freeze_Type_Refs);
+
+ -- Local variables
+
+ Saved_First_Entity : constant Entity_Id := First_Entity (Def_Id);
+ Saved_Last_Entity : constant Entity_Id := Last_Entity (Def_Id);
+ Dup_Expr : constant Node_Id := Cloned_Expression;
+
+ -- Start of processing for Freeze_Expr_Types
+
+ begin
+ -- Preanalyze a duplicate of the expression to have available the
+ -- minimum decoration needed to locate referenced unfrozen types
+ -- without adding any decoration to the function expression.
+
+ Push_Scope (Def_Id);
+ Install_Formals (Def_Id);
+
+ Preanalyze_Spec_Expression (Dup_Expr, Typ);
+ End_Scope;
+
+ -- Restore certain attributes of Def_Id since the preanalysis may
+ -- have introduced itypes to this scope, thus modifying attributes
+ -- First_Entity and Last_Entity.
+
+ Set_First_Entity (Def_Id, Saved_First_Entity);
+ Set_Last_Entity (Def_Id, Saved_Last_Entity);
+
+ if Present (Last_Entity (Def_Id)) then
+ Set_Next_Entity (Last_Entity (Def_Id), Empty);
+ end if;
+
+ -- Freeze all types referenced in the expression
+
+ Freeze_References (Dup_Expr);
+ end Freeze_Expr_Types;
+
-----------------------------
-- Freeze_Fixed_Point_Type --
-----------------------------
diff --git a/gcc/ada/freeze.ads b/gcc/ada/freeze.ads
index 20badd0..96b3c90 100644
--- a/gcc/ada/freeze.ads
+++ b/gcc/ada/freeze.ads
@@ -230,6 +230,17 @@ package Freeze is
-- so need to be similarly treated. Freeze_Expression takes care of
-- determining the proper insertion point for generated freeze actions.
+ procedure Freeze_Expr_Types
+ (Def_Id : Entity_Id;
+ Typ : Entity_Id;
+ Expr : Node_Id;
+ N : Node_Id);
+ -- N is the body constructed for an expression function that is a
+ -- completion, and Def_Id is the function being completed.
+ -- This procedure freezes before N all the types referenced in Expr,
+ -- which is either the expression of the expression function, or
+ -- the expression in a pre/post aspect that applies to Def_Id;
+
procedure Freeze_Fixed_Point_Type (Typ : Entity_Id);
-- Freeze fixed point type. For fixed-point types, we have to defer
-- setting the size and bounds till the freeze point, since they are
diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in
index d51d397..d8dac73 100644
--- a/gcc/ada/gcc-interface/Make-lang.in
+++ b/gcc/ada/gcc-interface/Make-lang.in
@@ -319,6 +319,7 @@ GNAT_ADA_OBJS = \
ada/libgnat/g-dynhta.o \
ada/libgnat/g-hesora.o \
ada/libgnat/g-htable.o \
+ ada/libgnat/g-lists.o \
ada/libgnat/g-spchge.o \
ada/libgnat/g-speche.o \
ada/libgnat/g-u3spch.o \
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in
index 601f23a..4d870c2 100644
--- a/gcc/ada/gcc-interface/Makefile.in
+++ b/gcc/ada/gcc-interface/Makefile.in
@@ -441,6 +441,11 @@ ifeq ($(ENABLE_VXADDR2LINE),true)
TOOLSCASE=cross top_buildir=../../.. \
../../vxaddr2line$(exeext)
endif
+ifeq ($(ENABLE_VXLINK),true)
+ $(MAKE) -C tools -f ../Makefile $(TOOLS_FLAGS_TO_PASS) \
+ TOOLSCASE=cross top_build=../../.. \
+ ../../vxlink$(exeext)
+endif
common-tools: ../stamp-tools
$(GNATMAKE) -j0 -c -b $(ADA_INCLUDES) \
@@ -478,6 +483,12 @@ common-tools: ../stamp-tools
$(GNATLINK) -v vxaddr2line -o $@ \
--GCC="$(CC) $(ADA_INCLUDES)" --LINK="$(GCC_LINK)" ../targext.o $(CLIB)
+../../vxlink$(exeext): ../stamp-tools
+ $(GNATMAKE) -c $(ADA_INCLUDES) vxlink-main --GCC="$(CC) $(ALL_ADAFLAGS)"
+ $(GNATBIND) $(ADA_INCLUDES) $(GNATBIND_FLAGS) vxlink-main
+ $(GNATLINK) -v vxlink-main -o $@ \
+ --GCC="$(CC) $(ADA_INCLUDES)" --LINK="$(GCC_LINK)"
+
gnatmake-re: ../stamp-tools
$(GNATMAKE) -j0 $(ADA_INCLUDES) -u sdefault --GCC="$(CC) $(MOST_ADA_FLAGS)"
$(GNATMAKE) -j0 -c $(ADA_INCLUDES) gnatmake --GCC="$(CC) $(ALL_ADAFLAGS)"
@@ -613,7 +624,7 @@ OSCONS_EXTRACT=$(OSCONS_CC) $(GNATLIBCFLAGS_FOR_C) -S s-oscons-tmplt.i
-$(MKDIR) ./bldtools/oscons
$(RM) $(addprefix ./bldtools/oscons/,$(notdir $^))
$(CP) $^ ./bldtools/oscons
- (cd ./bldtools/oscons ; $(GNATMAKE) -q xoscons)
+ (cd ./bldtools/oscons ; gnatmake -q xoscons)
$(RTSDIR)/s-oscons.ads: ../stamp-gnatlib1-$(RTSDIR) s-oscons-tmplt.c gsocket.h ./bldtools/oscons/xoscons
$(RM) $(RTSDIR)/s-oscons-tmplt.i $(RTSDIR)/s-oscons-tmplt.s
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index b1dc379..6f605bd 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -5421,7 +5421,7 @@ update_profile (Entity_Id gnat_subprog)
if (DECL_P (gnu_type))
{
/* Builtins cannot have their address taken so we can reset them. */
- gcc_assert (DECL_BUILT_IN (gnu_type));
+ gcc_assert (fndecl_built_in_p (gnu_type));
save_gnu_tree (gnat_subprog, NULL_TREE, false);
save_gnu_tree (gnat_subprog, gnu_type, false);
return;
diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h
index a75cb90..eb64a8b 100644
--- a/gcc/ada/gcc-interface/gigi.h
+++ b/gcc/ada/gcc-interface/gigi.h
@@ -285,7 +285,7 @@ extern void process_type (Entity_Id gnat_entity);
location and false if it doesn't. If CLEAR_COLUMN is true, set the column
information to 0. */
extern bool Sloc_to_locus (Source_Ptr Sloc, location_t *locus,
- bool clear_column = false);
+ bool clear_column = false, const_tree decl = 0);
/* Post an error message. MSG is the error message, properly annotated.
NODE is the node at which to post the error and the node to use for the
@@ -1081,7 +1081,7 @@ call_is_atomic_load (tree exp)
{
tree fndecl = get_callee_fndecl (exp);
- if (!(fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL))
+ if (!(fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)))
return false;
enum built_in_function code = DECL_FUNCTION_CODE (fndecl);
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 31e098a..940bf5f 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -41,6 +41,7 @@
#include "stmt.h"
#include "varasm.h"
#include "output.h"
+#include "debug.h"
#include "libfuncs.h" /* For set_stack_check_libfunc. */
#include "tree-iterator.h"
#include "gimplify.h"
@@ -255,6 +256,12 @@ static tree create_init_temporary (const char *, tree, tree *, Node_Id);
static const char *extract_encoding (const char *) ATTRIBUTE_UNUSED;
static const char *decode_name (const char *) ATTRIBUTE_UNUSED;
+/* This makes gigi's file_info_ptr visible in this translation unit,
+ so that Sloc_to_locus can look it up when deciding whether to map
+ decls to instances. */
+
+static struct File_Info_Type *file_map;
+
/* This is the main program of the back-end. It sets up all the table
structures and then generates code. */
@@ -300,6 +307,12 @@ gigi (Node_Id gnat_root,
type_annotate_only = (gigi_operating_mode == 1);
+ if (Generate_SCO_Instance_Table != 0)
+ {
+ file_map = file_info_ptr;
+ maybe_create_decl_to_instance_map (number_file);
+ }
+
for (i = 0; i < number_file; i++)
{
/* Use the identifier table to make a permanent copy of the filename as
@@ -701,6 +714,7 @@ gigi (Node_Id gnat_root,
}
/* Destroy ourselves. */
+ file_map = NULL;
destroy_gnat_decl ();
destroy_gnat_utils ();
@@ -3771,7 +3785,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
}
/* Set the line number in the decl to correspond to that of the body. */
- if (!Sloc_to_locus (Sloc (gnat_node), &locus))
+ if (!Sloc_to_locus (Sloc (gnat_node), &locus, false, gnu_subprog_decl))
locus = input_location;
DECL_SOURCE_LOCATION (gnu_subprog_decl) = locus;
@@ -4436,6 +4450,7 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
const bool suppress_type_conversion
= ((Nkind (gnat_actual) == N_Unchecked_Type_Conversion
&& (!in_param
+ || !is_by_ref_formal_parm
|| (Is_Composite_Type (Underlying_Type (gnat_formal_type))
&& !Is_Constrained (Underlying_Type (gnat_formal_type)))))
|| (Nkind (gnat_actual) == N_Type_Conversion
@@ -9970,12 +9985,14 @@ maybe_implicit_deref (tree exp)
return exp;
}
-/* Convert SLOC into LOCUS. Return true if SLOC corresponds to a source code
- location and false if it doesn't. If CLEAR_COLUMN is true, set the column
- information to 0. */
+/* Convert SLOC into LOCUS. Return true if SLOC corresponds to a
+ source code location and false if it doesn't. If CLEAR_COLUMN is
+ true, set the column information to 0. If DECL is given and SLOC
+ refers to a File with an instance, map DECL to that instance. */
bool
-Sloc_to_locus (Source_Ptr Sloc, location_t *locus, bool clear_column)
+Sloc_to_locus (Source_Ptr Sloc, location_t *locus, bool clear_column,
+ const_tree decl)
{
if (Sloc == No_Location)
return false;
@@ -9999,6 +10016,9 @@ Sloc_to_locus (Source_Ptr Sloc, location_t *locus, bool clear_column)
*locus
= linemap_position_for_line_and_column (line_table, map, line, column);
+ if (file_map && file_map[file - 1].Instance)
+ decl_to_instance_map->put (decl, file_map[file - 1].Instance);
+
return true;
}
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index cc1fe77..313d984 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -773,7 +773,7 @@ gnat_pushdecl (tree decl, Node_Id gnat_node)
debugger at the proper time. */
if (DECL_EXTERNAL (decl)
&& TREE_CODE (decl) == FUNCTION_DECL
- && DECL_BUILT_IN (decl))
+ && fndecl_built_in_p (decl))
vec_safe_push (builtin_decls, decl);
else if (global_bindings_p ())
vec_safe_push (global_decls, decl);
diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi
index b5972bb..aeaa146 100644
--- a/gcc/ada/gnat_ugn.texi
+++ b/gcc/ada/gnat_ugn.texi
@@ -21,7 +21,7 @@
@copying
@quotation
-GNAT User's Guide for Native Platforms , Jul 13, 2018
+GNAT User's Guide for Native Platforms , Aug 20, 2018
AdaCore
@@ -9429,7 +9429,7 @@ Long_Size : Pos; -- Standard.Long_Integer'Size
Maximum_Alignment : Pos; -- Maximum permitted alignment
Max_Unaligned_Field : Pos; -- Maximum size for unaligned bit field
Pointer_Size : Pos; -- System.Address'Size
-Short_Enums : Nat; -- Short foreign convention enums?
+Short_Enums : Nat; -- Foreign enums use short size?
Short_Size : Pos; -- Standard.Short_Integer'Size
Strict_Alignment : Nat; -- Strict alignment?
System_Allocator_Alignment : Nat; -- Alignment for malloc calls
@@ -9437,6 +9437,32 @@ Wchar_T_Size : Pos; -- Interfaces.C.wchar_t'Size
Words_BE : Nat; -- Words stored big-endian?
@end example
+@code{Bits_Per_Unit} is the number of bits in a storage unit, the equivalent of
+GCC macro @code{BITS_PER_UNIT} documented as follows: @cite{Define this macro to be the number of bits in an addressable storage unit (byte); normally 8.}
+
+@code{Bits_Per_Word} is the number of bits in a machine word, the equivalent of
+GCC macro @code{BITS_PER_WORD} documented as follows: @cite{Number of bits in a word; normally 32.}
+
+@code{Double_Scalar_Alignment} is the alignment for a scalar whose size is two
+machine words. It should be the same as the alignment for C @code{long_long} on
+most targets.
+
+@code{Maximum_Alignment} is the maximum alignment that the compiler might choose
+by default for a type or object, which is also the maximum alignment that can
+be specified in GNAT. It is computed for GCC backends as @code{BIGGEST_ALIGNMENT
+/ BITS_PER_UNIT} where GCC macro @code{BIGGEST_ALIGNMENT} is documented as
+follows: @cite{Biggest alignment that any data type can require on this machine@comma{} in bits.}
+
+@code{Max_Unaligned_Field} is the maximum size for unaligned bit field, which is
+64 for the majority of GCC targets (but can be different on some targets like
+AAMP).
+
+@code{Strict_Alignment} is the equivalent of GCC macro @code{STRICT_ALIGNMENT}
+documented as follows: @cite{Define this macro to be the value 1 if instructions will fail to work if given data not on the nominal alignment. If instructions will merely go slower in that case@comma{} define this macro as 0.}
+
+@code{System_Allocator_Alignment} is the guaranteed alignment of data returned
+by calls to @code{malloc}.
+
The format of the input file is as follows. First come the values of
the variables defined above, with one line per value:
@@ -22606,20 +22632,19 @@ to use the proper subtypes in object declarations.
@geindex MKS_Type type
The simplest way to impose dimensionality checking on a computation is to make
-use of the package @code{System.Dim.Mks},
-which is part of the GNAT library. This
-package defines a floating-point type @code{MKS_Type},
-for which a sequence of
-dimension names are specified, together with their conventional abbreviations.
-The following should be read together with the full specification of the
-package, in file @code{s-dimmks.ads}.
+use of one of the instantiations of the package @code{System.Dim.Generic_Mks}, which
+are part of the GNAT library. This generic package defines a floating-point
+type @code{MKS_Type}, for which a sequence of dimension names are specified,
+together with their conventional abbreviations. The following should be read
+together with the full specification of the package, in file
+@code{s-digemk.ads}.
@quotation
-@geindex s-dimmks.ads file
+@geindex s-digemk.ads file
@example
-type Mks_Type is new Long_Long_Float
+type Mks_Type is new Float_Type
with
Dimension_System => (
(Unit_Name => Meter, Unit_Symbol => 'm', Dim_Symbol => 'L'),
@@ -22674,10 +22699,25 @@ as well as useful multiples of these units:
@end example
@end quotation
-Using this package, you can then define a derived unit by
-providing the aspect that
-specifies its dimensions within the MKS system, as well as the string to
-be used for output of a value of that unit:
+There are three instantiations of @code{System.Dim.Generic_Mks} defined in the
+GNAT library:
+
+
+@itemize *
+
+@item
+@code{System.Dim.Float_Mks} based on @code{Float} defined in @code{s-diflmk.ads}.
+
+@item
+@code{System.Dim.Long_Mks} based on @code{Long_Float} defined in @code{s-dilomk.ads}.
+
+@item
+@code{System.Dim.Mks} based on @code{Long_Long_Float} defined in @code{s-dimmks.ads}.
+@end itemize
+
+Using one of these packages, you can then define a derived unit by providing
+the aspect that specifies its dimensions within the MKS system, as well as the
+string to be used for output of a value of that unit:
@quotation
diff --git a/gcc/ada/gnatlink.adb b/gcc/ada/gnatlink.adb
index 16981b8..5c8bb7d 100644
--- a/gcc/ada/gnatlink.adb
+++ b/gcc/ada/gnatlink.adb
@@ -1103,9 +1103,9 @@ procedure Gnatlink is
-- as it is in the same directory as the shared version.
if Nlast >= Library_Version'Length
- and then Next_Line
- (Nlast - Library_Version'Length + 1 .. Nlast)
- = Library_Version
+ and then
+ Next_Line (Nlast - Library_Version'Length + 1 .. Nlast) =
+ Library_Version
then
-- Set Last to point to last character before the
-- library version.
diff --git a/gcc/ada/impunit.adb b/gcc/ada/impunit.adb
index cfa1d5e..3e5fbe0 100644
--- a/gcc/ada/impunit.adb
+++ b/gcc/ada/impunit.adb
@@ -281,6 +281,7 @@ package body Impunit is
("g-htable", F), -- GNAT.Htable
("g-io ", F), -- GNAT.IO
("g-io_aux", F), -- GNAT.IO_Aux
+ ("g-lists ", F), -- GNAT.Lists
("g-locfil", F), -- GNAT.Lock_Files
("g-mbdira", F), -- GNAT.MBBS_Discrete_Random
("g-mbflra", F), -- GNAT.MBBS_Float_Random
@@ -372,10 +373,18 @@ package body Impunit is
("s-addima", F), -- System.Address_Image
("s-atocou", F), -- System.Atomic_Counters
("s-assert", F), -- System.Assertions
+ ("s-dfmkio", F), -- System.Dim.Float_Mks_IO
+ ("s-dfmopr", F), -- System.Dim.Float_Mks.Other_Prefixes
+ ("s-dgmgop", F), -- System.Dim.Generic_Mks.Generic_Other_Prefixes
+ ("s-dlmopr", F), -- System.Dim.Long_Mks.Other_Prefixes
("s-diflio", F), -- System.Dim.Float_IO
+ ("s-diflmk", F), -- System.Dim.Float_Mks
+ ("s-digemk", F), -- System.Dim.Generic_Mks
("s-diinio", F), -- System.Dim.Integer_IO
+ ("s-dilomk", F), -- System.Dim.Long_Mks
("s-dimkio", F), -- System.Dim.Mks_IO
("s-dimmks", F), -- System.Dim.Mks
+ ("s-dlmkio", F), -- System.Dim.Long_Mks_IO
("s-dmotpr", F), -- System.Dim.Mks.Other_Prefixes
("s-memory", F), -- System.Memory
("s-parint", F), -- System.Partition_Interface
diff --git a/gcc/ada/itypes.adb b/gcc/ada/itypes.adb
index fa88ef7..6640c57 100644
--- a/gcc/ada/itypes.adb
+++ b/gcc/ada/itypes.adb
@@ -42,7 +42,7 @@ package body Itypes is
Related_Nod : Node_Id;
Related_Id : Entity_Id := Empty;
Suffix : Character := ' ';
- Suffix_Index : Nat := 0;
+ Suffix_Index : Int := 0;
Scope_Id : Entity_Id := Current_Scope) return Entity_Id
is
Typ : Entity_Id;
diff --git a/gcc/ada/itypes.ads b/gcc/ada/itypes.ads
index e59cbe8..1513c8a 100644
--- a/gcc/ada/itypes.ads
+++ b/gcc/ada/itypes.ads
@@ -110,7 +110,7 @@ package Itypes is
Related_Nod : Node_Id;
Related_Id : Entity_Id := Empty;
Suffix : Character := ' ';
- Suffix_Index : Nat := 0;
+ Suffix_Index : Int := 0;
Scope_Id : Entity_Id := Current_Scope) return Entity_Id;
-- Used to create a new Itype
--
diff --git a/gcc/ada/layout.adb b/gcc/ada/layout.adb
index 6b77757..a7b24ab 100644
--- a/gcc/ada/layout.adb
+++ b/gcc/ada/layout.adb
@@ -325,6 +325,16 @@ package body Layout is
then
Init_Size (E, 2 * System_Address_Size);
+ -- If unnesting subprograms, subprogram access types contain the
+ -- address of both the subprogram and an activation record. But if we
+ -- set that, we'll get a warning on different unchecked conversion
+ -- sizes in the RTS. So leave unset ub that case.
+
+ elsif Unnest_Subprogram_Mode
+ and then Is_Access_Subprogram_Type (E)
+ then
+ null;
+
-- Normal case of thin pointer
else
diff --git a/gcc/ada/lib-writ.adb b/gcc/ada/lib-writ.adb
index 9a54fa9..a4f9526 100644
--- a/gcc/ada/lib-writ.adb
+++ b/gcc/ada/lib-writ.adb
@@ -744,7 +744,14 @@ package body Lib.Writ is
Note_Unit := U;
end if;
- if Note_Unit = Unit_Num then
+ -- No action needed for pragmas removed by the expander (for
+ -- example, pragmas of ignored ghost entities).
+
+ if Nkind (N) = N_Null_Statement then
+ pragma Assert (Nkind (Original_Node (N)) = N_Pragma);
+ null;
+
+ elsif Note_Unit = Unit_Num then
Write_Info_Initiate ('N');
Write_Info_Char (' ');
@@ -956,10 +963,11 @@ package body Lib.Writ is
-- allow partial analysis on incomplete sources.
if GNATprove_Mode then
-
Body_Fname :=
- Get_File_Name (Get_Body_Name (Uname),
- Subunit => False, May_Fail => True);
+ Get_File_Name
+ (Uname => Get_Body_Name (Uname),
+ Subunit => False,
+ May_Fail => True);
Body_Index := Get_Unit_Index (Get_Body_Name (Uname));
@@ -974,8 +982,10 @@ package body Lib.Writ is
else
Body_Fname :=
- Get_File_Name (Get_Body_Name (Uname),
- Subunit => False, May_Fail => False);
+ Get_File_Name
+ (Uname => Get_Body_Name (Uname),
+ Subunit => False,
+ May_Fail => False);
Body_Index := Get_Unit_Index (Get_Body_Name (Uname));
end if;
diff --git a/gcc/ada/lib-xref-spark_specific.adb b/gcc/ada/lib-xref-spark_specific.adb
index 0ce834a..ce4538b 100644
--- a/gcc/ada/lib-xref-spark_specific.adb
+++ b/gcc/ada/lib-xref-spark_specific.adb
@@ -228,7 +228,18 @@ package body SPARK_Specific is
end loop;
if Nkind (Context) = N_Pragma then
- Context := Parent (Context);
+
+ -- When used for cross-references then aspects might not be
+ -- yet linked to pragmas; when used for AST navigation in
+ -- GNATprove this routine is expected to follow those links.
+
+ if From_Aspect_Specification (Context) then
+ Context := Corresponding_Aspect (Context);
+ pragma Assert (Nkind (Context) = N_Aspect_Specification);
+ Context := Entity (Context);
+ else
+ Context := Parent (Context);
+ end if;
end if;
when N_Entry_Body
diff --git a/gcc/ada/lib-xref.ads b/gcc/ada/lib-xref.ads
index 5c7a086..903e64e 100644
--- a/gcc/ada/lib-xref.ads
+++ b/gcc/ada/lib-xref.ads
@@ -632,6 +632,11 @@ package Lib.Xref is
-- Return the closest enclosing subprogram or library-level package.
-- This ensures that GNATprove can distinguish local variables from
-- global variables.
+ --
+ -- ??? This routine should only be used for processing related to
+ -- cross-references, where it might return wrong result but must avoid
+ -- crashes on ill-formed source code. It is wrong to use it where exact
+ -- result is needed.
procedure Generate_Dereference
(N : Node_Id;
diff --git a/gcc/ada/libgnarl/a-intnam__dragonfly.ads b/gcc/ada/libgnarl/a-intnam__dragonfly.ads
index 1de9735..8fb16f3 100644
--- a/gcc/ada/libgnarl/a-intnam__dragonfly.ads
+++ b/gcc/ada/libgnarl/a-intnam__dragonfly.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1991-2015, Free Software Foundation, Inc. --
+-- Copyright (C) 1991-2018, 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- --
diff --git a/gcc/ada/libgnarl/s-osinte__dragonfly.adb b/gcc/ada/libgnarl/s-osinte__dragonfly.adb
index dc9e19c..3cf18d1 100644
--- a/gcc/ada/libgnarl/s-osinte__dragonfly.adb
+++ b/gcc/ada/libgnarl/s-osinte__dragonfly.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1991-2015, Free Software Foundation, Inc. --
+-- Copyright (C) 1991-2018, 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- --
diff --git a/gcc/ada/libgnarl/s-osinte__dragonfly.ads b/gcc/ada/libgnarl/s-osinte__dragonfly.ads
index a67702c..5a4255f 100644
--- a/gcc/ada/libgnarl/s-osinte__dragonfly.ads
+++ b/gcc/ada/libgnarl/s-osinte__dragonfly.ads
@@ -7,7 +7,7 @@
-- S p e c --
-- --
-- Copyright (C) 1991-1994, Florida State University --
--- Copyright (C) 1995-2015, Free Software Foundation, Inc. --
+-- Copyright (C) 1995-2018, 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- --
diff --git a/gcc/ada/libgnarl/s-osinte__gnu.adb b/gcc/ada/libgnarl/s-osinte__gnu.adb
index fb099ac..3147748 100644
--- a/gcc/ada/libgnarl/s-osinte__gnu.adb
+++ b/gcc/ada/libgnarl/s-osinte__gnu.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2015-2016, Free Software Foundation, Inc. --
+-- Copyright (C) 2015-2018, 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- --
diff --git a/gcc/ada/libgnarl/s-osinte__gnu.ads b/gcc/ada/libgnarl/s-osinte__gnu.ads
index 183c5b8..0482a4e 100644
--- a/gcc/ada/libgnarl/s-osinte__gnu.ads
+++ b/gcc/ada/libgnarl/s-osinte__gnu.ads
@@ -7,7 +7,7 @@
-- S p e c --
-- --
-- Copyright (C) 1991-1994, Florida State University --
--- Copyright (C) 1995-2016, Free Software Foundation, Inc. --
+-- Copyright (C) 1995-2018, 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- --
diff --git a/gcc/ada/libgnarl/s-osinte__hpux-dce.adb b/gcc/ada/libgnarl/s-osinte__hpux-dce.adb
index a9d46a0..84d5101 100644
--- a/gcc/ada/libgnarl/s-osinte__hpux-dce.adb
+++ b/gcc/ada/libgnarl/s-osinte__hpux-dce.adb
@@ -7,7 +7,7 @@
-- B o d y --
-- --
-- Copyright (C) 1991-1994, Florida State University --
--- Copyright (C) 1995-2010, AdaCore --
+-- Copyright (C) 1995-2018, 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- --
diff --git a/gcc/ada/libgnarl/s-osinte__hpux-dce.ads b/gcc/ada/libgnarl/s-osinte__hpux-dce.ads
index 28fb5ba..36c4b9c 100644
--- a/gcc/ada/libgnarl/s-osinte__hpux-dce.ads
+++ b/gcc/ada/libgnarl/s-osinte__hpux-dce.ads
@@ -7,7 +7,7 @@
-- S p e c --
-- --
-- Copyright (C) 1991-1994, Florida State University --
--- Copyright (C) 1995-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1995-2018, 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- --
diff --git a/gcc/ada/libgnarl/s-taprop__hpux-dce.adb b/gcc/ada/libgnarl/s-taprop__hpux-dce.adb
index 1c5dcc1..6a1bb86 100644
--- a/gcc/ada/libgnarl/s-taprop__hpux-dce.adb
+++ b/gcc/ada/libgnarl/s-taprop__hpux-dce.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2018, 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- --
diff --git a/gcc/ada/libgnarl/s-taspri__hpux-dce.ads b/gcc/ada/libgnarl/s-taspri__hpux-dce.ads
index 137f34b..9c75f29 100644
--- a/gcc/ada/libgnarl/s-taspri__hpux-dce.ads
+++ b/gcc/ada/libgnarl/s-taspri__hpux-dce.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1991-2014, Free Software Foundation, Inc. --
+-- Copyright (C) 1991-2018, 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- --
diff --git a/gcc/ada/libgnat/g-dynhta.adb b/gcc/ada/libgnat/g-dynhta.adb
index a6e2734..b093e79 100644
--- a/gcc/ada/libgnat/g-dynhta.adb
+++ b/gcc/ada/libgnat/g-dynhta.adb
@@ -38,11 +38,10 @@ package body GNAT.Dynamic_HTables is
-------------------
package body Static_HTable is
-
function Get_Non_Null (T : Instance) return Elmt_Ptr;
-- Returns Null_Ptr if Iterator_Started is False or if the Table is
- -- empty. Returns Iterator_Ptr if non null, or the next non null
- -- element in table if any.
+ -- empty. Returns Iterator_Ptr if non null, or the next non null element
+ -- in table if any.
---------
-- Get --
@@ -363,7 +362,834 @@ package body GNAT.Dynamic_HTables is
begin
E.Next := Next;
end Set_Next;
-
end Simple_HTable;
+ --------------------
+ -- Dynamic_HTable --
+ --------------------
+
+ package body Dynamic_HTable is
+ Minimum_Size : constant Bucket_Range_Type := 32;
+ -- Minimum size of the buckets
+
+ Safe_Compression_Size : constant Bucket_Range_Type :=
+ Minimum_Size * Compression_Factor;
+ -- Maximum safe size for hash table compression. Beyond this size, a
+ -- compression will violate the minimum size constraint on the buckets.
+
+ Safe_Expansion_Size : constant Bucket_Range_Type :=
+ Bucket_Range_Type'Last / Expansion_Factor;
+ -- Maximum safe size for hash table expansion. Beyond this size, an
+ -- expansion will overflow the buckets.
+
+ procedure Destroy_Buckets (Bkts : Bucket_Table_Ptr);
+ pragma Inline (Destroy_Buckets);
+ -- Destroy all nodes within buckets Bkts
+
+ procedure Detach (Nod : Node_Ptr);
+ pragma Inline (Detach);
+ -- Detach node Nod from the bucket it resides in
+
+ procedure Ensure_Circular (Head : Node_Ptr);
+ pragma Inline (Ensure_Circular);
+ -- Ensure that dummy head Head is circular with respect to itself
+
+ procedure Ensure_Created (T : Instance);
+ pragma Inline (Ensure_Created);
+ -- Verify that hash table T is created. Raise Not_Created if this is not
+ -- the case.
+
+ procedure Ensure_Unlocked (T : Instance);
+ pragma Inline (Ensure_Unlocked);
+ -- Verify that hash table T is unlocked. Raise Table_Locked if this is
+ -- not the case.
+
+ function Find_Bucket
+ (Bkts : Bucket_Table_Ptr;
+ Key : Key_Type) return Node_Ptr;
+ pragma Inline (Find_Bucket);
+ -- Find the bucket among buckets Bkts which corresponds to key Key, and
+ -- return its dummy head.
+
+ function Find_Node (Head : Node_Ptr; Key : Key_Type) return Node_Ptr;
+ pragma Inline (Find_Node);
+ -- Traverse a bucket indicated by dummy head Head to determine whether
+ -- there exists a node with key Key. If such a node exists, return it,
+ -- otherwise return null.
+
+ procedure First_Valid_Node
+ (T : Instance;
+ Low_Bkt : Bucket_Range_Type;
+ High_Bkt : Bucket_Range_Type;
+ Idx : out Bucket_Range_Type;
+ Nod : out Node_Ptr);
+ pragma Inline (First_Valid_Node);
+ -- Find the first valid node in the buckets of hash table T constrained
+ -- by the range Low_Bkt .. High_Bkt. If such a node exists, return its
+ -- bucket index in Idx and reference in Nod. If no such node exists,
+ -- Idx is set to 0 and Nod to null.
+
+ procedure Free is
+ new Ada.Unchecked_Deallocation (Bucket_Table, Bucket_Table_Ptr);
+
+ procedure Free is
+ new Ada.Unchecked_Deallocation (Hash_Table, Instance);
+
+ procedure Free is
+ new Ada.Unchecked_Deallocation (Node, Node_Ptr);
+
+ function Is_Valid (Iter : Iterator) return Boolean;
+ pragma Inline (Is_Valid);
+ -- Determine whether iterator Iter refers to a valid key-value pair
+
+ function Is_Valid (Nod : Node_Ptr; Head : Node_Ptr) return Boolean;
+ pragma Inline (Is_Valid);
+ -- Determine whether node Nod is non-null and does not refer to dummy
+ -- head Head, thus making it valid.
+
+ function Load_Factor (T : Instance) return Threshold_Type;
+ pragma Inline (Load_Factor);
+ -- Calculate the load factor of hash table T
+
+ procedure Lock (T : Instance);
+ pragma Inline (Lock);
+ -- Lock all mutation functionality of hash table T
+
+ procedure Mutate_And_Rehash (T : Instance; Size : Bucket_Range_Type);
+ pragma Inline (Mutate_And_Rehash);
+ -- Replace the buckets of hash table T with a new set of buckets of size
+ -- Size. Rehash all key-value pairs from the old to the new buckets.
+
+ procedure Prepend (Nod : Node_Ptr; Head : Node_Ptr);
+ pragma Inline (Prepend);
+ -- Insert node Nod immediately after dummy head Head
+
+ procedure Unlock (T : Instance);
+ pragma Inline (Unlock);
+ -- Unlock all mutation functionality of hash table T
+
+ ------------
+ -- Create --
+ ------------
+
+ function Create (Initial_Size : Bucket_Range_Type) return Instance is
+ Size : constant Bucket_Range_Type :=
+ Bucket_Range_Type'Max (Initial_Size, Minimum_Size);
+ -- Ensure that the buckets meet a minimum size
+
+ T : constant Instance := new Hash_Table;
+
+ begin
+ T.Buckets := new Bucket_Table (0 .. Size - 1);
+ T.Initial_Size := Size;
+
+ return T;
+ end Create;
+
+ ------------
+ -- Delete --
+ ------------
+
+ procedure Delete (T : Instance; Key : Key_Type) is
+ procedure Compress;
+ pragma Inline (Compress);
+ -- Determine whether hash table T requires compression, and if so,
+ -- half its size.
+
+ --------------
+ -- Compress --
+ --------------
+
+ procedure Compress is
+ pragma Assert (T /= null);
+ pragma Assert (T.Buckets /= null);
+
+ Old_Size : constant Bucket_Range_Type := T.Buckets'Length;
+
+ begin
+ -- The ratio of pairs to buckets is under the desited threshold.
+ -- Compress the hash table only when there is still room to do so.
+
+ if Load_Factor (T) < Compression_Threshold
+ and then Old_Size >= Safe_Compression_Size
+ then
+ Mutate_And_Rehash (T, Old_Size / Compression_Factor);
+ end if;
+ end Compress;
+
+ -- Local variables
+
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ -- Start of processing for Delete
+
+ begin
+ Ensure_Created (T);
+ Ensure_Unlocked (T);
+
+ -- Obtain the dummy head of the bucket which should house the
+ -- key-value pair.
+
+ Head := Find_Bucket (T.Buckets, Key);
+
+ -- Try to find a node in the bucket which matches the key
+
+ Nod := Find_Node (Head, Key);
+
+ -- If such a node exists, remove it from the bucket and deallocate it
+
+ if Is_Valid (Nod, Head) then
+ Detach (Nod);
+ Free (Nod);
+
+ T.Pairs := T.Pairs - 1;
+
+ -- Compress the hash table if the load factor drops below
+ -- Compression_Threshold.
+
+ Compress;
+ end if;
+ end Delete;
+
+ -------------
+ -- Destroy --
+ -------------
+
+ procedure Destroy (T : in out Instance) is
+ begin
+ Ensure_Created (T);
+ Ensure_Unlocked (T);
+
+ -- Destroy all nodes in all buckets
+
+ Destroy_Buckets (T.Buckets);
+ Free (T.Buckets);
+ Free (T);
+ end Destroy;
+
+ ---------------------
+ -- Destroy_Buckets --
+ ---------------------
+
+ procedure Destroy_Buckets (Bkts : Bucket_Table_Ptr) is
+ procedure Destroy_Bucket (Head : Node_Ptr);
+ pragma Inline (Destroy_Bucket);
+ -- Destroy all nodes in a bucket with dummy head Head
+
+ --------------------
+ -- Destroy_Bucket --
+ --------------------
+
+ procedure Destroy_Bucket (Head : Node_Ptr) is
+ Nod : Node_Ptr;
+
+ begin
+ -- Destroy all valid nodes which follow the dummy head
+
+ while Is_Valid (Head.Next, Head) loop
+ Nod := Head.Next;
+
+ Detach (Nod);
+ Free (Nod);
+ end loop;
+ end Destroy_Bucket;
+
+ -- Start of processing for Destroy_Buckets
+
+ begin
+ pragma Assert (Bkts /= null);
+
+ for Scan_Idx in Bkts'Range loop
+ Destroy_Bucket (Bkts (Scan_Idx)'Access);
+ end loop;
+ end Destroy_Buckets;
+
+ ------------
+ -- Detach --
+ ------------
+
+ procedure Detach (Nod : Node_Ptr) is
+ pragma Assert (Nod /= null);
+
+ Next : constant Node_Ptr := Nod.Next;
+ Prev : constant Node_Ptr := Nod.Prev;
+
+ begin
+ pragma Assert (Next /= null);
+ pragma Assert (Prev /= null);
+
+ Prev.Next := Next;
+ Next.Prev := Prev;
+
+ Nod.Next := null;
+ Nod.Prev := null;
+ end Detach;
+
+ ---------------------
+ -- Ensure_Circular --
+ ---------------------
+
+ procedure Ensure_Circular (Head : Node_Ptr) is
+ pragma Assert (Head /= null);
+
+ begin
+ if Head.Next = null and then Head.Prev = null then
+ Head.Next := Head;
+ Head.Prev := Head;
+ end if;
+ end Ensure_Circular;
+
+ --------------------
+ -- Ensure_Created --
+ --------------------
+
+ procedure Ensure_Created (T : Instance) is
+ begin
+ if T = null then
+ raise Not_Created;
+ end if;
+ end Ensure_Created;
+
+ ---------------------
+ -- Ensure_Unlocked --
+ ---------------------
+
+ procedure Ensure_Unlocked (T : Instance) is
+ begin
+ pragma Assert (T /= null);
+
+ -- The hash table has at least one outstanding iterator
+
+ if T.Locked > 0 then
+ raise Table_Locked;
+ end if;
+ end Ensure_Unlocked;
+
+ -----------------
+ -- Find_Bucket --
+ -----------------
+
+ function Find_Bucket
+ (Bkts : Bucket_Table_Ptr;
+ Key : Key_Type) return Node_Ptr
+ is
+ pragma Assert (Bkts /= null);
+
+ Idx : constant Bucket_Range_Type := Hash (Key) mod Bkts'Length;
+
+ begin
+ return Bkts (Idx)'Access;
+ end Find_Bucket;
+
+ ---------------
+ -- Find_Node --
+ ---------------
+
+ function Find_Node (Head : Node_Ptr; Key : Key_Type) return Node_Ptr is
+ pragma Assert (Head /= null);
+
+ Nod : Node_Ptr;
+
+ begin
+ -- Traverse the nodes of the bucket, looking for a key-value pair
+ -- with the same key.
+
+ Nod := Head.Next;
+ while Is_Valid (Nod, Head) loop
+ if Equivalent_Keys (Nod.Key, Key) then
+ return Nod;
+ end if;
+
+ Nod := Nod.Next;
+ end loop;
+
+ return null;
+ end Find_Node;
+
+ ----------------------
+ -- First_Valid_Node --
+ ----------------------
+
+ procedure First_Valid_Node
+ (T : Instance;
+ Low_Bkt : Bucket_Range_Type;
+ High_Bkt : Bucket_Range_Type;
+ Idx : out Bucket_Range_Type;
+ Nod : out Node_Ptr)
+ is
+ Head : Node_Ptr;
+
+ begin
+ pragma Assert (T /= null);
+ pragma Assert (T.Buckets /= null);
+
+ -- Assume that no valid node exists
+
+ Idx := 0;
+ Nod := null;
+
+ -- Examine the buckets of the hash table within the requested range,
+ -- looking for the first valid node.
+
+ for Scan_Idx in Low_Bkt .. High_Bkt loop
+ Head := T.Buckets (Scan_Idx)'Access;
+
+ -- The bucket contains at least one valid node, return the first
+ -- such node.
+
+ if Is_Valid (Head.Next, Head) then
+ Idx := Scan_Idx;
+ Nod := Head.Next;
+ return;
+ end if;
+ end loop;
+ end First_Valid_Node;
+
+ ---------
+ -- Get --
+ ---------
+
+ function Get (T : Instance; Key : Key_Type) return Value_Type is
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ begin
+ Ensure_Created (T);
+
+ -- Obtain the dummy head of the bucket which should house the
+ -- key-value pair.
+
+ Head := Find_Bucket (T.Buckets, Key);
+
+ -- Try to find a node in the bucket which matches the key
+
+ Nod := Find_Node (Head, Key);
+
+ -- If such a node exists, return the value of the key-value pair
+
+ if Is_Valid (Nod, Head) then
+ return Nod.Value;
+ end if;
+
+ return No_Value;
+ end Get;
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : Iterator) return Boolean is
+ Is_OK : constant Boolean := Is_Valid (Iter);
+ T : constant Instance := Iter.Table;
+
+ begin
+ pragma Assert (T /= null);
+
+ -- The iterator is no longer valid which indicates that it has been
+ -- exhausted. Unlock all mutation functionality of the hash table
+ -- because the iterator cannot be advanced any further.
+
+ if not Is_OK then
+ Unlock (T);
+ end if;
+
+ return Is_OK;
+ end Has_Next;
+
+ --------------
+ -- Is_Valid --
+ --------------
+
+ function Is_Valid (Iter : Iterator) return Boolean is
+ begin
+ -- The invariant of Iterate and Next ensures that the iterator always
+ -- refers to a valid node if there exists one.
+
+ return Iter.Nod /= null;
+ end Is_Valid;
+
+ --------------
+ -- Is_Valid --
+ --------------
+
+ function Is_Valid (Nod : Node_Ptr; Head : Node_Ptr) return Boolean is
+ begin
+ -- A node is valid if it is non-null, and does not refer to the dummy
+ -- head of some bucket.
+
+ return Nod /= null and then Nod /= Head;
+ end Is_Valid;
+
+ -------------
+ -- Iterate --
+ -------------
+
+ function Iterate (T : Instance) return Iterator is
+ Iter : Iterator;
+
+ begin
+ Ensure_Created (T);
+ pragma Assert (T.Buckets /= null);
+
+ -- Initialize the iterator to reference the first valid node in
+ -- the full range of hash table buckets. If no such node exists,
+ -- the iterator is left in a state which does not allow it to
+ -- advance.
+
+ First_Valid_Node
+ (T => T,
+ Low_Bkt => T.Buckets'First,
+ High_Bkt => T.Buckets'Last,
+ Idx => Iter.Idx,
+ Nod => Iter.Nod);
+
+ -- Associate the iterator with the hash table to allow for future
+ -- mutation functionality unlocking.
+
+ Iter.Table := T;
+
+ -- Lock all mutation functionality of the hash table while it is
+ -- being iterated on.
+
+ Lock (T);
+
+ return Iter;
+ end Iterate;
+
+ -----------------
+ -- Load_Factor --
+ -----------------
+
+ function Load_Factor (T : Instance) return Threshold_Type is
+ pragma Assert (T /= null);
+ pragma Assert (T.Buckets /= null);
+
+ begin
+ -- The load factor is the ratio of key-value pairs to buckets
+
+ return Threshold_Type (T.Pairs) / Threshold_Type (T.Buckets'Length);
+ end Load_Factor;
+
+ ----------
+ -- Lock --
+ ----------
+
+ procedure Lock (T : Instance) is
+ begin
+ -- The hash table may be locked multiple times if multiple iterators
+ -- are operating over it.
+
+ T.Locked := T.Locked + 1;
+ end Lock;
+
+ -----------------------
+ -- Mutate_And_Rehash --
+ -----------------------
+
+ procedure Mutate_And_Rehash (T : Instance; Size : Bucket_Range_Type) is
+ procedure Rehash (From : Bucket_Table_Ptr; To : Bucket_Table_Ptr);
+ pragma Inline (Rehash);
+ -- Remove all nodes from buckets From and rehash them into buckets To
+
+ procedure Rehash_Bucket (Head : Node_Ptr; To : Bucket_Table_Ptr);
+ pragma Inline (Rehash_Bucket);
+ -- Detach all nodes starting from dummy head Head and rehash them
+ -- into To.
+
+ procedure Rehash_Node (Nod : Node_Ptr; To : Bucket_Table_Ptr);
+ pragma Inline (Rehash_Node);
+ -- Rehash node Nod into To
+
+ ------------
+ -- Rehash --
+ ------------
+
+ procedure Rehash (From : Bucket_Table_Ptr; To : Bucket_Table_Ptr) is
+ begin
+ pragma Assert (From /= null);
+ pragma Assert (To /= null);
+
+ for Scan_Idx in From'Range loop
+ Rehash_Bucket (From (Scan_Idx)'Access, To);
+ end loop;
+ end Rehash;
+
+ -------------------
+ -- Rehash_Bucket --
+ -------------------
+
+ procedure Rehash_Bucket (Head : Node_Ptr; To : Bucket_Table_Ptr) is
+ pragma Assert (Head /= null);
+
+ Nod : Node_Ptr;
+
+ begin
+ -- Detach all nodes which follow the dummy head
+
+ while Is_Valid (Head.Next, Head) loop
+ Nod := Head.Next;
+
+ Detach (Nod);
+ Rehash_Node (Nod, To);
+ end loop;
+ end Rehash_Bucket;
+
+ -----------------
+ -- Rehash_Node --
+ -----------------
+
+ procedure Rehash_Node (Nod : Node_Ptr; To : Bucket_Table_Ptr) is
+ pragma Assert (Nod /= null);
+
+ Head : Node_Ptr;
+
+ begin
+ -- Obtain the dummy head of the bucket which should house the
+ -- key-value pair.
+
+ Head := Find_Bucket (To, Nod.Key);
+
+ -- Ensure that the dummy head of an empty bucket is circular with
+ -- respect to itself.
+
+ Ensure_Circular (Head);
+
+ -- Prepend the node to the bucket
+
+ Prepend (Nod, Head);
+ end Rehash_Node;
+
+ -- Local declarations
+
+ Old_Bkts : Bucket_Table_Ptr;
+
+ -- Start of processing for Mutate_And_Rehash
+
+ begin
+ pragma Assert (T /= null);
+
+ Old_Bkts := T.Buckets;
+ T.Buckets := new Bucket_Table (0 .. Size - 1);
+
+ -- Transfer and rehash all key-value pairs from the old buckets to
+ -- the new buckets.
+
+ Rehash (From => Old_Bkts, To => T.Buckets);
+ Free (Old_Bkts);
+ end Mutate_And_Rehash;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next (Iter : in out Iterator; Key : out Key_Type) is
+ Is_OK : constant Boolean := Is_Valid (Iter);
+ Saved : constant Node_Ptr := Iter.Nod;
+ T : constant Instance := Iter.Table;
+ Head : Node_Ptr;
+
+ begin
+ pragma Assert (T /= null);
+ pragma Assert (T.Buckets /= null);
+
+ -- The iterator is no longer valid which indicates that it has been
+ -- exhausted. Unlock all mutation functionality of the hash table as
+ -- the iterator cannot be advanced any further.
+
+ if not Is_OK then
+ Unlock (T);
+ raise Iterator_Exhausted;
+ end if;
+
+ -- Advance to the next node along the same bucket
+
+ Iter.Nod := Iter.Nod.Next;
+ Head := T.Buckets (Iter.Idx)'Access;
+
+ -- If the new node is no longer valid, then this indicates that the
+ -- current bucket has been exhausted. Advance to the next valid node
+ -- within the remaining range of buckets. If no such node exists, the
+ -- iterator is left in a state which does not allow it to advance.
+
+ if not Is_Valid (Iter.Nod, Head) then
+ First_Valid_Node
+ (T => T,
+ Low_Bkt => Iter.Idx + 1,
+ High_Bkt => T.Buckets'Last,
+ Idx => Iter.Idx,
+ Nod => Iter.Nod);
+ end if;
+
+ Key := Saved.Key;
+ end Next;
+
+ -------------
+ -- Prepend --
+ -------------
+
+ procedure Prepend (Nod : Node_Ptr; Head : Node_Ptr) is
+ pragma Assert (Nod /= null);
+ pragma Assert (Head /= null);
+
+ Next : constant Node_Ptr := Head.Next;
+
+ begin
+ Head.Next := Nod;
+ Next.Prev := Nod;
+
+ Nod.Next := Next;
+ Nod.Prev := Head;
+ end Prepend;
+
+ ---------
+ -- Put --
+ ---------
+
+ procedure Put
+ (T : Instance;
+ Key : Key_Type;
+ Value : Value_Type)
+ is
+ procedure Expand;
+ pragma Inline (Expand);
+ -- Determine whether hash table T requires expansion, and if so,
+ -- double its size.
+
+ procedure Prepend_Or_Replace (Head : Node_Ptr);
+ pragma Inline (Prepend_Or_Replace);
+ -- Update the value of a node within a bucket with dummy head Head
+ -- whose key is Key to Value. If there is no such node, prepend a new
+ -- key-value pair to the bucket.
+
+ ------------
+ -- Expand --
+ ------------
+
+ procedure Expand is
+ pragma Assert (T /= null);
+ pragma Assert (T.Buckets /= null);
+
+ Old_Size : constant Bucket_Range_Type := T.Buckets'Length;
+
+ begin
+ -- The ratio of pairs to buckets is over the desited threshold.
+ -- Expand the hash table only when there is still room to do so.
+
+ if Load_Factor (T) > Expansion_Threshold
+ and then Old_Size <= Safe_Expansion_Size
+ then
+ Mutate_And_Rehash (T, Old_Size * Expansion_Factor);
+ end if;
+ end Expand;
+
+ ------------------------
+ -- Prepend_Or_Replace --
+ ------------------------
+
+ procedure Prepend_Or_Replace (Head : Node_Ptr) is
+ pragma Assert (Head /= null);
+
+ Nod : Node_Ptr;
+
+ begin
+ -- If the bucket containst at least one valid node, then there is
+ -- a chance that a node with the same key as Key exists. If this
+ -- is the case, the value of that node must be updated.
+
+ Nod := Head.Next;
+ while Is_Valid (Nod, Head) loop
+ if Equivalent_Keys (Nod.Key, Key) then
+ Nod.Value := Value;
+ return;
+ end if;
+
+ Nod := Nod.Next;
+ end loop;
+
+ -- At this point the bucket is either empty, or none of the nodes
+ -- match key Key. Prepend a new key-value pair.
+
+ Nod := new Node'(Key, Value, null, null);
+
+ Prepend (Nod, Head);
+ end Prepend_Or_Replace;
+
+ -- Local variables
+
+ Head : Node_Ptr;
+
+ -- Start of processing for Put
+
+ begin
+ Ensure_Created (T);
+ Ensure_Unlocked (T);
+
+ -- Obtain the dummy head of the bucket which should house the
+ -- key-value pair.
+
+ Head := Find_Bucket (T.Buckets, Key);
+
+ -- Ensure that the dummy head of an empty bucket is circular with
+ -- respect to itself.
+
+ Ensure_Circular (Head);
+
+ -- In case the bucket already contains a node with the same key,
+ -- replace its value, otherwise prepend a new key-value pair.
+
+ Prepend_Or_Replace (Head);
+
+ T.Pairs := T.Pairs + 1;
+
+ -- Expand the hash table if the ratio of pairs to buckets goes over
+ -- Expansion_Threshold.
+
+ Expand;
+ end Put;
+
+ -----------
+ -- Reset --
+ -----------
+
+ procedure Reset (T : Instance) is
+ begin
+ Ensure_Created (T);
+ Ensure_Unlocked (T);
+
+ -- Destroy all nodes in all buckets
+
+ Destroy_Buckets (T.Buckets);
+ Free (T.Buckets);
+
+ -- Recreate the buckets using the original size from creation time
+
+ T.Buckets := new Bucket_Table (0 .. T.Initial_Size - 1);
+ T.Pairs := 0;
+ end Reset;
+
+ ----------
+ -- Size --
+ ----------
+
+ function Size (T : Instance) return Pair_Count_Type is
+ begin
+ Ensure_Created (T);
+
+ return T.Pairs;
+ end Size;
+
+ ------------
+ -- Unlock --
+ ------------
+
+ procedure Unlock (T : Instance) is
+ begin
+ -- The hash table may be locked multiple times if multiple iterators
+ -- are operating over it.
+
+ T.Locked := T.Locked - 1;
+ end Unlock;
+ end Dynamic_HTable;
+
end GNAT.Dynamic_HTables;
diff --git a/gcc/ada/libgnat/g-dynhta.ads b/gcc/ada/libgnat/g-dynhta.ads
index ea331c0..41574fd 100644
--- a/gcc/ada/libgnat/g-dynhta.ads
+++ b/gcc/ada/libgnat/g-dynhta.ads
@@ -31,13 +31,11 @@
-- Hash table searching routines
--- This package contains three separate packages. The Simple_HTable package
+-- This package contains two separate packages. The Simple_HTable package
-- provides a very simple abstraction that associates one element to one key
-- value and takes care of all allocations automatically using the heap. The
-- Static_HTable package provides a more complex interface that allows full
--- control over allocation. The Load_Factor_HTable package provides a more
--- complex abstraction where collisions are resolved by chaining, and the
--- table grows by a percentage after the load factor has been exceeded.
+-- control over allocation.
-- This package provides a facility similar to that of GNAT.HTable, except
-- that this package declares types that can be used to define dynamic
@@ -48,6 +46,8 @@
-- GNAT.HTable to keep as much coherency as possible between these two
-- related units.
+pragma Compiler_Unit_Warning;
+
package GNAT.Dynamic_HTables is
-------------------
@@ -85,40 +85,38 @@ package GNAT.Dynamic_HTables is
Null_Ptr : Elmt_Ptr;
-- The null value of the Elmt_Ptr type
+ with function Next (E : Elmt_Ptr) return Elmt_Ptr;
with procedure Set_Next (E : Elmt_Ptr; Next : Elmt_Ptr);
- with function Next (E : Elmt_Ptr) return Elmt_Ptr;
-- The type must provide an internal link for the sake of the
-- staticness of the HTable.
type Key is limited private;
with function Get_Key (E : Elmt_Ptr) return Key;
- with function Hash (F : Key) return Header_Num;
- with function Equal (F1, F2 : Key) return Boolean;
+ with function Hash (F : Key) return Header_Num;
+ with function Equal (F1 : Key; F2 : Key) return Boolean;
package Static_HTable is
-
type Instance is private;
Nil : constant Instance;
procedure Reset (T : in out Instance);
- -- Resets the hash table by releasing all memory associated with
- -- it. The hash table can safely be reused after this call. For the
- -- most common case where Elmt_Ptr is an access type, and Null_Ptr is
- -- null, this is only needed if the same table is reused in a new
- -- context. If Elmt_Ptr is other than an access type, or Null_Ptr is
- -- other than null, then Reset must be called before the first use of
- -- the hash table.
+ -- Resets the hash table by releasing all memory associated with it. The
+ -- hash table can safely be reused after this call. For the most common
+ -- case where Elmt_Ptr is an access type, and Null_Ptr is null, this is
+ -- only needed if the same table is reused in a new context. If Elmt_Ptr
+ -- is other than an access type, or Null_Ptr is other than null, then
+ -- Reset must be called before the first use of the hash table.
procedure Set (T : in out Instance; E : Elmt_Ptr);
-- Insert the element pointer in the HTable
function Get (T : Instance; K : Key) return Elmt_Ptr;
- -- Returns the latest inserted element pointer with the given Key
- -- or null if none.
+ -- Returns the latest inserted element pointer with the given Key or
+ -- null if none.
procedure Remove (T : Instance; K : Key);
- -- Removes the latest inserted element pointer associated with the
- -- given key if any, does nothing if none.
+ -- Removes the latest inserted element pointer associated with the given
+ -- key if any, does nothing if none.
function Get_First (T : Instance) return Elmt_Ptr;
-- Returns Null_Ptr if the Htable is empty, otherwise returns one
@@ -126,11 +124,11 @@ package GNAT.Dynamic_HTables is
-- function will return the same element.
function Get_Next (T : Instance) return Elmt_Ptr;
- -- Returns an unspecified element that has not been returned by the
- -- same function since the last call to Get_First or Null_Ptr if
- -- there is no such element or Get_First has never been called. If
- -- there is no call to 'Set' in between Get_Next calls, all the
- -- elements of the Htable will be traversed.
+ -- Returns an unspecified element that has not been returned by the same
+ -- function since the last call to Get_First or Null_Ptr if there is no
+ -- such element or Get_First has never been called. If there is no call
+ -- to 'Set' in between Get_Next calls, all the elements of the Htable
+ -- will be traversed.
private
type Table_Type is array (Header_Num) of Elmt_Ptr;
@@ -169,11 +167,10 @@ package GNAT.Dynamic_HTables is
-- a given key
type Key is private;
- with function Hash (F : Key) return Header_Num;
- with function Equal (F1, F2 : Key) return Boolean;
+ with function Hash (F : Key) return Header_Num;
+ with function Equal (F1 : Key; F2 : Key) return Boolean;
package Simple_HTable is
-
type Instance is private;
Nil : constant Instance;
@@ -233,7 +230,6 @@ package GNAT.Dynamic_HTables is
-- same restrictions apply as Get_Next.
private
-
type Element_Wrapper;
type Elmt_Ptr is access all Element_Wrapper;
type Element_Wrapper is record
@@ -260,7 +256,263 @@ package GNAT.Dynamic_HTables is
type Instance is new Tab.Instance;
Nil : constant Instance := Instance (Tab.Nil);
-
end Simple_HTable;
+ --------------------
+ -- Dynamic_HTable --
+ --------------------
+
+ -- The following package offers a hash table abstraction with the following
+ -- characteristics:
+ --
+ -- * Dynamic resizing based on load factor.
+ -- * Creation of multiple instances, of different sizes.
+ -- * Iterable keys.
+ --
+ -- This type of hash table is best used in scenarios where the size of the
+ -- key set is not known. The dynamic resizing aspect allows for performance
+ -- to remain within reasonable bounds as the size of the key set grows.
+ --
+ -- The following use pattern must be employed when operating this table:
+ --
+ -- Table : Instance := Create (<some size>);
+ --
+ -- <various operations>
+ --
+ -- Destroy (Table);
+ --
+ -- The destruction of the table reclaims all storage occupied by it.
+
+ -- The following type denotes the underlying range of the hash table
+ -- buckets.
+
+ type Bucket_Range_Type is mod 2 ** 32;
+
+ -- The following type denotes the multiplicative factor used in expansion
+ -- and compression of the hash table.
+
+ subtype Factor_Type is Bucket_Range_Type range 2 .. 100;
+
+ -- The following type denotes the number of key-value pairs stored in the
+ -- hash table.
+
+ type Pair_Count_Type is range 0 .. 2 ** 31 - 1;
+
+ -- The following type denotes the threshold range used in expansion and
+ -- compression of the hash table.
+
+ subtype Threshold_Type is Long_Float range 0.0 .. Long_Float'Last;
+
+ generic
+ type Key_Type is private;
+ type Value_Type is private;
+ -- The types of the key-value pairs stored in the hash table
+
+ No_Value : Value_Type;
+ -- An indicator for a non-existent value
+
+ Expansion_Threshold : Threshold_Type;
+ Expansion_Factor : Factor_Type;
+ -- Once the load factor goes over Expansion_Threshold, the size of the
+ -- buckets is increased using the formula
+ --
+ -- New_Size = Old_Size * Expansion_Factor
+ --
+ -- An Expansion_Threshold of 1.5 and Expansion_Factor of 2 indicate that
+ -- the size of the buckets will be doubled once the load factor exceeds
+ -- 1.5.
+
+ Compression_Threshold : Threshold_Type;
+ Compression_Factor : Factor_Type;
+ -- Once the load factor drops below Compression_Threshold, the size of
+ -- the buckets is decreased using the formula
+ --
+ -- New_Size = Old_Size / Compression_Factor
+ --
+ -- A Compression_Threshold of 0.5 and Compression_Factor of 2 indicate
+ -- that the size of the buckets will be halved once the load factor
+ -- drops below 0.5.
+
+ with function Equivalent_Keys
+ (Left : Key_Type;
+ Right : Key_Type) return Boolean;
+ -- Determine whether two keys are equivalent
+
+ with function Hash (Key : Key_Type) return Bucket_Range_Type;
+ -- Map an arbitrary key into the range of buckets
+
+ package Dynamic_HTable is
+
+ ----------------------
+ -- Table operations --
+ ----------------------
+
+ -- The following type denotes a hash table handle. Each instance must be
+ -- created using routine Create.
+
+ type Instance is private;
+ Nil : constant Instance;
+
+ Not_Created : exception;
+ -- This exception is raised when the hash table has not been created by
+ -- routine Create, and an attempt is made to read or mutate its state.
+
+ Table_Locked : exception;
+ -- This exception is raised when the hash table is being iterated on,
+ -- and an attempt is made to mutate its state.
+
+ function Create (Initial_Size : Bucket_Range_Type) return Instance;
+ -- Create a new table with bucket capacity Initial_Size. This routine
+ -- must be called at the start of a hash table's lifetime.
+
+ procedure Delete (T : Instance; Key : Key_Type);
+ -- Delete the value which corresponds to key Key from hash table T. The
+ -- routine has no effect if the value is not present in the hash table.
+ -- This action will raise Table_Locked if the hash table has outstanding
+ -- iterators. If the load factor drops below Compression_Threshold, the
+ -- size of the buckets is decreased by Copression_Factor.
+
+ procedure Destroy (T : in out Instance);
+ -- Destroy the contents of hash table T, rendering it unusable. This
+ -- routine must be called at the end of a hash table's lifetime. This
+ -- action will raise Table_Locked if the hash table has outstanding
+ -- iterators.
+
+ function Get (T : Instance; Key : Key_Type) return Value_Type;
+ -- Obtain the value which corresponds to key Key from hash table T. If
+ -- the value does not exist, return No_Value.
+
+ procedure Put
+ (T : Instance;
+ Key : Key_Type;
+ Value : Value_Type);
+ -- Associate value Value with key Key in hash table T. If the table
+ -- already contains a mapping of the same key to a previous value, the
+ -- previous value is overwritten. This action will raise Table_Locked
+ -- if the hash table has outstanding iterators. If the load factor goes
+ -- over Expansion_Threshold, the size of the buckets is increased by
+ -- Expansion_Factor.
+
+ procedure Reset (T : Instance);
+ -- Destroy the contents of hash table T, and reset it to its initial
+ -- created state. This action will raise Table_Locked if the hash table
+ -- has outstanding iterators.
+
+ function Size (T : Instance) return Pair_Count_Type;
+ -- Obtain the number of key-value pairs in hash table T
+
+ -------------------------
+ -- Iterator operations --
+ -------------------------
+
+ -- The following type represents a key iterator. An iterator locks
+ -- all mutation operations, and unlocks them once it is exhausted.
+ -- The iterator must be used with the following pattern:
+ --
+ -- Iter := Iterate (My_Table);
+ -- while Has_Next (Iter) loop
+ -- Key := Next (Iter);
+ -- . . .
+ -- end loop;
+ --
+ -- It is possible to advance the iterator by using Next only, however
+ -- this risks raising Iterator_Exhausted.
+
+ type Iterator is private;
+
+ Iterator_Exhausted : exception;
+ -- This exception is raised when an iterator is exhausted and further
+ -- attempts to advance it are made by calling routine Next.
+
+ function Iterate (T : Instance) return Iterator;
+ -- Obtain an iterator over the keys of hash table T. This action locks
+ -- all mutation functionality of the associated hash table.
+
+ function Has_Next (Iter : Iterator) return Boolean;
+ -- Determine whether iterator Iter has more keys to examine. If the
+ -- iterator has been exhausted, restore all mutation functionality of
+ -- the associated hash table.
+
+ procedure Next
+ (Iter : in out Iterator;
+ Key : out Key_Type);
+ -- Return the current key referenced by iterator Iter and advance to
+ -- the next available key. If the iterator has been exhausted and
+ -- further attempts are made to advance it, this routine restores
+ -- mutation functionality of the associated hash table, and then
+ -- raises Iterator_Exhausted.
+
+ private
+ -- The following type represents a doubly linked list node used to
+ -- store a key-value pair. There are several reasons to use a doubly
+ -- linked list:
+ --
+ -- * Most read and write operations utilize the same primitve
+ -- routines to locate, create, and delete a node, allowing for
+ -- greater degree of code sharing.
+ --
+ -- * Special cases are eliminated by maintaining a circular node
+ -- list with a dummy head (see type Bucket_Table).
+ --
+ -- A node is said to be "valid" if it is non-null, and does not refer to
+ -- the dummy head of some bucket.
+
+ type Node;
+ type Node_Ptr is access all Node;
+ type Node is record
+ Key : Key_Type;
+ Value : Value_Type := No_Value;
+ -- Key-value pair stored in a bucket
+
+ Prev : Node_Ptr := null;
+ Next : Node_Ptr := null;
+ end record;
+
+ -- The following type represents a bucket table. Each bucket contains a
+ -- circular doubly linked list of nodes with a dummy head. Initially,
+ -- the head does not refer to itself. This is intentional because it
+ -- improves the performance of creation, compression, and expansion by
+ -- avoiding a separate pass to link a head to itself. Several routines
+ -- ensure that the head is properly formed.
+
+ type Bucket_Table is array (Bucket_Range_Type range <>) of aliased Node;
+ type Bucket_Table_Ptr is access Bucket_Table;
+
+ -- The following type represents a hash table
+
+ type Hash_Table is record
+ Buckets : Bucket_Table_Ptr := null;
+ -- Reference to the compressing / expanding buckets
+
+ Initial_Size : Bucket_Range_Type := 0;
+ -- The initial size of the buckets as specified at creation time
+
+ Locked : Natural := 0;
+ -- Number of outstanding iterators
+
+ Pairs : Pair_Count_Type := 0;
+ -- Number of key-value pairs in the buckets
+ end record;
+
+ type Instance is access Hash_Table;
+ Nil : constant Instance := null;
+
+ -- The following type represents a key iterator
+
+ type Iterator is record
+ Idx : Bucket_Range_Type := 0;
+ -- Index of the current bucket being examined. This index is always
+ -- kept within the range of the buckets.
+
+ Nod : Node_Ptr := null;
+ -- Reference to the current node being examined within the current
+ -- bucket. The invariant of the iterator requires that this field
+ -- always point to a valid node. A value of null indicates that the
+ -- iterator is exhausted.
+
+ Table : Instance := null;
+ -- Reference to the associated hash table
+ end record;
+ end Dynamic_HTable;
+
end GNAT.Dynamic_HTables;
diff --git a/gcc/ada/libgnat/g-lists.adb b/gcc/ada/libgnat/g-lists.adb
new file mode 100644
index 0000000..a058f33
--- /dev/null
+++ b/gcc/ada/libgnat/g-lists.adb
@@ -0,0 +1,635 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- G N A T . L I S T S --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2018, 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. --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+with Ada.Unchecked_Deallocation;
+
+package body GNAT.Lists is
+
+ package body Doubly_Linked_List is
+ procedure Delete_Node (L : Instance; Nod : Node_Ptr);
+ pragma Inline (Delete_Node);
+ -- Detach and delete node Nod from list L
+
+ procedure Ensure_Circular (Head : Node_Ptr);
+ pragma Inline (Ensure_Circular);
+ -- Ensure that dummy head Head is circular with respect to itself
+
+ procedure Ensure_Created (L : Instance);
+ pragma Inline (Ensure_Created);
+ -- Verify that list L is created. Raise Not_Created if this is not the
+ -- case.
+
+ procedure Ensure_Full (L : Instance);
+ pragma Inline (Ensure_Full);
+ -- Verify that list L contains at least one element. Raise List_Empty if
+ -- this is not the case.
+
+ procedure Ensure_Unlocked (L : Instance);
+ pragma Inline (Ensure_Unlocked);
+ -- Verify that list L is unlocked. Raise List_Locked if this is not the
+ -- case.
+
+ function Find_Node
+ (Head : Node_Ptr;
+ Elem : Element_Type) return Node_Ptr;
+ pragma Inline (Find_Node);
+ -- Travers a list indicated by dummy head Head to determine whethe there
+ -- exists a node with element Elem. If such a node exists, return it,
+ -- otherwise return null;
+
+ procedure Free is new Ada.Unchecked_Deallocation (Linked_List, Instance);
+
+ procedure Free is new Ada.Unchecked_Deallocation (Node, Node_Ptr);
+
+ procedure Insert_Between
+ (L : Instance;
+ Elem : Element_Type;
+ Left : Node_Ptr;
+ Right : Node_Ptr);
+ pragma Inline (Insert_Between);
+ -- Insert element Elem between nodes Left and Right of list L
+
+ function Is_Valid (Iter : Iterator) return Boolean;
+ pragma Inline (Is_Valid);
+ -- Determine whether iterator Iter refers to a valid element
+
+ function Is_Valid (Nod : Node_Ptr; Head : Node_Ptr) return Boolean;
+ pragma Inline (Is_Valid);
+ -- Determine whether node Nod is non-null and does not refer to dummy
+ -- head Head, thus making it valid.
+
+ procedure Lock (L : Instance);
+ pragma Inline (Lock);
+ -- Lock all mutation functionality of list L
+
+ procedure Unlock (L : Instance);
+ pragma Inline (Unlock);
+ -- Unlock all mutation functionality of list L
+
+ ------------
+ -- Append --
+ ------------
+
+ procedure Append (L : Instance; Elem : Element_Type) is
+ Head : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+ Ensure_Unlocked (L);
+
+ -- Ensure that the dummy head of an empty list is circular with
+ -- respect to itself.
+
+ Head := L.Nodes'Access;
+ Ensure_Circular (Head);
+
+ -- Append the node by inserting it between the last node and the
+ -- dummy head.
+
+ Insert_Between
+ (L => L,
+ Elem => Elem,
+ Left => Head.Prev,
+ Right => Head);
+ end Append;
+
+ ------------
+ -- Create --
+ ------------
+
+ function Create return Instance is
+ begin
+ return new Linked_List;
+ end Create;
+
+ --------------
+ -- Contains --
+ --------------
+
+ function Contains (L : Instance; Elem : Element_Type) return Boolean is
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+
+ Head := L.Nodes'Access;
+ Nod := Find_Node (Head, Elem);
+
+ return Is_Valid (Nod, Head);
+ end Contains;
+
+ ------------
+ -- Delete --
+ ------------
+
+ procedure Delete (L : Instance; Elem : Element_Type) is
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+ Ensure_Full (L);
+ Ensure_Unlocked (L);
+
+ Head := L.Nodes'Access;
+ Nod := Find_Node (Head, Elem);
+
+ if Is_Valid (Nod, Head) then
+ Delete_Node (L, Nod);
+ end if;
+ end Delete;
+
+ ------------------
+ -- Delete_First --
+ ------------------
+
+ procedure Delete_First (L : Instance) is
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+ Ensure_Full (L);
+ Ensure_Unlocked (L);
+
+ Head := L.Nodes'Access;
+ Nod := Head.Next;
+
+ if Is_Valid (Nod, Head) then
+ Delete_Node (L, Nod);
+ end if;
+ end Delete_First;
+
+ -----------------
+ -- Delete_Last --
+ -----------------
+
+ procedure Delete_Last (L : Instance) is
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+ Ensure_Full (L);
+ Ensure_Unlocked (L);
+
+ Head := L.Nodes'Access;
+ Nod := Head.Prev;
+
+ if Is_Valid (Nod, Head) then
+ Delete_Node (L, Nod);
+ end if;
+ end Delete_Last;
+
+ -----------------
+ -- Delete_Node --
+ -----------------
+
+ procedure Delete_Node (L : Instance; Nod : Node_Ptr) is
+ Ref : Node_Ptr := Nod;
+
+ pragma Assert (Ref /= null);
+
+ Next : constant Node_Ptr := Ref.Next;
+ Prev : constant Node_Ptr := Ref.Prev;
+
+ begin
+ pragma Assert (L /= null);
+ pragma Assert (Next /= null);
+ pragma Assert (Prev /= null);
+
+ Prev.Next := Next; -- Prev ---> Next
+ Next.Prev := Prev; -- Prev <--> Next
+
+ Ref.Next := null;
+ Ref.Prev := null;
+
+ L.Elements := L.Elements - 1;
+
+ Free (Ref);
+ end Delete_Node;
+
+ -------------
+ -- Destroy --
+ -------------
+
+ procedure Destroy (L : in out Instance) is
+ Head : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+ Ensure_Unlocked (L);
+
+ Head := L.Nodes'Access;
+
+ while Is_Valid (Head.Next, Head) loop
+ Delete_Node (L, Head.Next);
+ end loop;
+
+ Free (L);
+ end Destroy;
+
+ ---------------------
+ -- Ensure_Circular --
+ ---------------------
+
+ procedure Ensure_Circular (Head : Node_Ptr) is
+ pragma Assert (Head /= null);
+
+ begin
+ if Head.Next = null and then Head.Prev = null then
+ Head.Next := Head;
+ Head.Prev := Head;
+ end if;
+ end Ensure_Circular;
+
+ --------------------
+ -- Ensure_Created --
+ --------------------
+
+ procedure Ensure_Created (L : Instance) is
+ begin
+ if L = null then
+ raise Not_Created;
+ end if;
+ end Ensure_Created;
+
+ -----------------
+ -- Ensure_Full --
+ -----------------
+
+ procedure Ensure_Full (L : Instance) is
+ begin
+ pragma Assert (L /= null);
+
+ if L.Elements = 0 then
+ raise List_Empty;
+ end if;
+ end Ensure_Full;
+
+ ---------------------
+ -- Ensure_Unlocked --
+ ---------------------
+
+ procedure Ensure_Unlocked (L : Instance) is
+ begin
+ pragma Assert (L /= null);
+
+ -- The list has at least one outstanding iterator
+
+ if L.Locked > 0 then
+ raise List_Locked;
+ end if;
+ end Ensure_Unlocked;
+
+ ---------------
+ -- Find_Node --
+ ---------------
+
+ function Find_Node
+ (Head : Node_Ptr;
+ Elem : Element_Type) return Node_Ptr
+ is
+ pragma Assert (Head /= null);
+
+ Nod : Node_Ptr;
+
+ begin
+ -- Traverse the nodes of the list, looking for a matching element
+
+ Nod := Head.Next;
+ while Is_Valid (Nod, Head) loop
+ if Nod.Elem = Elem then
+ return Nod;
+ end if;
+
+ Nod := Nod.Next;
+ end loop;
+
+ return null;
+ end Find_Node;
+
+ -----------
+ -- First --
+ -----------
+
+ function First (L : Instance) return Element_Type is
+ begin
+ Ensure_Created (L);
+ Ensure_Full (L);
+
+ return L.Nodes.Next.Elem;
+ end First;
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : Iterator) return Boolean is
+ Is_OK : constant Boolean := Is_Valid (Iter);
+
+ begin
+ -- The iterator is no longer valid which indicates that it has been
+ -- exhausted. Unlock all mutation functionality of the list because
+ -- the iterator cannot be advanced any further.
+
+ if not Is_OK then
+ Unlock (Iter.List);
+ end if;
+
+ return Is_OK;
+ end Has_Next;
+
+ ------------------
+ -- Insert_After --
+ ------------------
+
+ procedure Insert_After
+ (L : Instance;
+ After : Element_Type;
+ Elem : Element_Type)
+ is
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+ Ensure_Unlocked (L);
+
+ Head := L.Nodes'Access;
+ Nod := Find_Node (Head, After);
+
+ if Is_Valid (Nod, Head) then
+ Insert_Between
+ (L => L,
+ Elem => Elem,
+ Left => Nod,
+ Right => Nod.Next);
+ end if;
+ end Insert_After;
+
+ -------------------
+ -- Insert_Before --
+ -------------------
+
+ procedure Insert_Before
+ (L : Instance;
+ Before : Element_Type;
+ Elem : Element_Type)
+ is
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+ Ensure_Unlocked (L);
+
+ Head := L.Nodes'Access;
+ Nod := Find_Node (Head, Before);
+
+ if Is_Valid (Nod, Head) then
+ Insert_Between
+ (L => L,
+ Elem => Elem,
+ Left => Nod.Prev,
+ Right => Nod);
+ end if;
+ end Insert_Before;
+
+ --------------------
+ -- Insert_Between --
+ --------------------
+
+ procedure Insert_Between
+ (L : Instance;
+ Elem : Element_Type;
+ Left : Node_Ptr;
+ Right : Node_Ptr)
+ is
+ pragma Assert (L /= null);
+ pragma Assert (Left /= null);
+ pragma Assert (Right /= null);
+
+ Nod : constant Node_Ptr :=
+ new Node'(Elem => Elem,
+ Next => Right, -- Left Nod ---> Right
+ Prev => Left); -- Left <--- Nod ---> Right
+
+ begin
+ Left.Next := Nod; -- Left <--> Nod ---> Right
+ Right.Prev := Nod; -- Left <--> Nod <--> Right
+
+ L.Elements := L.Elements + 1;
+ end Insert_Between;
+
+ --------------
+ -- Is_Empty --
+ --------------
+
+ function Is_Empty (L : Instance) return Boolean is
+ begin
+ Ensure_Created (L);
+
+ return L.Elements = 0;
+ end Is_Empty;
+
+ --------------
+ -- Is_Valid --
+ --------------
+
+ function Is_Valid (Iter : Iterator) return Boolean is
+ begin
+ -- The invariant of Iterate and Next ensures that the iterator always
+ -- refers to a valid node if there exists one.
+
+ return Is_Valid (Iter.Nod, Iter.List.Nodes'Access);
+ end Is_Valid;
+
+ --------------
+ -- Is_Valid --
+ --------------
+
+ function Is_Valid (Nod : Node_Ptr; Head : Node_Ptr) return Boolean is
+ begin
+ -- A node is valid if it is non-null, and does not refer to the dummy
+ -- head of some list.
+
+ return Nod /= null and then Nod /= Head;
+ end Is_Valid;
+
+ -------------
+ -- Iterate --
+ -------------
+
+ function Iterate (L : Instance) return Iterator is
+ begin
+ Ensure_Created (L);
+
+ -- Lock all mutation functionality of the list while it is being
+ -- iterated on.
+
+ Lock (L);
+
+ return (List => L, Nod => L.Nodes.Next);
+ end Iterate;
+
+ ----------
+ -- Last --
+ ----------
+
+ function Last (L : Instance) return Element_Type is
+ begin
+ Ensure_Created (L);
+ Ensure_Full (L);
+
+ return L.Nodes.Prev.Elem;
+ end Last;
+
+ ------------
+ -- Length --
+ ------------
+
+ function Length (L : Instance) return Element_Count_Type is
+ begin
+ Ensure_Created (L);
+
+ return L.Elements;
+ end Length;
+
+ ----------
+ -- Lock --
+ ----------
+
+ procedure Lock (L : Instance) is
+ begin
+ pragma Assert (L /= null);
+
+ -- The list may be locked multiple times if multiple iterators are
+ -- operating over it.
+
+ L.Locked := L.Locked + 1;
+ end Lock;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next
+ (Iter : in out Iterator;
+ Elem : out Element_Type)
+ is
+ Is_OK : constant Boolean := Is_Valid (Iter);
+ Saved : constant Node_Ptr := Iter.Nod;
+
+ begin
+ -- The iterator is no linger valid which indicates that it has been
+ -- exhausted. Unlock all mutation functionality of the list as the
+ -- iterator cannot be advanced any further.
+
+ if not Is_OK then
+ Unlock (Iter.List);
+ raise Iterator_Exhausted;
+ end if;
+
+ -- Advance to the next node along the list
+
+ Iter.Nod := Iter.Nod.Next;
+ Elem := Saved.Elem;
+ end Next;
+
+ -------------
+ -- Prepend --
+ -------------
+
+ procedure Prepend (L : Instance; Elem : Element_Type) is
+ Head : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+ Ensure_Unlocked (L);
+
+ -- Ensure that the dummy head of an empty list is circular with
+ -- respect to itself.
+
+ Head := L.Nodes'Access;
+ Ensure_Circular (Head);
+
+ -- Append the node by inserting it between the dummy head and the
+ -- first node.
+
+ Insert_Between
+ (L => L,
+ Elem => Elem,
+ Left => Head,
+ Right => Head.Next);
+ end Prepend;
+
+ -------------
+ -- Replace --
+ -------------
+
+ procedure Replace
+ (L : Instance;
+ Old_Elem : Element_Type;
+ New_Elem : Element_Type)
+ is
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+ Ensure_Unlocked (L);
+
+ Head := L.Nodes'Access;
+ Nod := Find_Node (Head, Old_Elem);
+
+ if Is_Valid (Nod, Head) then
+ Nod.Elem := New_Elem;
+ end if;
+ end Replace;
+
+ ------------
+ -- Unlock --
+ ------------
+
+ procedure Unlock (L : Instance) is
+ begin
+ pragma Assert (L /= null);
+
+ -- The list may be locked multiple times if multiple iterators are
+ -- operating over it.
+
+ L.Locked := L.Locked - 1;
+ end Unlock;
+ end Doubly_Linked_List;
+
+end GNAT.Lists;
diff --git a/gcc/ada/libgnat/g-lists.ads b/gcc/ada/libgnat/g-lists.ads
new file mode 100644
index 0000000..777b4f6
--- /dev/null
+++ b/gcc/ada/libgnat/g-lists.ads
@@ -0,0 +1,245 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- G N A T . L I S T S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, 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. --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+pragma Compiler_Unit_Warning;
+
+package GNAT.Lists is
+
+ ------------------------
+ -- Doubly_Linked_List --
+ ------------------------
+
+ -- The following package offers a doubly linked list abstraction with the
+ -- following characteristics:
+ --
+ -- * Creation of multiple instances, of different sizes.
+ -- * Iterable elements.
+ --
+ -- The following use pattern must be employed with this list:
+ --
+ -- List : Instance := Create;
+ --
+ -- <various operations>
+ --
+ -- Destroy (List)
+ --
+ -- The destruction of the list reclaims all storage occupied by it.
+
+ -- The following type denotes the number of elements stored in a list
+
+ type Element_Count_Type is range 0 .. 2 ** 31 - 1;
+
+ generic
+ type Element_Type is private;
+
+ with function "="
+ (Left : Element_Type;
+ Right : Element_Type) return Boolean;
+
+ package Doubly_Linked_List is
+
+ ---------------------
+ -- List operations --
+ ---------------------
+
+ type Instance is private;
+ Nil : constant Instance;
+
+ List_Empty : exception;
+ -- This exception is raised when the list is empty, and an attempt is
+ -- made to delete an element from it.
+
+ List_Locked : exception;
+ -- This exception is raised when the list is being iterated on, and an
+ -- attempt is made to mutate its state.
+
+ Not_Created : exception;
+ -- This exception is raised when the list has not been created by
+ -- routine Create, and an attempt is made to read or mutate its state.
+
+ procedure Append (L : Instance; Elem : Element_Type);
+ -- Insert element Elem at the end of list L. This action will raise
+ -- List_Locked if the list has outstanding iterators.
+
+ function Contains (L : Instance; Elem : Element_Type) return Boolean;
+ -- Determine whether list L contains element Elem
+
+ function Create return Instance;
+ -- Create a new list
+
+ procedure Delete (L : Instance; Elem : Element_Type);
+ -- Delete element Elem from list L. The routine has no effect if Elem is
+ -- not present. This action will raise
+ --
+ -- * List_Empty if the list is empty.
+ -- * List_Locked if the list has outstanding iterators.
+
+ procedure Delete_First (L : Instance);
+ -- Delete an element from the start of list L. This action will raise
+ --
+ -- * List_Empty if the list is empty.
+ -- * List_Locked if the list has outstanding iterators.
+
+ procedure Delete_Last (L : Instance);
+ -- Delete an element from the end of list L. This action will raise
+ --
+ -- * List_Empty if the list is empty.
+ -- * List_Locked if the list has outstanding iterators.
+
+ procedure Destroy (L : in out Instance);
+ -- Destroy the contents of list L. This routine must be called at the
+ -- end of a list's lifetime. This action will raise List_Locked if the
+ -- list has outstanding iterators.
+
+ function First (L : Instance) return Element_Type;
+ -- Obtain an element from the start of list L. This action will raise
+ -- List_Empty if the list is empty.
+
+ procedure Insert_After
+ (L : Instance;
+ After : Element_Type;
+ Elem : Element_Type);
+ -- Insert new element Elem after element After in list L. The routine
+ -- has no effect if After is not present. This action will raise
+ -- List_Locked if the list has outstanding iterators.
+
+ procedure Insert_Before
+ (L : Instance;
+ Before : Element_Type;
+ Elem : Element_Type);
+ -- Insert new element Elem before element Before in list L. The routine
+ -- has no effect if After is not present. This action will raise
+ -- List_Locked if the list has outstanding iterators.
+
+ function Is_Empty (L : Instance) return Boolean;
+ -- Determine whether list L is empty
+
+ function Last (L : Instance) return Element_Type;
+ -- Obtain an element from the end of list L. This action will raise
+ -- List_Empty if the list is empty.
+
+ function Length (L : Instance) return Element_Count_Type;
+ -- Obtain the number of elements in list L
+
+ procedure Prepend (L : Instance; Elem : Element_Type);
+ -- Insert element Elem at the start of list L. This action will raise
+ -- List_Locked if the list has outstanding iterators.
+
+ procedure Replace
+ (L : Instance;
+ Old_Elem : Element_Type;
+ New_Elem : Element_Type);
+ -- Replace old element Old_Elem with new element New_Elem in list L. The
+ -- routine has no effect if Old_Elem is not present. This action will
+ -- raise List_Locked if the list has outstanding iterators.
+
+ -------------------------
+ -- Iterator operations --
+ -------------------------
+
+ -- The following type represents an element iterator. An iterator locks
+ -- all mutation operations, and ulocks them once it is exhausted. The
+ -- iterator must be used with the following pattern:
+ --
+ -- Iter := Iterate (My_List);
+ -- while Has_Next (Iter) loop
+ -- Next (Iter, Element);
+ -- end loop;
+ --
+ -- It is possible to advance the iterator by using Next only, however
+ -- this risks raising Iterator_Exhausted.
+
+ type Iterator is private;
+
+ Iterator_Exhausted : exception;
+ -- This exception is raised when an iterator is exhausted and further
+ -- attempts to advance it are made by calling routine Next.
+
+ function Iterate (L : Instance) return Iterator;
+ -- Obtain an iterator over the elements of list L. This action locks all
+ -- mutation functionality of the associated list.
+
+ function Has_Next (Iter : Iterator) return Boolean;
+ -- Determine whether iterator Iter has more elements to examine. If the
+ -- iterator has been exhausted, restore all mutation functionality of
+ -- the associated list.
+
+ procedure Next
+ (Iter : in out Iterator;
+ Elem : out Element_Type);
+ -- Return the current element referenced by iterator Iter and advance
+ -- to the next available element. If the iterator has been exhausted
+ -- and further attempts are made to advance it, this routine restores
+ -- mutation functionality of the associated list, and then raises
+ -- Iterator_Exhausted.
+
+ private
+ -- The following type represents a list node
+
+ type Node;
+ type Node_Ptr is access all Node;
+ type Node is record
+ Elem : Element_Type;
+
+ Next : Node_Ptr := null;
+ Prev : Node_Ptr := null;
+ end record;
+
+ -- The following type represents a list
+
+ type Linked_List is record
+ Elements : Element_Count_Type := 0;
+ -- The number of elements in the list
+
+ Locked : Natural := 0;
+ -- Number of outstanding iterators
+
+ Nodes : aliased Node;
+ -- The dummy head of the list
+ end record;
+
+ type Instance is access all Linked_List;
+ Nil : constant Instance := null;
+
+ -- The following type represents an element iterator
+
+ type Iterator is record
+ List : Instance := null;
+ -- Reference to the associated list
+
+ Nod : Node_Ptr := null;
+ -- Reference to the current node being examined. The invariant of the
+ -- iterator requires that this field always points to a valid node. A
+ -- value of null indicates that the iterator is exhausted.
+ end record;
+ end Doubly_Linked_List;
+
+end GNAT.Lists;
diff --git a/gcc/ada/libgnat/s-dfmkio.ads b/gcc/ada/libgnat/s-dfmkio.ads
new file mode 100644
index 0000000..c9a96c2
--- /dev/null
+++ b/gcc/ada/libgnat/s-dfmkio.ads
@@ -0,0 +1,38 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . D I M . F L O A T _ M K S _ I O --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, 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. --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+-- Provides output facilities for the Float MKS dimension system (see
+-- System.Dim.Float_Mks and System.Dim.Float_IO).
+
+with System.Dim.Float_Mks; use System.Dim.Float_Mks;
+with System.Dim.Float_IO;
+
+package System.Dim.Float_Mks_IO is new System.Dim.Float_IO (Mks_Type);
diff --git a/gcc/ada/libgnat/s-dfmopr.ads b/gcc/ada/libgnat/s-dfmopr.ads
new file mode 100644
index 0000000..6938feb
--- /dev/null
+++ b/gcc/ada/libgnat/s-dfmopr.ads
@@ -0,0 +1,35 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . D I M . F L O A T _ M K S . O T H E R _ P R E F I X E S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, 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. --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+with System.Dim.Generic_Mks.Generic_Other_Prefixes;
+
+package System.Dim.Float_Mks.Other_Prefixes is
+ new System.Dim.Float_Mks.Generic_Other_Prefixes;
diff --git a/gcc/ada/libgnat/s-dgmgop.ads b/gcc/ada/libgnat/s-dgmgop.ads
new file mode 100644
index 0000000..496056d
--- /dev/null
+++ b/gcc/ada/libgnat/s-dgmgop.ads
@@ -0,0 +1,174 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . D I M . G E N E R I C _ M K S --
+-- . G E N E R I C _ O T H E R _ P R E F I X E S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2011-2018, 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. --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+-- Package that defines some other prefixes for the MKS base unit system.
+
+-- These prefixes have been defined in a child package in order to avoid too
+-- many constant declarations in System.Dim.Generic_Mks.
+
+generic
+package System.Dim.Generic_Mks.Generic_Other_Prefixes is
+
+ -- SI prefixes for Meter
+
+ pragma Warnings (Off);
+ -- Turn off the all the dimension warnings
+
+ ym : constant Length := 1.0E-24; -- yocto
+ zm : constant Length := 1.0E-21; -- zepto
+ am : constant Length := 1.0E-18; -- atto
+ fm : constant Length := 1.0E-15; -- femto
+ pm : constant Length := 1.0E-12; -- pico
+ nm : constant Length := 1.0E-09; -- nano
+ Gm : constant Length := 1.0E+09; -- giga
+ Tm : constant Length := 1.0E+12; -- tera
+ Pem : constant Length := 1.0E+15; -- peta
+ Em : constant Length := 1.0E+18; -- exa
+ Zem : constant Length := 1.0E+21; -- zetta
+ Yom : constant Length := 1.0E+24; -- yotta
+
+ -- SI prefixes for Kilogram
+
+ yg : constant Mass := 1.0E-27; -- yocto
+ zg : constant Mass := 1.0E-24; -- zepto
+ ag : constant Mass := 1.0E-21; -- atto
+ fg : constant Mass := 1.0E-18; -- femto
+ pg : constant Mass := 1.0E-15; -- pico
+ ng : constant Mass := 1.0E-12; -- nano
+ Gg : constant Mass := 1.0E+06; -- giga
+ Tg : constant Mass := 1.0E+09; -- tera
+ Peg : constant Mass := 1.0E+13; -- peta
+ Eg : constant Mass := 1.0E+15; -- exa
+ Zeg : constant Mass := 1.0E+18; -- zetta
+ Yog : constant Mass := 1.0E+21; -- yotta
+
+ -- SI prefixes for Second
+
+ ys : constant Time := 1.0E-24; -- yocto
+ zs : constant Time := 1.0E-21; -- zepto
+ as : constant Time := 1.0E-18; -- atto
+ fs : constant Time := 1.0E-15; -- femto
+ ps : constant Time := 1.0E-12; -- pico
+ ns : constant Time := 1.0E-09; -- nano
+ Gs : constant Time := 1.0E+09; -- giga
+ Ts : constant Time := 1.0E+12; -- tera
+ Pes : constant Time := 1.0E+15; -- peta
+ Es : constant Time := 1.0E+18; -- exa
+ Zes : constant Time := 1.0E+21; -- zetta
+ Yos : constant Time := 1.0E+24; -- yotta
+
+ -- SI prefixes for Ampere
+
+ yA : constant Electric_Current := 1.0E-24; -- yocto
+ zA : constant Electric_Current := 1.0E-21; -- zepto
+ aA : constant Electric_Current := 1.0E-18; -- atto
+ fA : constant Electric_Current := 1.0E-15; -- femto
+ nA : constant Electric_Current := 1.0E-09; -- nano
+ uA : constant Electric_Current := 1.0E-06; -- micro (u)
+ GA : constant Electric_Current := 1.0E+09; -- giga
+ TA : constant Electric_Current := 1.0E+12; -- tera
+ PeA : constant Electric_Current := 1.0E+15; -- peta
+ EA : constant Electric_Current := 1.0E+18; -- exa
+ ZeA : constant Electric_Current := 1.0E+21; -- zetta
+ YoA : constant Electric_Current := 1.0E+24; -- yotta
+
+ -- SI prefixes for Kelvin
+
+ yK : constant Thermodynamic_Temperature := 1.0E-24; -- yocto
+ zK : constant Thermodynamic_Temperature := 1.0E-21; -- zepto
+ aK : constant Thermodynamic_Temperature := 1.0E-18; -- atto
+ fK : constant Thermodynamic_Temperature := 1.0E-15; -- femto
+ pK : constant Thermodynamic_Temperature := 1.0E-12; -- pico
+ nK : constant Thermodynamic_Temperature := 1.0E-09; -- nano
+ uK : constant Thermodynamic_Temperature := 1.0E-06; -- micro (u)
+ mK : constant Thermodynamic_Temperature := 1.0E-03; -- milli
+ cK : constant Thermodynamic_Temperature := 1.0E-02; -- centi
+ dK : constant Thermodynamic_Temperature := 1.0E-01; -- deci
+ daK : constant Thermodynamic_Temperature := 1.0E+01; -- deka
+ hK : constant Thermodynamic_Temperature := 1.0E+02; -- hecto
+ kK : constant Thermodynamic_Temperature := 1.0E+03; -- kilo
+ MeK : constant Thermodynamic_Temperature := 1.0E+06; -- mega
+ GK : constant Thermodynamic_Temperature := 1.0E+09; -- giga
+ TK : constant Thermodynamic_Temperature := 1.0E+12; -- tera
+ PeK : constant Thermodynamic_Temperature := 1.0E+15; -- peta
+ EK : constant Thermodynamic_Temperature := 1.0E+18; -- exa
+ ZeK : constant Thermodynamic_Temperature := 1.0E+21; -- zetta
+ YoK : constant Thermodynamic_Temperature := 1.0E+24; -- yotta
+
+ -- SI prefixes for Mole
+
+ ymol : constant Amount_Of_Substance := 1.0E-24; -- yocto
+ zmol : constant Amount_Of_Substance := 1.0E-21; -- zepto
+ amol : constant Amount_Of_Substance := 1.0E-18; -- atto
+ fmol : constant Amount_Of_Substance := 1.0E-15; -- femto
+ pmol : constant Amount_Of_Substance := 1.0E-12; -- pico
+ nmol : constant Amount_Of_Substance := 1.0E-09; -- nano
+ umol : constant Amount_Of_Substance := 1.0E-06; -- micro (u)
+ mmol : constant Amount_Of_Substance := 1.0E-03; -- milli
+ cmol : constant Amount_Of_Substance := 1.0E-02; -- centi
+ dmol : constant Amount_Of_Substance := 1.0E-01; -- deci
+ damol : constant Amount_Of_Substance := 1.0E+01; -- deka
+ hmol : constant Amount_Of_Substance := 1.0E+02; -- hecto
+ kmol : constant Amount_Of_Substance := 1.0E+03; -- kilo
+ Memol : constant Amount_Of_Substance := 1.0E+06; -- mega
+ Gmol : constant Amount_Of_Substance := 1.0E+09; -- giga
+ Tmol : constant Amount_Of_Substance := 1.0E+12; -- tera
+ Pemol : constant Amount_Of_Substance := 1.0E+15; -- peta
+ Emol : constant Amount_Of_Substance := 1.0E+18; -- exa
+ Zemol : constant Amount_Of_Substance := 1.0E+21; -- zetta
+ Yomol : constant Amount_Of_Substance := 1.0E+24; -- yotta
+
+ -- SI prefixes for Candela
+
+ ycd : constant Luminous_Intensity := 1.0E-24; -- yocto
+ zcd : constant Luminous_Intensity := 1.0E-21; -- zepto
+ acd : constant Luminous_Intensity := 1.0E-18; -- atto
+ fcd : constant Luminous_Intensity := 1.0E-15; -- femto
+ pcd : constant Luminous_Intensity := 1.0E-12; -- pico
+ ncd : constant Luminous_Intensity := 1.0E-09; -- nano
+ ucd : constant Luminous_Intensity := 1.0E-06; -- micro (u)
+ mcd : constant Luminous_Intensity := 1.0E-03; -- milli
+ ccd : constant Luminous_Intensity := 1.0E-02; -- centi
+ dcd : constant Luminous_Intensity := 1.0E-01; -- deci
+ dacd : constant Luminous_Intensity := 1.0E+01; -- deka
+ hcd : constant Luminous_Intensity := 1.0E+02; -- hecto
+ kcd : constant Luminous_Intensity := 1.0E+03; -- kilo
+ Mecd : constant Luminous_Intensity := 1.0E+06; -- mega
+ Gcd : constant Luminous_Intensity := 1.0E+09; -- giga
+ Tcd : constant Luminous_Intensity := 1.0E+12; -- tera
+ Pecd : constant Luminous_Intensity := 1.0E+15; -- peta
+ Ecd : constant Luminous_Intensity := 1.0E+18; -- exa
+ Zecd : constant Luminous_Intensity := 1.0E+21; -- zetta
+ Yocd : constant Luminous_Intensity := 1.0E+24; -- yotta
+
+ pragma Warnings (On);
+end System.Dim.Generic_Mks.Generic_Other_Prefixes;
diff --git a/gcc/ada/libgnat/s-diflmk.ads b/gcc/ada/libgnat/s-diflmk.ads
new file mode 100644
index 0000000..435948e
--- /dev/null
+++ b/gcc/ada/libgnat/s-diflmk.ads
@@ -0,0 +1,34 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . D I M . F L O A T _ M K S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, 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. --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+with System.Dim.Generic_Mks;
+
+package System.Dim.Float_Mks is new System.Dim.Generic_Mks (Float);
diff --git a/gcc/ada/libgnat/s-digemk.ads b/gcc/ada/libgnat/s-digemk.ads
new file mode 100644
index 0000000..4f55ad4
--- /dev/null
+++ b/gcc/ada/libgnat/s-digemk.ads
@@ -0,0 +1,396 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . D I M . G E N E R I C _ M K S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2011-2018, 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. --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+-- Defines the MKS dimension system which is the SI system of units
+
+-- Some other prefixes of this system are defined in a child package (see
+-- System.Dim.Generic_Mks.Generic_Other_Prefixes) in order to avoid too many
+-- constant declarations in this package.
+
+-- The dimension terminology is defined in System.Dim package
+
+with Ada.Numerics;
+
+generic
+ type Float_Type is digits <>;
+
+package System.Dim.Generic_Mks is
+
+ e : constant := Ada.Numerics.e;
+ Pi : constant := Ada.Numerics.Pi;
+
+ -- Dimensioned type Mks_Type
+
+ type Mks_Type is new Float_Type
+ with
+ Dimension_System => (
+ (Unit_Name => Meter, Unit_Symbol => 'm', Dim_Symbol => 'L'),
+ (Unit_Name => Kilogram, Unit_Symbol => "kg", Dim_Symbol => 'M'),
+ (Unit_Name => Second, Unit_Symbol => 's', Dim_Symbol => 'T'),
+ (Unit_Name => Ampere, Unit_Symbol => 'A', Dim_Symbol => 'I'),
+ (Unit_Name => Kelvin, Unit_Symbol => 'K', Dim_Symbol => '@'),
+ (Unit_Name => Mole, Unit_Symbol => "mol", Dim_Symbol => 'N'),
+ (Unit_Name => Candela, Unit_Symbol => "cd", Dim_Symbol => 'J'));
+
+ -- SI Base dimensioned subtypes
+
+ subtype Length is Mks_Type
+ with
+ Dimension => (Symbol => 'm',
+ Meter => 1,
+ others => 0);
+
+ subtype Mass is Mks_Type
+ with
+ Dimension => (Symbol => "kg",
+ Kilogram => 1,
+ others => 0);
+
+ subtype Time is Mks_Type
+ with
+ Dimension => (Symbol => 's',
+ Second => 1,
+ others => 0);
+
+ subtype Electric_Current is Mks_Type
+ with
+ Dimension => (Symbol => 'A',
+ Ampere => 1,
+ others => 0);
+
+ subtype Thermodynamic_Temperature is Mks_Type
+ with
+ Dimension => (Symbol => 'K',
+ Kelvin => 1,
+ others => 0);
+
+ subtype Amount_Of_Substance is Mks_Type
+ with
+ Dimension => (Symbol => "mol",
+ Mole => 1,
+ others => 0);
+
+ subtype Luminous_Intensity is Mks_Type
+ with
+ Dimension => (Symbol => "cd",
+ Candela => 1,
+ others => 0);
+
+ -- Initialize SI Base unit values
+
+ -- Turn off the all the dimension warnings for these basic assignments
+ -- since otherwise we would get complaints about assigning dimensionless
+ -- values to dimensioned subtypes (we can't assign 1.0*m to m).
+
+ pragma Warnings (Off, "*assumed to be*");
+
+ m : constant Length := 1.0;
+ kg : constant Mass := 1.0;
+ s : constant Time := 1.0;
+ A : constant Electric_Current := 1.0;
+ K : constant Thermodynamic_Temperature := 1.0;
+ mol : constant Amount_Of_Substance := 1.0;
+ cd : constant Luminous_Intensity := 1.0;
+
+ pragma Warnings (On, "*assumed to be*");
+
+ -- SI Derived dimensioned subtypes
+
+ subtype Absorbed_Dose is Mks_Type
+ with
+ Dimension => (Symbol => "Gy",
+ Meter => 2,
+ Second => -2,
+ others => 0);
+
+ subtype Angle is Mks_Type
+ with
+ Dimension => (Symbol => "rad",
+ others => 0);
+
+ subtype Area is Mks_Type
+ with
+ Dimension => (
+ Meter => 2,
+ others => 0);
+
+ subtype Catalytic_Activity is Mks_Type
+ with
+ Dimension => (Symbol => "kat",
+ Second => -1,
+ Mole => 1,
+ others => 0);
+
+ subtype Celsius_Temperature is Mks_Type
+ with
+ Dimension => (Symbol => "°C",
+ Kelvin => 1,
+ others => 0);
+
+ subtype Electric_Capacitance is Mks_Type
+ with
+ Dimension => (Symbol => 'F',
+ Meter => -2,
+ Kilogram => -1,
+ Second => 4,
+ Ampere => 2,
+ others => 0);
+
+ subtype Electric_Charge is Mks_Type
+ with
+ Dimension => (Symbol => 'C',
+ Second => 1,
+ Ampere => 1,
+ others => 0);
+
+ subtype Electric_Conductance is Mks_Type
+ with
+ Dimension => (Symbol => 'S',
+ Meter => -2,
+ Kilogram => -1,
+ Second => 3,
+ Ampere => 2,
+ others => 0);
+
+ subtype Electric_Potential_Difference is Mks_Type
+ with
+ Dimension => (Symbol => 'V',
+ Meter => 2,
+ Kilogram => 1,
+ Second => -3,
+ Ampere => -1,
+ others => 0);
+
+ -- Note the type punning below. The Symbol is a single "ohm" character
+ -- encoded in UTF-8 (ce a9 in hexadecimal), but this file is not compiled
+ -- with -gnatW8, so we're treating the string literal as a two-character
+ -- String.
+
+ subtype Electric_Resistance is Mks_Type
+ with
+ Dimension => (Symbol => "Ω",
+ Meter => 2,
+ Kilogram => 1,
+ Second => -3,
+ Ampere => -2,
+ others => 0);
+
+ subtype Energy is Mks_Type
+ with
+ Dimension => (Symbol => 'J',
+ Meter => 2,
+ Kilogram => 1,
+ Second => -2,
+ others => 0);
+
+ subtype Equivalent_Dose is Mks_Type
+ with
+ Dimension => (Symbol => "Sv",
+ Meter => 2,
+ Second => -2,
+ others => 0);
+
+ subtype Force is Mks_Type
+ with
+ Dimension => (Symbol => 'N',
+ Meter => 1,
+ Kilogram => 1,
+ Second => -2,
+ others => 0);
+
+ subtype Frequency is Mks_Type
+ with
+ Dimension => (Symbol => "Hz",
+ Second => -1,
+ others => 0);
+
+ subtype Illuminance is Mks_Type
+ with
+ Dimension => (Symbol => "lx",
+ Meter => -2,
+ Candela => 1,
+ others => 0);
+
+ subtype Inductance is Mks_Type
+ with
+ Dimension => (Symbol => 'H',
+ Meter => 2,
+ Kilogram => 1,
+ Second => -2,
+ Ampere => -2,
+ others => 0);
+
+ subtype Luminous_Flux is Mks_Type
+ with
+ Dimension => (Symbol => "lm",
+ Candela => 1,
+ others => 0);
+
+ subtype Magnetic_Flux is Mks_Type
+ with
+ Dimension => (Symbol => "Wb",
+ Meter => 2,
+ Kilogram => 1,
+ Second => -2,
+ Ampere => -1,
+ others => 0);
+
+ subtype Magnetic_Flux_Density is Mks_Type
+ with
+ Dimension => (Symbol => 'T',
+ Kilogram => 1,
+ Second => -2,
+ Ampere => -1,
+ others => 0);
+
+ subtype Power is Mks_Type
+ with
+ Dimension => (Symbol => 'W',
+ Meter => 2,
+ Kilogram => 1,
+ Second => -3,
+ others => 0);
+
+ subtype Pressure is Mks_Type
+ with
+ Dimension => (Symbol => "Pa",
+ Meter => -1,
+ Kilogram => 1,
+ Second => -2,
+ others => 0);
+
+ subtype Radioactivity is Mks_Type
+ with
+ Dimension => (Symbol => "Bq",
+ Second => -1,
+ others => 0);
+
+ subtype Solid_Angle is Mks_Type
+ with
+ Dimension => (Symbol => "sr",
+ others => 0);
+
+ subtype Speed is Mks_Type
+ with
+ Dimension => (
+ Meter => 1,
+ Second => -1,
+ others => 0);
+
+ subtype Volume is Mks_Type
+ with
+ Dimension => (
+ Meter => 3,
+ others => 0);
+
+ -- Initialize derived dimension values
+
+ -- Turn off the all the dimension warnings for these basic assignments
+ -- since otherwise we would get complaints about assigning dimensionless
+ -- values to dimensioned subtypes.
+
+ pragma Warnings (Off, "*assumed to be*");
+
+ rad : constant Angle := 1.0;
+ sr : constant Solid_Angle := 1.0;
+ Hz : constant Frequency := 1.0;
+ N : constant Force := 1.0;
+ Pa : constant Pressure := 1.0;
+ J : constant Energy := 1.0;
+ W : constant Power := 1.0;
+ C : constant Electric_Charge := 1.0;
+ V : constant Electric_Potential_Difference := 1.0;
+ F : constant Electric_Capacitance := 1.0;
+ Ohm : constant Electric_Resistance := 1.0;
+ Si : constant Electric_Conductance := 1.0;
+ Wb : constant Magnetic_Flux := 1.0;
+ T : constant Magnetic_Flux_Density := 1.0;
+ H : constant Inductance := 1.0;
+ dC : constant Celsius_Temperature := 273.15;
+ lm : constant Luminous_Flux := 1.0;
+ lx : constant Illuminance := 1.0;
+ Bq : constant Radioactivity := 1.0;
+ Gy : constant Absorbed_Dose := 1.0;
+ Sv : constant Equivalent_Dose := 1.0;
+ kat : constant Catalytic_Activity := 1.0;
+
+ -- SI prefixes for Meter
+
+ um : constant Length := 1.0E-06; -- micro (u)
+ mm : constant Length := 1.0E-03; -- milli
+ cm : constant Length := 1.0E-02; -- centi
+ dm : constant Length := 1.0E-01; -- deci
+ dam : constant Length := 1.0E+01; -- deka
+ hm : constant Length := 1.0E+02; -- hecto
+ km : constant Length := 1.0E+03; -- kilo
+ Mem : constant Length := 1.0E+06; -- mega
+
+ -- SI prefixes for Kilogram
+
+ ug : constant Mass := 1.0E-09; -- micro (u)
+ mg : constant Mass := 1.0E-06; -- milli
+ cg : constant Mass := 1.0E-05; -- centi
+ dg : constant Mass := 1.0E-04; -- deci
+ g : constant Mass := 1.0E-03; -- gram
+ dag : constant Mass := 1.0E-02; -- deka
+ hg : constant Mass := 1.0E-01; -- hecto
+ Meg : constant Mass := 1.0E+03; -- mega
+
+ -- SI prefixes for Second
+
+ us : constant Time := 1.0E-06; -- micro (u)
+ ms : constant Time := 1.0E-03; -- milli
+ cs : constant Time := 1.0E-02; -- centi
+ ds : constant Time := 1.0E-01; -- deci
+ das : constant Time := 1.0E+01; -- deka
+ hs : constant Time := 1.0E+02; -- hecto
+ ks : constant Time := 1.0E+03; -- kilo
+ Mes : constant Time := 1.0E+06; -- mega
+
+ -- Other constants for Second
+
+ min : constant Time := 60.0 * s;
+ hour : constant Time := 60.0 * min;
+ day : constant Time := 24.0 * hour;
+ year : constant Time := 365.25 * day;
+
+ -- SI prefixes for Ampere
+
+ mA : constant Electric_Current := 1.0E-03; -- milli
+ cA : constant Electric_Current := 1.0E-02; -- centi
+ dA : constant Electric_Current := 1.0E-01; -- deci
+ daA : constant Electric_Current := 1.0E+01; -- deka
+ hA : constant Electric_Current := 1.0E+02; -- hecto
+ kA : constant Electric_Current := 1.0E+03; -- kilo
+ MeA : constant Electric_Current := 1.0E+06; -- mega
+
+ pragma Warnings (On, "*assumed to be*");
+end System.Dim.Generic_Mks;
diff --git a/gcc/ada/libgnat/s-dilomk.ads b/gcc/ada/libgnat/s-dilomk.ads
new file mode 100644
index 0000000..2aaecae
--- /dev/null
+++ b/gcc/ada/libgnat/s-dilomk.ads
@@ -0,0 +1,34 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . D I M . L O N G _ M K S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, 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. --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+with System.Dim.Generic_Mks;
+
+package System.Dim.Long_Mks is new System.Dim.Generic_Mks (Long_Float);
diff --git a/gcc/ada/libgnat/s-dimmks.ads b/gcc/ada/libgnat/s-dimmks.ads
index f21f82d..bf89f1b 100644
--- a/gcc/ada/libgnat/s-dimmks.ads
+++ b/gcc/ada/libgnat/s-dimmks.ads
@@ -29,365 +29,6 @@
-- --
------------------------------------------------------------------------------
--- Defines the MKS dimension system which is the SI system of units
+with System.Dim.Generic_Mks;
--- Some other prefixes of this system are defined in a child package (see
--- System.Dim_Mks.Other_Prefixes) in order to avoid too many constant
--- declarations in this package.
-
--- The dimension terminology is defined in System.Dim_IO package
-
-with Ada.Numerics;
-
-package System.Dim.Mks is
-
- e : constant := Ada.Numerics.e;
- Pi : constant := Ada.Numerics.Pi;
-
- -- Dimensioned type Mks_Type
-
- type Mks_Type is new Long_Long_Float
- with
- Dimension_System => (
- (Unit_Name => Meter, Unit_Symbol => 'm', Dim_Symbol => 'L'),
- (Unit_Name => Kilogram, Unit_Symbol => "kg", Dim_Symbol => 'M'),
- (Unit_Name => Second, Unit_Symbol => 's', Dim_Symbol => 'T'),
- (Unit_Name => Ampere, Unit_Symbol => 'A', Dim_Symbol => 'I'),
- (Unit_Name => Kelvin, Unit_Symbol => 'K', Dim_Symbol => '@'),
- (Unit_Name => Mole, Unit_Symbol => "mol", Dim_Symbol => 'N'),
- (Unit_Name => Candela, Unit_Symbol => "cd", Dim_Symbol => 'J'));
-
- -- SI Base dimensioned subtypes
-
- subtype Length is Mks_Type
- with
- Dimension => (Symbol => 'm',
- Meter => 1,
- others => 0);
-
- subtype Mass is Mks_Type
- with
- Dimension => (Symbol => "kg",
- Kilogram => 1,
- others => 0);
-
- subtype Time is Mks_Type
- with
- Dimension => (Symbol => 's',
- Second => 1,
- others => 0);
-
- subtype Electric_Current is Mks_Type
- with
- Dimension => (Symbol => 'A',
- Ampere => 1,
- others => 0);
-
- subtype Thermodynamic_Temperature is Mks_Type
- with
- Dimension => (Symbol => 'K',
- Kelvin => 1,
- others => 0);
-
- subtype Amount_Of_Substance is Mks_Type
- with
- Dimension => (Symbol => "mol",
- Mole => 1,
- others => 0);
-
- subtype Luminous_Intensity is Mks_Type
- with
- Dimension => (Symbol => "cd",
- Candela => 1,
- others => 0);
-
- -- Initialize SI Base unit values
-
- -- Turn off the all the dimension warnings for these basic assignments
- -- since otherwise we would get complaints about assigning dimensionless
- -- values to dimensioned subtypes (we can't assign 1.0*m to m).
-
- pragma Warnings (Off, "*assumed to be*");
-
- m : constant Length := 1.0;
- kg : constant Mass := 1.0;
- s : constant Time := 1.0;
- A : constant Electric_Current := 1.0;
- K : constant Thermodynamic_Temperature := 1.0;
- mol : constant Amount_Of_Substance := 1.0;
- cd : constant Luminous_Intensity := 1.0;
-
- pragma Warnings (On, "*assumed to be*");
-
- -- SI Derived dimensioned subtypes
-
- subtype Absorbed_Dose is Mks_Type
- with
- Dimension => (Symbol => "Gy",
- Meter => 2,
- Second => -2,
- others => 0);
-
- subtype Angle is Mks_Type
- with
- Dimension => (Symbol => "rad",
- others => 0);
-
- subtype Area is Mks_Type
- with
- Dimension => (
- Meter => 2,
- others => 0);
-
- subtype Catalytic_Activity is Mks_Type
- with
- Dimension => (Symbol => "kat",
- Second => -1,
- Mole => 1,
- others => 0);
-
- subtype Celsius_Temperature is Mks_Type
- with
- Dimension => (Symbol => "°C",
- Kelvin => 1,
- others => 0);
-
- subtype Electric_Capacitance is Mks_Type
- with
- Dimension => (Symbol => 'F',
- Meter => -2,
- Kilogram => -1,
- Second => 4,
- Ampere => 2,
- others => 0);
-
- subtype Electric_Charge is Mks_Type
- with
- Dimension => (Symbol => 'C',
- Second => 1,
- Ampere => 1,
- others => 0);
-
- subtype Electric_Conductance is Mks_Type
- with
- Dimension => (Symbol => 'S',
- Meter => -2,
- Kilogram => -1,
- Second => 3,
- Ampere => 2,
- others => 0);
-
- subtype Electric_Potential_Difference is Mks_Type
- with
- Dimension => (Symbol => 'V',
- Meter => 2,
- Kilogram => 1,
- Second => -3,
- Ampere => -1,
- others => 0);
-
- -- Note the type punning below. The Symbol is a single "ohm" character
- -- encoded in UTF-8 (ce a9 in hexadecimal), but this file is not compiled
- -- with -gnatW8, so we're treating the string literal as a two-character
- -- String.
-
- subtype Electric_Resistance is Mks_Type
- with
- Dimension => (Symbol => "Ω",
- Meter => 2,
- Kilogram => 1,
- Second => -3,
- Ampere => -2,
- others => 0);
-
- subtype Energy is Mks_Type
- with
- Dimension => (Symbol => 'J',
- Meter => 2,
- Kilogram => 1,
- Second => -2,
- others => 0);
-
- subtype Equivalent_Dose is Mks_Type
- with
- Dimension => (Symbol => "Sv",
- Meter => 2,
- Second => -2,
- others => 0);
-
- subtype Force is Mks_Type
- with
- Dimension => (Symbol => 'N',
- Meter => 1,
- Kilogram => 1,
- Second => -2,
- others => 0);
-
- subtype Frequency is Mks_Type
- with
- Dimension => (Symbol => "Hz",
- Second => -1,
- others => 0);
-
- subtype Illuminance is Mks_Type
- with
- Dimension => (Symbol => "lx",
- Meter => -2,
- Candela => 1,
- others => 0);
-
- subtype Inductance is Mks_Type
- with
- Dimension => (Symbol => 'H',
- Meter => 2,
- Kilogram => 1,
- Second => -2,
- Ampere => -2,
- others => 0);
-
- subtype Luminous_Flux is Mks_Type
- with
- Dimension => (Symbol => "lm",
- Candela => 1,
- others => 0);
-
- subtype Magnetic_Flux is Mks_Type
- with
- Dimension => (Symbol => "Wb",
- Meter => 2,
- Kilogram => 1,
- Second => -2,
- Ampere => -1,
- others => 0);
-
- subtype Magnetic_Flux_Density is Mks_Type
- with
- Dimension => (Symbol => 'T',
- Kilogram => 1,
- Second => -2,
- Ampere => -1,
- others => 0);
-
- subtype Power is Mks_Type
- with
- Dimension => (Symbol => 'W',
- Meter => 2,
- Kilogram => 1,
- Second => -3,
- others => 0);
-
- subtype Pressure is Mks_Type
- with
- Dimension => (Symbol => "Pa",
- Meter => -1,
- Kilogram => 1,
- Second => -2,
- others => 0);
-
- subtype Radioactivity is Mks_Type
- with
- Dimension => (Symbol => "Bq",
- Second => -1,
- others => 0);
-
- subtype Solid_Angle is Mks_Type
- with
- Dimension => (Symbol => "sr",
- others => 0);
-
- subtype Speed is Mks_Type
- with
- Dimension => (
- Meter => 1,
- Second => -1,
- others => 0);
-
- subtype Volume is Mks_Type
- with
- Dimension => (
- Meter => 3,
- others => 0);
-
- -- Initialize derived dimension values
-
- -- Turn off the all the dimension warnings for these basic assignments
- -- since otherwise we would get complaints about assigning dimensionless
- -- values to dimensioned subtypes.
-
- pragma Warnings (Off, "*assumed to be*");
-
- rad : constant Angle := 1.0;
- sr : constant Solid_Angle := 1.0;
- Hz : constant Frequency := 1.0;
- N : constant Force := 1.0;
- Pa : constant Pressure := 1.0;
- J : constant Energy := 1.0;
- W : constant Power := 1.0;
- C : constant Electric_Charge := 1.0;
- V : constant Electric_Potential_Difference := 1.0;
- F : constant Electric_Capacitance := 1.0;
- Ohm : constant Electric_Resistance := 1.0;
- Si : constant Electric_Conductance := 1.0;
- Wb : constant Magnetic_Flux := 1.0;
- T : constant Magnetic_Flux_Density := 1.0;
- H : constant Inductance := 1.0;
- dC : constant Celsius_Temperature := 273.15;
- lm : constant Luminous_Flux := 1.0;
- lx : constant Illuminance := 1.0;
- Bq : constant Radioactivity := 1.0;
- Gy : constant Absorbed_Dose := 1.0;
- Sv : constant Equivalent_Dose := 1.0;
- kat : constant Catalytic_Activity := 1.0;
-
- -- SI prefixes for Meter
-
- um : constant Length := 1.0E-06; -- micro (u)
- mm : constant Length := 1.0E-03; -- milli
- cm : constant Length := 1.0E-02; -- centi
- dm : constant Length := 1.0E-01; -- deci
- dam : constant Length := 1.0E+01; -- deka
- hm : constant Length := 1.0E+02; -- hecto
- km : constant Length := 1.0E+03; -- kilo
- Mem : constant Length := 1.0E+06; -- mega
-
- -- SI prefixes for Kilogram
-
- ug : constant Mass := 1.0E-09; -- micro (u)
- mg : constant Mass := 1.0E-06; -- milli
- cg : constant Mass := 1.0E-05; -- centi
- dg : constant Mass := 1.0E-04; -- deci
- g : constant Mass := 1.0E-03; -- gram
- dag : constant Mass := 1.0E-02; -- deka
- hg : constant Mass := 1.0E-01; -- hecto
- Meg : constant Mass := 1.0E+03; -- mega
-
- -- SI prefixes for Second
-
- us : constant Time := 1.0E-06; -- micro (u)
- ms : constant Time := 1.0E-03; -- milli
- cs : constant Time := 1.0E-02; -- centi
- ds : constant Time := 1.0E-01; -- deci
- das : constant Time := 1.0E+01; -- deka
- hs : constant Time := 1.0E+02; -- hecto
- ks : constant Time := 1.0E+03; -- kilo
- Mes : constant Time := 1.0E+06; -- mega
-
- -- Other constants for Second
-
- min : constant Time := 60.0 * s;
- hour : constant Time := 60.0 * min;
- day : constant Time := 24.0 * hour;
- year : constant Time := 365.25 * day;
-
- -- SI prefixes for Ampere
-
- mA : constant Electric_Current := 1.0E-03; -- milli
- cA : constant Electric_Current := 1.0E-02; -- centi
- dA : constant Electric_Current := 1.0E-01; -- deci
- daA : constant Electric_Current := 1.0E+01; -- deka
- hA : constant Electric_Current := 1.0E+02; -- hecto
- kA : constant Electric_Current := 1.0E+03; -- kilo
- MeA : constant Electric_Current := 1.0E+06; -- mega
-
- pragma Warnings (On, "*assumed to be*");
-end System.Dim.Mks;
+package System.Dim.Mks is new System.Dim.Generic_Mks (Long_Long_Float);
diff --git a/gcc/ada/libgnat/s-dlmkio.ads b/gcc/ada/libgnat/s-dlmkio.ads
new file mode 100644
index 0000000..088727a
--- /dev/null
+++ b/gcc/ada/libgnat/s-dlmkio.ads
@@ -0,0 +1,38 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . D I M . L O N G _ M K S _ I O --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, 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. --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+-- Provides output facilities for the Long_Float MKS dimension system (see
+-- System.Dim.Long_Mks and System.Dim.Float_IO).
+
+with System.Dim.Long_Mks; use System.Dim.Long_Mks;
+with System.Dim.Float_IO;
+
+package System.Dim.Long_Mks_IO is new System.Dim.Float_IO (Mks_Type);
diff --git a/gcc/ada/libgnat/s-dlmopr.ads b/gcc/ada/libgnat/s-dlmopr.ads
new file mode 100644
index 0000000..c9280b4
--- /dev/null
+++ b/gcc/ada/libgnat/s-dlmopr.ads
@@ -0,0 +1,35 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . D I M . L O N G _ M K S . O T H E R _ P R E F I X E S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, 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. --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+with System.Dim.Generic_Mks.Generic_Other_Prefixes;
+
+package System.Dim.Long_Mks.Other_Prefixes is
+ new System.Dim.Long_Mks.Generic_Other_Prefixes;
diff --git a/gcc/ada/libgnat/s-dmotpr.ads b/gcc/ada/libgnat/s-dmotpr.ads
index c0adcb3..041ce37 100644
--- a/gcc/ada/libgnat/s-dmotpr.ads
+++ b/gcc/ada/libgnat/s-dmotpr.ads
@@ -29,144 +29,7 @@
-- --
------------------------------------------------------------------------------
--- Package that defines some other prefixes for the MKS base unit system.
-
--- These prefixes have been defined in a child package in order to avoid too
--- many constant declarations in System.Dim_Mks.
+with System.Dim.Generic_Mks.Generic_Other_Prefixes;
package System.Dim.Mks.Other_Prefixes is
-
- -- SI prefixes for Meter
-
- pragma Warnings (Off);
- -- Turn off the all the dimension warnings
-
- ym : constant Length := 1.0E-24; -- yocto
- zm : constant Length := 1.0E-21; -- zepto
- am : constant Length := 1.0E-18; -- atto
- fm : constant Length := 1.0E-15; -- femto
- pm : constant Length := 1.0E-12; -- pico
- nm : constant Length := 1.0E-09; -- nano
- Gm : constant Length := 1.0E+09; -- giga
- Tm : constant Length := 1.0E+12; -- tera
- Pem : constant Length := 1.0E+15; -- peta
- Em : constant Length := 1.0E+18; -- exa
- Zem : constant Length := 1.0E+21; -- zetta
- Yom : constant Length := 1.0E+24; -- yotta
-
- -- SI prefixes for Kilogram
-
- yg : constant Mass := 1.0E-27; -- yocto
- zg : constant Mass := 1.0E-24; -- zepto
- ag : constant Mass := 1.0E-21; -- atto
- fg : constant Mass := 1.0E-18; -- femto
- pg : constant Mass := 1.0E-15; -- pico
- ng : constant Mass := 1.0E-12; -- nano
- Gg : constant Mass := 1.0E+06; -- giga
- Tg : constant Mass := 1.0E+09; -- tera
- Peg : constant Mass := 1.0E+13; -- peta
- Eg : constant Mass := 1.0E+15; -- exa
- Zeg : constant Mass := 1.0E+18; -- zetta
- Yog : constant Mass := 1.0E+21; -- yotta
-
- -- SI prefixes for Second
-
- ys : constant Time := 1.0E-24; -- yocto
- zs : constant Time := 1.0E-21; -- zepto
- as : constant Time := 1.0E-18; -- atto
- fs : constant Time := 1.0E-15; -- femto
- ps : constant Time := 1.0E-12; -- pico
- ns : constant Time := 1.0E-09; -- nano
- Gs : constant Time := 1.0E+09; -- giga
- Ts : constant Time := 1.0E+12; -- tera
- Pes : constant Time := 1.0E+15; -- peta
- Es : constant Time := 1.0E+18; -- exa
- Zes : constant Time := 1.0E+21; -- zetta
- Yos : constant Time := 1.0E+24; -- yotta
-
- -- SI prefixes for Ampere
-
- yA : constant Electric_Current := 1.0E-24; -- yocto
- zA : constant Electric_Current := 1.0E-21; -- zepto
- aA : constant Electric_Current := 1.0E-18; -- atto
- fA : constant Electric_Current := 1.0E-15; -- femto
- nA : constant Electric_Current := 1.0E-09; -- nano
- uA : constant Electric_Current := 1.0E-06; -- micro (u)
- GA : constant Electric_Current := 1.0E+09; -- giga
- TA : constant Electric_Current := 1.0E+12; -- tera
- PeA : constant Electric_Current := 1.0E+15; -- peta
- EA : constant Electric_Current := 1.0E+18; -- exa
- ZeA : constant Electric_Current := 1.0E+21; -- zetta
- YoA : constant Electric_Current := 1.0E+24; -- yotta
-
- -- SI prefixes for Kelvin
-
- yK : constant Thermodynamic_Temperature := 1.0E-24; -- yocto
- zK : constant Thermodynamic_Temperature := 1.0E-21; -- zepto
- aK : constant Thermodynamic_Temperature := 1.0E-18; -- atto
- fK : constant Thermodynamic_Temperature := 1.0E-15; -- femto
- pK : constant Thermodynamic_Temperature := 1.0E-12; -- pico
- nK : constant Thermodynamic_Temperature := 1.0E-09; -- nano
- uK : constant Thermodynamic_Temperature := 1.0E-06; -- micro (u)
- mK : constant Thermodynamic_Temperature := 1.0E-03; -- milli
- cK : constant Thermodynamic_Temperature := 1.0E-02; -- centi
- dK : constant Thermodynamic_Temperature := 1.0E-01; -- deci
- daK : constant Thermodynamic_Temperature := 1.0E+01; -- deka
- hK : constant Thermodynamic_Temperature := 1.0E+02; -- hecto
- kK : constant Thermodynamic_Temperature := 1.0E+03; -- kilo
- MeK : constant Thermodynamic_Temperature := 1.0E+06; -- mega
- GK : constant Thermodynamic_Temperature := 1.0E+09; -- giga
- TK : constant Thermodynamic_Temperature := 1.0E+12; -- tera
- PeK : constant Thermodynamic_Temperature := 1.0E+15; -- peta
- EK : constant Thermodynamic_Temperature := 1.0E+18; -- exa
- ZeK : constant Thermodynamic_Temperature := 1.0E+21; -- zetta
- YoK : constant Thermodynamic_Temperature := 1.0E+24; -- yotta
-
- -- SI prefixes for Mole
-
- ymol : constant Amount_Of_Substance := 1.0E-24; -- yocto
- zmol : constant Amount_Of_Substance := 1.0E-21; -- zepto
- amol : constant Amount_Of_Substance := 1.0E-18; -- atto
- fmol : constant Amount_Of_Substance := 1.0E-15; -- femto
- pmol : constant Amount_Of_Substance := 1.0E-12; -- pico
- nmol : constant Amount_Of_Substance := 1.0E-09; -- nano
- umol : constant Amount_Of_Substance := 1.0E-06; -- micro (u)
- mmol : constant Amount_Of_Substance := 1.0E-03; -- milli
- cmol : constant Amount_Of_Substance := 1.0E-02; -- centi
- dmol : constant Amount_Of_Substance := 1.0E-01; -- deci
- damol : constant Amount_Of_Substance := 1.0E+01; -- deka
- hmol : constant Amount_Of_Substance := 1.0E+02; -- hecto
- kmol : constant Amount_Of_Substance := 1.0E+03; -- kilo
- Memol : constant Amount_Of_Substance := 1.0E+06; -- mega
- Gmol : constant Amount_Of_Substance := 1.0E+09; -- giga
- Tmol : constant Amount_Of_Substance := 1.0E+12; -- tera
- Pemol : constant Amount_Of_Substance := 1.0E+15; -- peta
- Emol : constant Amount_Of_Substance := 1.0E+18; -- exa
- Zemol : constant Amount_Of_Substance := 1.0E+21; -- zetta
- Yomol : constant Amount_Of_Substance := 1.0E+24; -- yotta
-
- -- SI prefixes for Candela
-
- ycd : constant Luminous_Intensity := 1.0E-24; -- yocto
- zcd : constant Luminous_Intensity := 1.0E-21; -- zepto
- acd : constant Luminous_Intensity := 1.0E-18; -- atto
- fcd : constant Luminous_Intensity := 1.0E-15; -- femto
- pcd : constant Luminous_Intensity := 1.0E-12; -- pico
- ncd : constant Luminous_Intensity := 1.0E-09; -- nano
- ucd : constant Luminous_Intensity := 1.0E-06; -- micro (u)
- mcd : constant Luminous_Intensity := 1.0E-03; -- milli
- ccd : constant Luminous_Intensity := 1.0E-02; -- centi
- dcd : constant Luminous_Intensity := 1.0E-01; -- deci
- dacd : constant Luminous_Intensity := 1.0E+01; -- deka
- hcd : constant Luminous_Intensity := 1.0E+02; -- hecto
- kcd : constant Luminous_Intensity := 1.0E+03; -- kilo
- Mecd : constant Luminous_Intensity := 1.0E+06; -- mega
- Gcd : constant Luminous_Intensity := 1.0E+09; -- giga
- Tcd : constant Luminous_Intensity := 1.0E+12; -- tera
- Pecd : constant Luminous_Intensity := 1.0E+15; -- peta
- Ecd : constant Luminous_Intensity := 1.0E+18; -- exa
- Zecd : constant Luminous_Intensity := 1.0E+21; -- zetta
- Yocd : constant Luminous_Intensity := 1.0E+24; -- yotta
-
- pragma Warnings (On);
-end System.Dim.Mks.Other_Prefixes;
+ new System.Dim.Mks.Generic_Other_Prefixes;
diff --git a/gcc/ada/sa_messages.adb b/gcc/ada/sa_messages.adb
new file mode 100644
index 0000000..30ae48c
--- /dev/null
+++ b/gcc/ada/sa_messages.adb
@@ -0,0 +1,539 @@
+------------------------------------------------------------------------------
+-- C O D E P E E R / S P A R K --
+-- --
+-- Copyright (C) 2015-2018, AdaCore --
+-- --
+-- This 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. This software is distributed in the hope that it will be useful, --
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- --
+-- TABILITY 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 distributed with this software; see file --
+-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy --
+-- of the license. --
+-- --
+------------------------------------------------------------------------------
+
+pragma Ada_2012;
+
+with Ada.Directories; use Ada.Directories;
+with Ada.Strings.Unbounded.Hash;
+
+with Ada.Text_IO; use Ada.Text_IO;
+with GNATCOLL.JSON; use GNATCOLL.JSON;
+
+package body SA_Messages is
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ function "<" (Left, Right : SA_Message) return Boolean is
+ (if Left.Kind /= Right.Kind then
+ Left.Kind < Right.Kind
+ else
+ Left.Kind in Check_Kind
+ and then Left.Check_Result < Right.Check_Result);
+
+ function "<" (Left, Right : Simple_Source_Location) return Boolean is
+ (if Left.File_Name /= Right.File_Name then
+ Left.File_Name < Right.File_Name
+ elsif Left.Line /= Right.Line then
+ Left.Line < Right.Line
+ else
+ Left.Column < Right.Column);
+
+ function "<" (Left, Right : Source_Locations) return Boolean is
+ (if Left'Length /= Right'Length then
+ Left'Length < Right'Length
+ elsif Left'Length = 0 then
+ False
+ elsif Left (Left'Last) /= Right (Right'Last) then
+ Left (Left'Last) < Right (Right'Last)
+ else
+ Left (Left'First .. Left'Last - 1) <
+ Right (Right'First .. Right'Last - 1));
+
+ function "<" (Left, Right : Source_Location) return Boolean is
+ (Left.Locations < Right.Locations);
+
+ function Base_Location
+ (Location : Source_Location) return Simple_Source_Location is
+ (Location.Locations (1));
+
+ function Hash (Key : SA_Message) return Hash_Type;
+ function Hash (Key : Source_Location) return Hash_Type;
+
+ ---------
+ -- "<" --
+ ---------
+
+ function "<" (Left, Right : Message_And_Location) return Boolean is
+ (if Left.Message = Right.Message
+ then Left.Location < Right.Location
+ else Left.Message < Right.Message);
+
+ ------------
+ -- Column --
+ ------------
+
+ function Column (Location : Source_Location) return Column_Number is
+ (Base_Location (Location).Column);
+
+ ---------------
+ -- File_Name --
+ ---------------
+
+ function File_Name (Location : Source_Location) return String is
+ (To_String (Base_Location (Location).File_Name));
+
+ function File_Name (Location : Source_Location) return Unbounded_String is
+ (Base_Location (Location).File_Name);
+
+ ------------------------
+ -- Enclosing_Instance --
+ ------------------------
+
+ function Enclosing_Instance
+ (Location : Source_Location) return Source_Location_Or_Null is
+ (Count => Location.Count - 1,
+ Locations => Location.Locations (2 .. Location.Count));
+
+ ----------
+ -- Hash --
+ ----------
+
+ function Hash (Key : Message_And_Location) return Hash_Type is
+ (Hash (Key.Message) + Hash (Key.Location));
+
+ function Hash (Key : SA_Message) return Hash_Type is
+ begin
+ return Result : Hash_Type :=
+ Hash_Type'Mod (Message_Kind'Pos (Key.Kind))
+ do
+ if Key.Kind in Check_Kind then
+ Result := Result +
+ Hash_Type'Mod (SA_Check_Result'Pos (Key.Check_Result));
+ end if;
+ end return;
+ end Hash;
+
+ function Hash (Key : Source_Location) return Hash_Type is
+ begin
+ return Result : Hash_Type := Hash_Type'Mod (Key.Count) do
+ for Loc of Key.Locations loop
+ Result := Result + Hash (Loc.File_Name);
+ Result := Result + Hash_Type'Mod (Loc.Line);
+ Result := Result + Hash_Type'Mod (Loc.Column);
+ end loop;
+ end return;
+ end Hash;
+
+ ---------------
+ -- Iteration --
+ ---------------
+
+ function Iteration (Location : Source_Location) return Iteration_Id is
+ (Base_Location (Location).Iteration);
+
+ ----------
+ -- Line --
+ ----------
+
+ function Line (Location : Source_Location) return Line_Number is
+ (Base_Location (Location).Line);
+
+ --------------
+ -- Location --
+ --------------
+
+ function Location
+ (Item : Message_And_Location) return Source_Location is
+ (Item.Location);
+
+ ----------
+ -- Make --
+ ----------
+
+ function Make
+ (File_Name : String;
+ Line : Line_Number;
+ Column : Column_Number;
+ Iteration : Iteration_Id;
+ Enclosing_Instance : Source_Location_Or_Null) return Source_Location
+ is
+ begin
+ return Result : Source_Location
+ (Count => Enclosing_Instance.Count + 1)
+ do
+ Result.Locations (1) :=
+ (File_Name => To_Unbounded_String (File_Name),
+ Line => Line,
+ Column => Column,
+ Iteration => Iteration);
+
+ Result.Locations (2 .. Result.Count) := Enclosing_Instance.Locations;
+ end return;
+ end Make;
+
+ ------------------
+ -- Make_Msg_Loc --
+ ------------------
+
+ function Make_Msg_Loc
+ (Msg : SA_Message;
+ Loc : Source_Location) return Message_And_Location
+ is
+ begin
+ return Message_And_Location'(Count => Loc.Count,
+ Message => Msg,
+ Location => Loc);
+ end Make_Msg_Loc;
+
+ -------------
+ -- Message --
+ -------------
+
+ function Message (Item : Message_And_Location) return SA_Message is
+ (Item.Message);
+
+ package Field_Names is
+
+ -- A Source_Location value is represented in JSON as a two or three
+ -- field value having fields Message_Kind (a string) and Locations (an
+ -- array); if the Message_Kind indicates a check kind, then a third
+ -- field is present: Check_Result (a string). The element type of the
+ -- Locations array is a value having at least 4 fields:
+ -- File_Name (a string), Line (an integer), Column (an integer),
+ -- and Iteration_Kind (an integer); if the Iteration_Kind field
+ -- has the value corresponding to the enumeration literal Numbered,
+ -- then two additional integer fields are present, Iteration_Number
+ -- and Iteration_Of_Total.
+
+ Check_Result : constant String := "Check_Result";
+ Column : constant String := "Column";
+ File_Name : constant String := "File_Name";
+ Iteration_Kind : constant String := "Iteration_Kind";
+ Iteration_Number : constant String := "Iteration_Number";
+ Iteration_Of_Total : constant String := "Iteration_Total";
+ Line : constant String := "Line";
+ Locations : constant String := "Locations";
+ Message_Kind : constant String := "Message_Kind";
+ Messages : constant String := "Messages";
+ end Field_Names;
+
+ package body Writing is
+ File : File_Type;
+ -- The file to which output will be written (in Close, not in Write)
+
+ Messages : JSON_Array;
+ -- Successive calls to Write append messages to this list
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ function To_JSON_Array
+ (Locations : Source_Locations) return JSON_Array;
+ -- Represent a Source_Locations array as a JSON_Array
+
+ function To_JSON_Value
+ (Location : Simple_Source_Location) return JSON_Value;
+ -- Represent a Simple_Source_Location as a JSON_Value
+
+ -----------
+ -- Close --
+ -----------
+
+ procedure Close is
+ Value : constant JSON_Value := Create_Object;
+
+ begin
+ -- only one field for now
+ Set_Field (Value, Field_Names.Messages, Messages);
+ Put_Line (File, Write (Item => Value, Compact => False));
+ Clear (Messages);
+ Close (File => File);
+ end Close;
+
+ -------------
+ -- Is_Open --
+ -------------
+
+ function Is_Open return Boolean is (Is_Open (File));
+
+ ----------
+ -- Open --
+ ----------
+
+ procedure Open (File_Name : String) is
+ begin
+ Create (File => File, Mode => Out_File, Name => File_Name);
+ Clear (Messages);
+ end Open;
+
+ -------------------
+ -- To_JSON_Array --
+ -------------------
+
+ function To_JSON_Array
+ (Locations : Source_Locations) return JSON_Array
+ is
+ begin
+ return Result : JSON_Array := Empty_Array do
+ for Location of Locations loop
+ Append (Result, To_JSON_Value (Location));
+ end loop;
+ end return;
+ end To_JSON_Array;
+
+ -------------------
+ -- To_JSON_Value --
+ -------------------
+
+ function To_JSON_Value
+ (Location : Simple_Source_Location) return JSON_Value
+ is
+ begin
+ return Result : constant JSON_Value := Create_Object do
+ Set_Field (Result, Field_Names.File_Name, Location.File_Name);
+ Set_Field (Result, Field_Names.Line, Integer (Location.Line));
+ Set_Field (Result, Field_Names.Column, Integer (Location.Column));
+ Set_Field (Result, Field_Names.Iteration_Kind, Integer'(
+ Iteration_Kind'Pos (Location.Iteration.Kind)));
+
+ if Location.Iteration.Kind = Numbered then
+ Set_Field (Result, Field_Names.Iteration_Number,
+ Location.Iteration.Number);
+ Set_Field (Result, Field_Names.Iteration_Of_Total,
+ Location.Iteration.Of_Total);
+ end if;
+ end return;
+ end To_JSON_Value;
+
+ -----------
+ -- Write --
+ -----------
+
+ procedure Write (Message : SA_Message; Location : Source_Location) is
+ Value : constant JSON_Value := Create_Object;
+
+ begin
+ Set_Field (Value, Field_Names.Message_Kind, Message.Kind'Img);
+
+ if Message.Kind in Check_Kind then
+ Set_Field
+ (Value, Field_Names.Check_Result, Message.Check_Result'Img);
+ end if;
+
+ Set_Field
+ (Value, Field_Names.Locations, To_JSON_Array (Location.Locations));
+ Append (Messages, Value);
+ end Write;
+ end Writing;
+
+ package body Reading is
+ File : File_Type;
+ -- The file from which messages are read (in Open, not in Read)
+
+ Messages : JSON_Array;
+ -- The list of messages that were read in from File
+
+ Next_Index : Positive;
+ -- The index of the message in Messages which will be returned by the
+ -- next call to Get.
+
+ Parse_Full_Path : Boolean := True;
+ -- if the full path or only the base name of the file should be parsed
+
+ -----------
+ -- Close --
+ -----------
+
+ procedure Close is
+ begin
+ Clear (Messages);
+ Close (File);
+ end Close;
+
+ ----------
+ -- Done --
+ ----------
+
+ function Done return Boolean is (Next_Index > Length (Messages));
+
+ ---------
+ -- Get --
+ ---------
+
+ function Get return Message_And_Location is
+ Value : constant JSON_Value := Get (Messages, Next_Index);
+
+ function Get_Message (Kind : Message_Kind) return SA_Message;
+ -- Return SA_Message of given kind, filling in any non-discriminant
+ -- by reading from Value.
+
+ function Make
+ (Location : Source_Location;
+ Message : SA_Message) return Message_And_Location;
+ -- Constructor
+
+ function To_Location
+ (Encoded : JSON_Array;
+ Full_Path : Boolean) return Source_Location;
+ -- Decode a Source_Location from JSON_Array representation
+
+ function To_Simple_Location
+ (Encoded : JSON_Value;
+ Full_Path : Boolean) return Simple_Source_Location;
+ -- Decode a Simple_Source_Location from JSON_Value representation
+
+ -----------------
+ -- Get_Message --
+ -----------------
+
+ function Get_Message (Kind : Message_Kind) return SA_Message is
+ begin
+ -- If we had AI12-0086, then we could use aggregates here (which
+ -- would be better than field-by-field assignment for the usual
+ -- maintainability reasons). But we don't, so we won't.
+
+ return Result : SA_Message (Kind => Kind) do
+ if Kind in Check_Kind then
+ Result.Check_Result :=
+ SA_Check_Result'Value
+ (Get (Value, Field_Names.Check_Result));
+ end if;
+ end return;
+ end Get_Message;
+
+ ----------
+ -- Make --
+ ----------
+
+ function Make
+ (Location : Source_Location;
+ Message : SA_Message) return Message_And_Location
+ is
+ (Count => Location.Count, Message => Message, Location => Location);
+
+ -----------------
+ -- To_Location --
+ -----------------
+
+ function To_Location
+ (Encoded : JSON_Array;
+ Full_Path : Boolean) return Source_Location is
+ begin
+ return Result : Source_Location (Count => Length (Encoded)) do
+ for I in Result.Locations'Range loop
+ Result.Locations (I) :=
+ To_Simple_Location (Get (Encoded, I), Full_Path);
+ end loop;
+ end return;
+ end To_Location;
+
+ ------------------------
+ -- To_Simple_Location --
+ ------------------------
+
+ function To_Simple_Location
+ (Encoded : JSON_Value;
+ Full_Path : Boolean) return Simple_Source_Location
+ is
+ function Get_Iteration_Id
+ (Kind : Iteration_Kind) return Iteration_Id;
+ -- Given the discriminant for an Iteration_Id value, return the
+ -- entire value.
+
+ ----------------------
+ -- Get_Iteration_Id --
+ ----------------------
+
+ function Get_Iteration_Id (Kind : Iteration_Kind)
+ return Iteration_Id
+ is
+ begin
+ -- Initialize non-discriminant fields, if any
+
+ return Result : Iteration_Id (Kind => Kind) do
+ if Kind = Numbered then
+ Result :=
+ (Kind => Numbered,
+ Number =>
+ Get (Encoded, Field_Names.Iteration_Number),
+ Of_Total =>
+ Get (Encoded, Field_Names.Iteration_Of_Total));
+ end if;
+ end return;
+ end Get_Iteration_Id;
+
+ -- Local variables
+
+ FN : constant Unbounded_String :=
+ Get (Encoded, Field_Names.File_Name);
+
+ -- Start of processing for To_Simple_Location
+
+ begin
+ return
+ (File_Name =>
+ (if Full_Path then
+ FN
+ else
+ To_Unbounded_String (Simple_Name (To_String (FN)))),
+ Line =>
+ Line_Number (Integer'(Get (Encoded, Field_Names.Line))),
+ Column =>
+ Column_Number (Integer'(Get (Encoded, Field_Names.Column))),
+ Iteration =>
+ Get_Iteration_Id
+ (Kind => Iteration_Kind'Val (Integer'(Get
+ (Encoded, Field_Names.Iteration_Kind)))));
+ end To_Simple_Location;
+
+ -- Start of processing for Get
+
+ begin
+ Next_Index := Next_Index + 1;
+
+ return Make
+ (Message =>
+ Get_Message
+ (Message_Kind'Value (Get (Value, Field_Names.Message_Kind))),
+ Location =>
+ To_Location
+ (Get (Value, Field_Names.Locations), Parse_Full_Path));
+ end Get;
+
+ -------------
+ -- Is_Open --
+ -------------
+
+ function Is_Open return Boolean is (Is_Open (File));
+
+ ----------
+ -- Open --
+ ----------
+
+ procedure Open (File_Name : String; Full_Path : Boolean := True) is
+ File_Text : Unbounded_String := Null_Unbounded_String;
+
+ begin
+ Parse_Full_Path := Full_Path;
+ Open (File => File, Mode => In_File, Name => File_Name);
+
+ -- File read here, not in Get, but that's an implementation detail
+
+ while not End_Of_File (File) loop
+ Append (File_Text, Get_Line (File));
+ end loop;
+
+ Messages := Get (Read (File_Text), Field_Names.Messages);
+ Next_Index := 1;
+ end Open;
+ end Reading;
+
+end SA_Messages;
diff --git a/gcc/ada/sa_messages.ads b/gcc/ada/sa_messages.ads
new file mode 100644
index 0000000..93226a7
--- /dev/null
+++ b/gcc/ada/sa_messages.ads
@@ -0,0 +1,267 @@
+------------------------------------------------------------------------------
+-- C O D E P E E R / S P A R K --
+-- --
+-- Copyright (C) 2015-2018, AdaCore --
+-- --
+-- This 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. This software is distributed in the hope that it will be useful, --
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- --
+-- TABILITY 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 distributed with this software; see file --
+-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy --
+-- of the license. --
+-- --
+------------------------------------------------------------------------------
+
+pragma Ada_2012;
+
+with Ada.Containers; use Ada.Containers;
+with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
+
+package SA_Messages is
+
+ -- This package can be used for reading/writing a file containing a
+ -- sequence of static anaysis results. Each element can describe a runtime
+ -- check whose outcome has been statically determined, or it might be a
+ -- warning or diagnostic message. It is expected that typically CodePeer
+ -- will do the writing and SPARK will do the reading; this will allow SPARK
+ -- to get the benefit of CodePeer's analysis.
+ --
+ -- Each item is represented as a pair consisting of a message and an
+ -- associated source location. Source locations may refer to a location
+ -- within the expansion of an instance of a generic; this is represented
+ -- by combining the corresponding location within the generic with the
+ -- location of the instance (repeated if the instance itself occurs within
+ -- a generic). In addition, the type Iteration_Id is intended for use in
+ -- distinguishing messages which refer to a specific iteration of a loop
+ -- (this case can arise, for example, if CodePeer chooses to unroll a
+ -- for-loop). This data structure is only general enough to support the
+ -- kinds of unrolling that are currently planned for CodePeer. For
+ -- example, an Iteration_Id can only identify an iteration of the nearest
+ -- enclosing loop of the associated File/Line/Column source location.
+ -- This is not a problem because CodePeer doesn't unroll loops which
+ -- contain other loops.
+
+ type Message_Kind is (
+
+ -- Check kinds
+
+ Array_Index_Check,
+ Divide_By_Zero_Check,
+ Tag_Check,
+ Discriminant_Check,
+ Range_Check,
+ Overflow_Check,
+ Assertion_Check,
+
+ -- Warning kinds
+
+ Suspicious_Range_Precondition_Warning,
+ Suspicious_First_Precondition_Warning,
+ Suspicious_Input_Warning,
+ Suspicious_Constant_Operation_Warning,
+ Unread_In_Out_Parameter_Warning,
+ Unassigned_In_Out_Parameter_Warning,
+ Non_Analyzed_Call_Warning,
+ Procedure_Does_Not_Return_Warning,
+ Check_Fails_On_Every_Call_Warning,
+ Unknown_Call_Warning,
+ Dead_Store_Warning,
+ Dead_Outparam_Store_Warning,
+ Potentially_Dead_Store_Warning,
+ Same_Value_Dead_Store_Warning,
+ Dead_Block_Warning,
+ Infinite_Loop_Warning,
+ Dead_Edge_Warning,
+ Plain_Dead_Edge_Warning,
+ True_Dead_Edge_Warning,
+ False_Dead_Edge_Warning,
+ True_Condition_Dead_Edge_Warning,
+ False_Condition_Dead_Edge_Warning,
+ Unrepeatable_While_Loop_Warning,
+ Dead_Block_Continuation_Warning,
+ Local_Lock_Of_Global_Object_Warning,
+ Analyzed_Module_Warning,
+ Non_Analyzed_Module_Warning,
+ Non_Analyzed_Procedure_Warning,
+ Incompletely_Analyzed_Procedure_Warning);
+
+ -- Assertion_Check includes checks for user-defined PPCs (both specific
+ -- and class-wide), Assert pragma checks, subtype predicate checks,
+ -- type invariant checks (specific and class-wide), and checks for
+ -- implementation-defined assertions such as Assert_And_Cut, Assume,
+ -- Contract_Cases, Default_Initial_Condition, Initial_Condition,
+ -- Loop_Invariant, Loop_Variant, and Refined_Post.
+ --
+ -- TBD: it might be nice to distinguish these different kinds of assertions
+ -- as is done in SPARK's VC_Kind enumeration type, but any distinction
+ -- which isn't already present in CP's BE_Message_Subkind enumeration type
+ -- would require more work on the CP side.
+ --
+ -- The warning kinds are pretty much a copy of the set of
+ -- Be_Message_Subkind values for which CP's Is_Warning predicate returns
+ -- True; see descriptive comment for each in CP's message_kinds.ads .
+
+ subtype Check_Kind is Message_Kind
+ range Array_Index_Check .. Assertion_Check;
+ subtype Warning_Kind is Message_Kind
+ range Message_Kind'Succ (Check_Kind'Last) .. Message_Kind'Last;
+
+ -- Possible outcomes of the static analysis of a runtime check
+ --
+ -- Not_Statically_Known_With_Low_Severity could be used instead of of
+ -- Not_Statically_Known if there is some reason to believe that (although
+ -- the tool couldn't prove it) the check is likely to always pass (in CP
+ -- terms, if the corresponding CP message has severity Low as opposed to
+ -- Medium). It's not clear yet whether SPARK will care about this
+ -- distinction.
+
+ type SA_Check_Result is
+ (Statically_Known_Success,
+ Not_Statically_Known_With_Low_Severity,
+ Not_Statically_Known,
+ Statically_Known_Failure);
+
+ type SA_Message (Kind : Message_Kind := Message_Kind'Last) is record
+ case Kind is
+ when Check_Kind =>
+ Check_Result : SA_Check_Result;
+
+ when Warning_Kind =>
+ null;
+ end case;
+ end record;
+
+ type Source_Location_Or_Null (<>) is private;
+ Null_Location : constant Source_Location_Or_Null;
+ subtype Source_Location is Source_Location_Or_Null with
+ Dynamic_Predicate => Source_Location /= Null_Location;
+
+ type Line_Number is new Positive;
+ type Column_Number is new Positive;
+
+ function File_Name (Location : Source_Location) return String;
+ function File_Name (Location : Source_Location) return Unbounded_String;
+ function Line (Location : Source_Location) return Line_Number;
+ function Column (Location : Source_Location) return Column_Number;
+
+ type Iteration_Kind is (None, Initial, Subsequent, Numbered);
+ -- None is for the usual no-unrolling case.
+ -- Initial and Subsequent are for use in the case where only the first
+ -- iteration of a loop (or some part thereof, such as the termination
+ -- test of a while-loop) is unrolled.
+ -- Numbered is for use in the case where a for-loop with a statically
+ -- known number of iterations is fully unrolled.
+
+ subtype Iteration_Number is Integer range 1 .. 255;
+ subtype Iteration_Total is Integer range 2 .. 255;
+
+ type Iteration_Id (Kind : Iteration_Kind := None) is record
+ case Kind is
+ when Numbered =>
+ Number : Iteration_Number;
+ Of_Total : Iteration_Total;
+ when others =>
+ null;
+ end case;
+ end record;
+
+ function Iteration (Location : Source_Location) return Iteration_Id;
+
+ function Enclosing_Instance
+ (Location : Source_Location) return Source_Location_Or_Null;
+ -- For a source location occurring within the expansion of an instance of a
+ -- generic unit, the Line, Column, and File_Name selectors will indicate a
+ -- location within the generic; the Enclosing_Instance selector yields the
+ -- location of the declaration of the instance.
+
+ function Make
+ (File_Name : String;
+ Line : Line_Number;
+ Column : Column_Number;
+ Iteration : Iteration_Id;
+ Enclosing_Instance : Source_Location_Or_Null) return Source_Location;
+ -- Constructor
+
+ type Message_And_Location (<>) is private;
+
+ function Location (Item : Message_And_Location) return Source_Location;
+ function Message (Item : Message_And_Location) return SA_Message;
+
+ function Make_Msg_Loc
+ (Msg : SA_Message;
+ Loc : Source_Location) return Message_And_Location;
+ -- Selectors
+
+ function "<" (Left, Right : Message_And_Location) return Boolean;
+ function Hash (Key : Message_And_Location) return Hash_Type;
+ -- Actuals for container instances
+
+ File_Extension : constant String; -- ".json" (but could change in future)
+ -- Clients may wish to use File_Extension in constructing
+ -- File_Name parameters for calls to Open.
+
+ package Writing is
+ function Is_Open return Boolean;
+
+ procedure Open (File_Name : String) with
+ Precondition => not Is_Open,
+ Postcondition => Is_Open;
+ -- Behaves like Text_IO.Create with respect to error cases
+
+ procedure Write (Message : SA_Message; Location : Source_Location);
+
+ procedure Close with
+ Precondition => Is_Open,
+ Postcondition => not Is_Open;
+ -- Behaves like Text_IO.Close with respect to error cases
+ end Writing;
+
+ package Reading is
+ function Is_Open return Boolean;
+
+ procedure Open (File_Name : String; Full_Path : Boolean := True) with
+ Precondition => not Is_Open,
+ Postcondition => Is_Open;
+ -- Behaves like Text_IO.Open with respect to error cases
+
+ function Done return Boolean with
+ Precondition => Is_Open;
+
+ function Get return Message_And_Location with
+ Precondition => not Done;
+
+ procedure Close with
+ Precondition => Is_Open,
+ Postcondition => not Is_Open;
+ -- Behaves like Text_IO.Close with respect to error cases
+ end Reading;
+
+private
+ type Simple_Source_Location is record
+ File_Name : Unbounded_String := Null_Unbounded_String;
+ Line : Line_Number := Line_Number'Last;
+ Column : Column_Number := Column_Number'Last;
+ Iteration : Iteration_Id := (Kind => None);
+ end record;
+
+ type Source_Locations is
+ array (Natural range <>) of Simple_Source_Location;
+
+ type Source_Location_Or_Null (Count : Natural) is record
+ Locations : Source_Locations (1 .. Count);
+ end record;
+
+ Null_Location : constant Source_Location_Or_Null :=
+ (Count => 0, Locations => (others => <>));
+
+ type Message_And_Location (Count : Positive) is record
+ Message : SA_Message;
+ Location : Source_Location (Count => Count);
+ end record;
+
+ File_Extension : constant String := ".json";
+end SA_Messages;
diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index cb1b2d5d..96eb488 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -11245,6 +11245,15 @@ package body Sem_Attr is
New_Occurrence_Of (Standard_Short_Integer, Loc),
Expression =>
Make_Integer_Literal (Loc, Uint_0)));
+
+ -- The above sets the Scope of the flag entity to the
+ -- current scope, in which the attribute appears, but
+ -- the flag declaration has been inserted after that
+ -- of Subp_Id, so the scope of the flag the same as
+ -- that of Subp_Id. This is relevant when unnesting,
+ -- whereh processing depends on correct scope settingl
+
+ Set_Scope (Flag_Id, Scop);
end if;
-- Taking the 'Access of an expression function freezes its
diff --git a/gcc/ada/sem_ch10.adb b/gcc/ada/sem_ch10.adb
index 39ed046..e6d0ba5 100644
--- a/gcc/ada/sem_ch10.adb
+++ b/gcc/ada/sem_ch10.adb
@@ -34,7 +34,6 @@ with Elists; use Elists;
with Fname; use Fname;
with Fname.UF; use Fname.UF;
with Freeze; use Freeze;
-with Ghost; use Ghost;
with Impunit; use Impunit;
with Inline; use Inline;
with Lib; use Lib;
@@ -2912,8 +2911,6 @@ package body Sem_Ch10 is
Set_Fatal_Error (Current_Sem_Unit, Error_Ignored);
end if;
end case;
-
- Mark_Ghost_Clause (N);
end Analyze_With_Clause;
------------------------------
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index 28a3dd8..00854c9 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -8765,44 +8765,45 @@ package body Sem_Ch13 is
if Raise_Expression_Present then
declare
- Map : constant Elist_Id := New_Elmt_List;
- New_V : Entity_Id := Empty;
+ function Reset_Loop_Variable
+ (N : Node_Id) return Traverse_Result;
- -- The unanalyzed expression will be copied and appear in
- -- both functions. Normally expressions do not declare new
- -- entities, but quantified expressions do, so we need to
- -- create new entities for their bound variables, to prevent
- -- multiple definitions in gigi.
-
- function Reset_Loop_Variable (N : Node_Id)
- return Traverse_Result;
-
- procedure Collect_Loop_Variables is
+ procedure Reset_Loop_Variables is
new Traverse_Proc (Reset_Loop_Variable);
------------------------
-- Reset_Loop_Variable --
------------------------
- function Reset_Loop_Variable (N : Node_Id)
- return Traverse_Result
+ function Reset_Loop_Variable
+ (N : Node_Id) return Traverse_Result
is
begin
if Nkind (N) = N_Iterator_Specification then
- New_V := Make_Defining_Identifier
- (Sloc (N), Chars (Defining_Identifier (N)));
-
- Set_Defining_Identifier (N, New_V);
+ Set_Defining_Identifier (N,
+ Make_Defining_Identifier
+ (Sloc (N), Chars (Defining_Identifier (N))));
end if;
return OK;
end Reset_Loop_Variable;
+ -- Local variables
+
+ Map : constant Elist_Id := New_Elmt_List;
+
begin
Append_Elmt (Object_Entity, Map);
Append_Elmt (Object_Entity_M, Map);
Expr_M := New_Copy_Tree (Expr, Map => Map);
- Collect_Loop_Variables (Expr_M);
+
+ -- The unanalyzed expression will be copied and appear in
+ -- both functions. Normally expressions do not declare new
+ -- entities, but quantified expressions do, so we need to
+ -- create new entities for their bound variables, to prevent
+ -- multiple definitions in gigi.
+
+ Reset_Loop_Variables (Expr_M);
end;
end if;
@@ -8856,6 +8857,43 @@ package body Sem_Ch13 is
Insert_After_And_Analyze (N, FBody);
+ -- The defining identifier of a quantified expression carries the
+ -- scope in which the type appears, but when unnesting we need
+ -- to indicate that its proper scope is the constructed predicate
+ -- function. The quantified expressions have been converted into
+ -- loops during analysis and expansion.
+
+ declare
+ function Reset_Quantified_Variable_Scope
+ (N : Node_Id) return Traverse_Result;
+
+ procedure Reset_Quantified_Variables_Scope is
+ new Traverse_Proc (Reset_Quantified_Variable_Scope);
+
+ -------------------------------------
+ -- Reset_Quantified_Variable_Scope --
+ -------------------------------------
+
+ function Reset_Quantified_Variable_Scope
+ (N : Node_Id) return Traverse_Result
+ is
+ begin
+ if Nkind_In (N, N_Iterator_Specification,
+ N_Loop_Parameter_Specification)
+ then
+ Set_Scope (Defining_Identifier (N),
+ Predicate_Function (Typ));
+ end if;
+
+ return OK;
+ end Reset_Quantified_Variable_Scope;
+
+ begin
+ if Unnest_Subprogram_Mode then
+ Reset_Quantified_Variables_Scope (Expr);
+ end if;
+ end;
+
-- within a generic unit, prevent a double analysis of the body
-- which will not be marked analyzed yet. This will happen when
-- the freeze node is created during the preanalysis of an
@@ -8972,6 +9010,8 @@ package body Sem_Ch13 is
Insert_Before_And_Analyze (N, FDecl);
Insert_After_And_Analyze (N, FBody);
+
+ -- Should quantified expressions be handled here as well ???
end;
end if;
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index 349ece7..cc84f9c 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -9453,6 +9453,7 @@ package body Sem_Ch3 is
(Derived_Type, Save_Discr_Constr);
Set_Stored_Constraint
(Derived_Type, Expand_To_Stored_Constraint (Parent_Type, Discs));
+
Replace_Components (Derived_Type, New_Decl);
end if;
@@ -13692,7 +13693,12 @@ package body Sem_Ch3 is
Related_Nod : Node_Id) return Entity_Id
is
T_Sub : constant Entity_Id :=
- Create_Itype (E_Record_Subtype, Related_Nod, Corr_Rec, 'C');
+ Create_Itype
+ (Ekind => E_Record_Subtype,
+ Related_Nod => Related_Nod,
+ Related_Id => Corr_Rec,
+ Suffix => 'C',
+ Suffix_Index => -1);
begin
Set_Etype (T_Sub, Corr_Rec);
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index 2dd9d2f..b330426 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -285,208 +285,6 @@ package body Sem_Ch6 is
LocX : constant Source_Ptr := Sloc (Expr);
Spec : constant Node_Id := Specification (N);
- procedure Freeze_Expr_Types (Def_Id : Entity_Id);
- -- N is an expression function that is a completion and Def_Id its
- -- defining entity. Freeze before N all the types referenced by the
- -- expression of the function.
-
- -----------------------
- -- Freeze_Expr_Types --
- -----------------------
-
- procedure Freeze_Expr_Types (Def_Id : Entity_Id) is
- function Cloned_Expression return Node_Id;
- -- Build a duplicate of the expression of the return statement that
- -- has no defining entities shared with the original expression.
-
- function Freeze_Type_Refs (Node : Node_Id) return Traverse_Result;
- -- Freeze all types referenced in the subtree rooted at Node
-
- -----------------------
- -- Cloned_Expression --
- -----------------------
-
- function Cloned_Expression return Node_Id is
- function Clone_Id (Node : Node_Id) return Traverse_Result;
- -- Tree traversal routine that clones the defining identifier of
- -- iterator and loop parameter specification nodes.
-
- --------------
- -- Clone_Id --
- --------------
-
- function Clone_Id (Node : Node_Id) return Traverse_Result is
- begin
- if Nkind_In (Node, N_Iterator_Specification,
- N_Loop_Parameter_Specification)
- then
- Set_Defining_Identifier (Node,
- New_Copy (Defining_Identifier (Node)));
- end if;
-
- return OK;
- end Clone_Id;
-
- procedure Clone_Def_Ids is new Traverse_Proc (Clone_Id);
-
- -- Local variable
-
- Dup_Expr : constant Node_Id := New_Copy_Tree (Expr);
-
- -- Start of processing for Cloned_Expression
-
- begin
- -- We must duplicate the expression with semantic information to
- -- inherit the decoration of global entities in generic instances.
- -- Set the parent of the new node to be the parent of the original
- -- to get the proper context, which is needed for complete error
- -- reporting and for semantic analysis.
-
- Set_Parent (Dup_Expr, Parent (Expr));
-
- -- Replace the defining identifier of iterators and loop param
- -- specifications by a clone to ensure that the cloned expression
- -- and the original expression don't have shared identifiers;
- -- otherwise, as part of the preanalysis of the expression, these
- -- shared identifiers may be left decorated with itypes which
- -- will not be available in the tree passed to the backend.
-
- Clone_Def_Ids (Dup_Expr);
-
- return Dup_Expr;
- end Cloned_Expression;
-
- ----------------------
- -- Freeze_Type_Refs --
- ----------------------
-
- function Freeze_Type_Refs (Node : Node_Id) return Traverse_Result is
- procedure Check_And_Freeze_Type (Typ : Entity_Id);
- -- Check that Typ is fully declared and freeze it if so
-
- ---------------------------
- -- Check_And_Freeze_Type --
- ---------------------------
-
- procedure Check_And_Freeze_Type (Typ : Entity_Id) is
- begin
- -- Skip Itypes created by the preanalysis, and itypes whose
- -- scope is another type (i.e. component subtypes that depend
- -- on a discriminant),
-
- if Is_Itype (Typ)
- and then (Scope_Within_Or_Same (Scope (Typ), Def_Id)
- or else Is_Type (Scope (Typ)))
- then
- return;
- end if;
-
- -- This provides a better error message than generating
- -- primitives whose compilation fails much later. Refine
- -- the error message if possible.
-
- Check_Fully_Declared (Typ, Node);
-
- if Error_Posted (Node) then
- if Has_Private_Component (Typ)
- and then not Is_Private_Type (Typ)
- then
- Error_Msg_NE ("\type& has private component", Node, Typ);
- end if;
-
- else
- Freeze_Before (N, Typ);
- end if;
- end Check_And_Freeze_Type;
-
- -- Start of processing for Freeze_Type_Refs
-
- begin
- -- Check that a type referenced by an entity can be frozen
-
- if Is_Entity_Name (Node) and then Present (Entity (Node)) then
- Check_And_Freeze_Type (Etype (Entity (Node)));
-
- -- Check that the enclosing record type can be frozen
-
- if Ekind_In (Entity (Node), E_Component, E_Discriminant) then
- Check_And_Freeze_Type (Scope (Entity (Node)));
- end if;
-
- -- Freezing an access type does not freeze the designated type,
- -- but freezing conversions between access to interfaces requires
- -- that the interface types themselves be frozen, so that dispatch
- -- table entities are properly created.
-
- -- Unclear whether a more general rule is needed ???
-
- elsif Nkind (Node) = N_Type_Conversion
- and then Is_Access_Type (Etype (Node))
- and then Is_Interface (Designated_Type (Etype (Node)))
- then
- Check_And_Freeze_Type (Designated_Type (Etype (Node)));
- end if;
-
- -- An implicit dereference freezes the designated type. In the
- -- case of a dispatching call whose controlling argument is an
- -- access type, the dereference is not made explicit, so we must
- -- check for such a call and freeze the designated type.
-
- if Nkind (Node) in N_Has_Etype
- and then Present (Etype (Node))
- and then Is_Access_Type (Etype (Node))
- and then Nkind (Parent (Node)) = N_Function_Call
- and then Node = Controlling_Argument (Parent (Node))
- then
- Check_And_Freeze_Type (Designated_Type (Etype (Node)));
- end if;
-
- -- No point in posting several errors on the same expression
-
- if Serious_Errors_Detected > 0 then
- return Abandon;
- else
- return OK;
- end if;
- end Freeze_Type_Refs;
-
- procedure Freeze_References is new Traverse_Proc (Freeze_Type_Refs);
-
- -- Local variables
-
- Saved_First_Entity : constant Entity_Id := First_Entity (Def_Id);
- Saved_Last_Entity : constant Entity_Id := Last_Entity (Def_Id);
- Dup_Expr : constant Node_Id := Cloned_Expression;
-
- -- Start of processing for Freeze_Expr_Types
-
- begin
- -- Preanalyze a duplicate of the expression to have available the
- -- minimum decoration needed to locate referenced unfrozen types
- -- without adding any decoration to the function expression.
-
- Push_Scope (Def_Id);
- Install_Formals (Def_Id);
-
- Preanalyze_Spec_Expression (Dup_Expr, Etype (Def_Id));
- End_Scope;
-
- -- Restore certain attributes of Def_Id since the preanalysis may
- -- have introduced itypes to this scope, thus modifying attributes
- -- First_Entity and Last_Entity.
-
- Set_First_Entity (Def_Id, Saved_First_Entity);
- Set_Last_Entity (Def_Id, Saved_Last_Entity);
-
- if Present (Last_Entity (Def_Id)) then
- Set_Next_Entity (Last_Entity (Def_Id), Empty);
- end if;
-
- -- Freeze all types referenced in the expression
-
- Freeze_References (Dup_Expr);
- end Freeze_Expr_Types;
-
-- Local variables
Asp : Node_Id;
@@ -600,7 +398,11 @@ package body Sem_Ch6 is
-- As elsewhere, we do not emit freeze nodes within a generic unit.
if not Inside_A_Generic then
- Freeze_Expr_Types (Def_Id);
+ Freeze_Expr_Types
+ (Def_Id => Def_Id,
+ Typ => Etype (Def_Id),
+ Expr => Expr,
+ N => N);
end if;
-- For navigation purposes, indicate that the function is a body
@@ -3347,8 +3149,12 @@ package body Sem_Ch6 is
end if;
if not Is_Frozen (Typ) then
- Set_Is_Frozen (Typ);
- Append_New_Elmt (Typ, Result);
+ if Scope (Typ) /= Current_Scope then
+ Set_Is_Frozen (Typ);
+ Append_New_Elmt (Typ, Result);
+ else
+ Freeze_Before (N, Typ);
+ end if;
end if;
end Mask_Type;
@@ -3838,28 +3644,28 @@ package body Sem_Ch6 is
-- They are necessary in any case to insure order of elaboration
-- in gigi.
- if not Is_Frozen (Spec_Id)
+ if Nkind (N) = N_Subprogram_Body
+ and then Was_Expression_Function (N)
+ and then not Has_Completion (Spec_Id)
+ and then Serious_Errors_Detected = 0
and then (Expander_Active
or else ASIS_Mode
- or else (Operating_Mode = Check_Semantics
- and then Serious_Errors_Detected = 0))
+ or else Operating_Mode = Check_Semantics)
then
-- The body generated for an expression function that is not a
-- completion is a freeze point neither for the profile nor for
-- anything else. That's why, in order to prevent any freezing
-- during analysis, we need to mask types declared outside the
- -- expression that are not yet frozen.
+ -- expression (and in an outer scope) that are not yet frozen.
- if Nkind (N) = N_Subprogram_Body
- and then Was_Expression_Function (N)
- and then not Has_Completion (Spec_Id)
- then
- Set_Is_Frozen (Spec_Id);
- Mask_Types := Mask_Unfrozen_Types (Spec_Id);
- else
- Set_Has_Delayed_Freeze (Spec_Id);
- Freeze_Before (N, Spec_Id);
- end if;
+ Set_Is_Frozen (Spec_Id);
+ Mask_Types := Mask_Unfrozen_Types (Spec_Id);
+
+ elsif not Is_Frozen (Spec_Id)
+ and then Serious_Errors_Detected = 0
+ then
+ Set_Has_Delayed_Freeze (Spec_Id);
+ Freeze_Before (N, Spec_Id);
end if;
end if;
@@ -7439,14 +7245,16 @@ package body Sem_Ch6 is
end if;
end;
- -- Functions can override abstract interface functions
+ -- Functions can override abstract interface functions. Return
+ -- types must be subtype conformant.
elsif Ekind (Def_Id) = E_Function
and then Ekind (Subp) = E_Function
and then Matches_Prefixed_View_Profile
(Parameter_Specifications (Parent (Def_Id)),
Parameter_Specifications (Parent (Subp)))
- and then Etype (Def_Id) = Etype (Subp)
+ and then Conforming_Types
+ (Etype (Def_Id), Etype (Subp), Subtype_Conformant)
then
Candidate := Subp;
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index ddfa543..2002b75 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -6067,7 +6067,10 @@ package body Sem_Res is
-- (including the body of another expression function) which would
-- place the freeze node in the wrong scope. An expression function
-- is frozen in the usual fashion, by the appearance of a real body,
- -- or at the end of a declarative part.
+ -- or at the end of a declarative part. However an implcit call to
+ -- an expression function may appear when it is part of a default
+ -- expression in a call to an initialiation procedure, and must be
+ -- frozen now, even if the body is inserted at a later point.
if Is_Entity_Name (Subp)
and then not In_Spec_Expression
@@ -6076,12 +6079,20 @@ package body Sem_Res is
(not Is_Expression_Function_Or_Completion (Entity (Subp))
or else Scope (Entity (Subp)) = Current_Scope)
then
+ if Is_Expression_Function (Entity (Subp)) then
+
+ -- Force freeze of expression function in call
+
+ Set_Comes_From_Source (Subp, True);
+ Set_Must_Not_Freeze (Subp, False);
+ end if;
+
Freeze_Expression (Subp);
end if;
-- For a predefined operator, the type of the result is the type imposed
-- by context, except for a predefined operation on universal fixed.
- -- Otherwise The type of the call is the type returned by the subprogram
+ -- Otherwise the type of the call is the type returned by the subprogram
-- being called.
if Is_Predefined_Op (Nam) then
@@ -6117,7 +6128,25 @@ package body Sem_Res is
Ret_Type : constant Entity_Id := Etype (Nam);
begin
- if Is_Access_Type (Ret_Type)
+ -- If this is a parameterless call there is no ambiguity and the
+ -- call has the type of the function.
+
+ if No (First_Actual (N)) then
+ Set_Etype (N, Etype (Nam));
+
+ if Present (First_Formal (Nam)) then
+ Resolve_Actuals (N, Nam);
+ end if;
+
+ -- Annotate the tree by creating a call marker in case the
+ -- original call is transformed by expansion. The call marker
+ -- is automatically saved for later examination by the ABE
+ -- Processing phase.
+
+ Build_Call_Marker (N);
+
+ elsif Is_Access_Type (Ret_Type)
+
and then Ret_Type = Component_Type (Designated_Type (Ret_Type))
then
Error_Msg_N
diff --git a/gcc/ada/sem_spark.adb b/gcc/ada/sem_spark.adb
index 3abfd99..e522620 100644
--- a/gcc/ada/sem_spark.adb
+++ b/gcc/ada/sem_spark.adb
@@ -52,15 +52,16 @@ package body Sem_SPARK is
type Elaboration_Context_Index is range 0 .. Elaboration_Context_Max - 1;
- function Elaboration_Context_Hash
- (Key : Entity_Id) return Elaboration_Context_Index;
+ function Elaboration_Context_Hash (Key : Entity_Id)
+ return Elaboration_Context_Index;
-- Function to hash any node of the AST
- type Perm_Kind is (No_Access, Read_Only, Read_Write, Write_Only);
- -- Permission type associated with paths
-
- subtype Read_Perm is Perm_Kind range Read_Only .. Read_Write;
- subtype Write_Perm is Perm_Kind range Read_Write .. Write_Only;
+ type Perm_Kind is (Borrowed, Observed, Unrestricted, Moved);
+ -- Permission type associated with paths. The Moved permission is
+ -- equivalent to the Unrestricted one (same permissions). The Moved is
+ -- however used to mark the RHS after a move (which still unrestricted).
+ -- This way, we may generate warnings when manipulating the RHS
+ -- afterwads since it is set to Null after the assignment.
type Perm_Tree_Wrapper;
@@ -94,6 +95,7 @@ package body Sem_SPARK is
-- The definition of permission trees. This is a tree, which has a
-- permission at each node, and depending on the type of the node,
-- can have zero, one, or more children pointed to by an access to tree.
+
type Perm_Tree (Kind : Path_Kind := Entire_Object) is record
Permission : Perm_Kind;
-- Permission at this level in the path
@@ -103,7 +105,6 @@ package body Sem_SPARK is
-- path.
case Kind is
-
-- An entire object is either a leaf (an object which cannot be
-- extended further in a path) or a subtree in folded form (which
-- could later be unfolded further in another kind of node). The
@@ -111,19 +112,19 @@ package body Sem_SPARK is
-- extension of that node if that permission is different from
-- the node's permission.
- when Entire_Object =>
+ when Entire_Object =>
Children_Permission : Perm_Kind;
-- Unfolded path of access type. The permission of the object
-- pointed to is given in Get_All.
- when Reference =>
+ when Reference =>
Get_All : Perm_Tree_Access;
-- Unfolded path of array type. The permission of the elements is
-- given in Get_Elem.
- when Array_Component =>
+ when Array_Component =>
Get_Elem : Perm_Tree_Access;
-- Unfolded path of record type. The permission of the regular
@@ -229,7 +230,7 @@ package body Sem_SPARK is
--------------------
procedure Perm_Mismatch
- (Exp_Perm, Act_Perm : Perm_Kind;
+ (Exp_Perm, Act_Perm : Perm_Kind;
N : Node_Id);
-- Issues a continuation error message about a mismatch between a
-- desired permission Exp_Perm and a permission obtained Act_Perm. N
@@ -243,10 +244,7 @@ package body Sem_SPARK is
-- Children_Permission --
-------------------------
- function Children_Permission
- (T : Perm_Tree_Access)
- return Perm_Kind
- is
+ function Children_Permission (T : Perm_Tree_Access) return Perm_Kind is
begin
return T.all.Tree.Children_Permission;
end Children_Permission;
@@ -257,7 +255,7 @@ package body Sem_SPARK is
function Component
(T : Perm_Tree_Access)
- return Perm_Tree_Maps.Instance
+ return Perm_Tree_Maps.Instance
is
begin
return T.all.Tree.Component;
@@ -267,13 +265,10 @@ package body Sem_SPARK is
-- Copy_Env --
--------------
- procedure Copy_Env
- (From : Perm_Env;
- To : in out Perm_Env)
- is
+ procedure Copy_Env (From : Perm_Env; To : in out Perm_Env) is
Comp_From : Perm_Tree_Access;
- Key_From : Perm_Tree_Maps.Key_Option;
- Son : Perm_Tree_Access;
+ Key_From : Perm_Tree_Maps.Key_Option;
+ Son : Perm_Tree_Access;
begin
Reset (To);
@@ -296,7 +291,7 @@ package body Sem_SPARK is
procedure Copy_Init_Map
(From : Initialization_Map;
- To : in out Initialization_Map)
+ To : in out Initialization_Map)
is
Comp_From : Boolean;
Key_From : Boolean_Variables_Maps.Key_Option;
@@ -315,25 +310,19 @@ package body Sem_SPARK is
-- Copy_Tree --
---------------
- procedure Copy_Tree
- (From : Perm_Tree_Access;
- To : Perm_Tree_Access)
- is
+ procedure Copy_Tree (From : Perm_Tree_Access; To : Perm_Tree_Access) is
begin
To.all := From.all;
-
case Kind (From) is
when Entire_Object =>
null;
when Reference =>
To.all.Tree.Get_All := new Perm_Tree_Wrapper;
-
Copy_Tree (Get_All (From), Get_All (To));
when Array_Component =>
To.all.Tree.Get_Elem := new Perm_Tree_Wrapper;
-
Copy_Tree (Get_Elem (From), Get_Elem (To));
when Record_Component =>
@@ -346,31 +335,26 @@ package body Sem_SPARK is
-- We put a new hash table, so that it gets dealiased from the
-- Component (From) hash table.
To.all.Tree.Component := Hash_Table;
-
To.all.Tree.Other_Components :=
new Perm_Tree_Wrapper'(Other_Components (From).all);
-
Copy_Tree (Other_Components (From), Other_Components (To));
-
Key_From := Perm_Tree_Maps.Get_First_Key
(Component (From));
+
while Key_From.Present loop
Comp_From := Perm_Tree_Maps.Get
(Component (From), Key_From.K);
-
pragma Assert (Comp_From /= null);
Son := new Perm_Tree_Wrapper;
-
Copy_Tree (Comp_From, Son);
-
Perm_Tree_Maps.Set
(To.all.Tree.Component, Key_From.K, Son);
-
Key_From := Perm_Tree_Maps.Get_Next_Key
(Component (From));
end loop;
end;
end case;
+
end Copy_Tree;
------------------------------
@@ -402,9 +386,7 @@ package body Sem_SPARK is
-- Free_Perm_Tree --
--------------------
- procedure Free_Perm_Tree
- (PT : in out Perm_Tree_Access)
- is
+ procedure Free_Perm_Tree (PT : in out Perm_Tree_Access) is
procedure Free_Perm_Tree_Dealloc is
new Ada.Unchecked_Deallocation
(Perm_Tree_Wrapper, Perm_Tree_Access);
@@ -430,6 +412,7 @@ package body Sem_SPARK is
Free_Perm_Tree (PT.all.Tree.Other_Components);
Comp := Perm_Tree_Maps.Get_First (Component (PT));
while Comp /= null loop
+
-- Free every Component subtree
Free_Perm_Tree (Comp);
@@ -444,10 +427,7 @@ package body Sem_SPARK is
-- Get_All --
-------------
- function Get_All
- (T : Perm_Tree_Access)
- return Perm_Tree_Access
- is
+ function Get_All (T : Perm_Tree_Access) return Perm_Tree_Access is
begin
return T.all.Tree.Get_All;
end Get_All;
@@ -456,10 +436,7 @@ package body Sem_SPARK is
-- Get_Elem --
--------------
- function Get_Elem
- (T : Perm_Tree_Access)
- return Perm_Tree_Access
- is
+ function Get_Elem (T : Perm_Tree_Access) return Perm_Tree_Access is
begin
return T.all.Tree.Get_Elem;
end Get_Elem;
@@ -468,10 +445,7 @@ package body Sem_SPARK is
-- Is_Node_Deep --
------------------
- function Is_Node_Deep
- (T : Perm_Tree_Access)
- return Boolean
- is
+ function Is_Node_Deep (T : Perm_Tree_Access) return Boolean is
begin
return T.all.Tree.Is_Node_Deep;
end Is_Node_Deep;
@@ -480,10 +454,7 @@ package body Sem_SPARK is
-- Kind --
----------
- function Kind
- (T : Perm_Tree_Access)
- return Path_Kind
- is
+ function Kind (T : Perm_Tree_Access) return Path_Kind is
begin
return T.all.Tree.Kind;
end Kind;
@@ -494,7 +465,7 @@ package body Sem_SPARK is
function Other_Components
(T : Perm_Tree_Access)
- return Perm_Tree_Access
+ return Perm_Tree_Access
is
begin
return T.all.Tree.Other_Components;
@@ -504,10 +475,7 @@ package body Sem_SPARK is
-- Permission --
----------------
- function Permission
- (T : Perm_Tree_Access)
- return Perm_Kind
- is
+ function Permission (T : Perm_Tree_Access) return Perm_Kind is
begin
return T.all.Tree.Permission;
end Permission;
@@ -516,13 +484,10 @@ package body Sem_SPARK is
-- Perm_Mismatch --
-------------------
- procedure Perm_Mismatch
- (Exp_Perm, Act_Perm : Perm_Kind;
- N : Node_Id)
- is
+ procedure Perm_Mismatch (Exp_Perm, Act_Perm : Perm_Kind; N : Node_Id) is
begin
- Error_Msg_N ("\expected at least `"
- & Perm_Kind'Image (Exp_Perm) & "`, got `"
+ Error_Msg_N ("\expected state `"
+ & Perm_Kind'Image (Exp_Perm) & "` at least, got `"
& Perm_Kind'Image (Act_Perm) & "`", N);
end Perm_Mismatch;
@@ -543,34 +508,29 @@ package body Sem_SPARK is
-- Default mode. Checks that paths have Read_Perm permission.
Move,
- -- Regular moving semantics (not under 'Access). Checks that paths have
- -- Read_Write permission. After moving a path, its permission is set to
- -- Write_Only and the permission of its extensions is set to No_Access.
+ -- Regular moving semantics. Checks that paths have
+ -- Unrestricted permission. After moving a path, its permission is set
+ -- to Unrestricted and the permission of its extensions is set
+ -- to Unrestricted.
Assign,
-- Used for the target of an assignment, or an actual parameter with
- -- mode OUT. Checks that paths have Write_Perm permission. After
- -- assigning to a path, its permission is set to Read_Write.
-
- Super_Move,
- -- Enhanced moving semantics (under 'Access). Checks that paths have
- -- Read_Write permission (shallow types may have only Write permission).
- -- After moving a path, its permission is set to No_Access, as well as
- -- the permission of its extensions and the permission of its prefixes
- -- up to the first Reference node.
-
- Borrow_Out,
- -- Used for actual OUT parameters. Checks that paths have Write_Perm
- -- permission. After checking a path, its permission is set to Read_Only
- -- when of a by-copy type, to No_Access otherwise. After the call, its
- -- permission is set to Read_Write.
+ -- mode OUT. Checks that paths have Unrestricted permission. After
+ -- assigning to a path, its permission is set to Unrestricted.
+
+ Borrow,
+ -- Used for the source of an assignement when initializes a stand alone
+ -- object of anonymous type, constant, or IN parameter and also OUT
+ -- or IN OUT composite object.
+ -- In the borrowed state, the access object is completely "dead".
Observe
-- Used for actual IN parameters of a scalar type. Checks that paths
-- have Read_Perm permission. After checking a path, its permission
- -- is set to Read_Only.
+ -- is set to Observed.
--
-- Also used for formal IN parameters
+
);
type Result_Kind is (Folded, Unfolded, Function_Call);
@@ -593,11 +553,6 @@ package body Sem_SPARK is
-- Local subprograms --
-----------------------
- function "<=" (P1, P2 : Perm_Kind) return Boolean;
- function ">=" (P1, P2 : Perm_Kind) return Boolean;
- function Glb (P1, P2 : Perm_Kind) return Perm_Kind;
- function Lub (P1, P2 : Perm_Kind) return Perm_Kind;
-
-- Checking proceduress for safe pointer usage. These procedures traverse
-- the AST, check nodes for correct permissions according to SPARK RM
-- 6.4.2, and update permissions depending on the node kind.
@@ -608,24 +563,15 @@ package body Sem_SPARK is
-- We are not in End_Of_Callee mode, hence we will save the environment
-- and start from a new one. We will add in the environment all formal
-- parameters as well as global used during the subprogram, with the
- -- appropriate permissions (write-only for out, read-only for observed,
- -- read-write for others).
- --
- -- After that we analyze the body of the function, and finaly, we check
- -- that each borrowed parameter and global has read-write permission. We
- -- then clean up the environment and put back the saved environment.
+ -- appropriate permissions (unrestricted for borrowed and moved, observed
+ -- for observed names).
procedure Check_Declaration (Decl : Node_Id);
procedure Check_Expression (Expr : Node_Id);
- procedure Check_Globals (N : Node_Id; Check_Mode : Checking_Mode);
- -- This procedure takes a global pragma and checks depending on mode:
- -- Mode Read: every in global is readable
- -- Mode Observe: same as Check_Param_Observes but on globals
- -- Mode Borrow_Out: Check_Param_Outs for globals
- -- Mode Move: Check_Param for globals with mode Read
- -- Mode Assign: Check_Param for globals with mode Assign
+ procedure Check_Globals (N : Node_Id);
+ -- This procedure takes a global pragma and checks it
procedure Check_List (L : List_Id);
-- Calls Check_Node on each element of the list
@@ -638,25 +584,15 @@ package body Sem_SPARK is
procedure Check_Package_Body (Pack : Node_Id);
- procedure Check_Param (Formal : Entity_Id; Actual : Node_Id);
- -- This procedure takes a formal and an actual parameter and calls the
- -- analyze node if the parameter is borrowed with mode in out, with the
- -- appropriate Checking_Mode (Move).
-
- procedure Check_Param_Observes (Formal : Entity_Id; Actual : Node_Id);
- -- This procedure takes a formal and an actual parameter and calls
- -- the analyze node if the parameter is observed, with the appropriate
- -- Checking_Mode.
-
- procedure Check_Param_Outs (Formal : Entity_Id; Actual : Node_Id);
- -- This procedure takes a formal and an actual parameter and calls the
- -- analyze node if the parameter is of mode out, with the appropriate
- -- Checking_Mode.
+ procedure Check_Param_In (Formal : Entity_Id; Actual : Node_Id);
+ -- This procedure takes a formal and an actual parameter and checks the
+ -- permission of every in-mode parameter. This includes Observing and
+ -- Borrowing.
- procedure Check_Param_Read (Formal : Entity_Id; Actual : Node_Id);
+ procedure Check_Param_Out (Formal : Entity_Id; Actual : Node_Id);
-- This procedure takes a formal and an actual parameter and checks the
- -- readability of every in-mode parameter. This includes observed in, and
- -- also borrowed in, that are then checked afterwards.
+ -- state of every out-mode and in out-mode parameter. This includes
+ -- Moving and Borrowing.
procedure Check_Statement (Stmt : Node_Id);
@@ -674,20 +610,6 @@ package body Sem_SPARK is
-- appropriate subtree for that Node_Id. If the tree is folded, then
-- it unrolls the tree up to the appropriate level.
- function Has_Alias
- (N : Node_Id)
- return Boolean;
- -- Function that returns whether the path given as parameter contains an
- -- extension that is declared as aliased.
-
- function Has_Array_Component (N : Node_Id) return Boolean;
- -- This function gets a Node_Id and looks recursively to find if the given
- -- path has any array component.
-
- function Has_Function_Component (N : Node_Id) return Boolean;
- -- This function gets a Node_Id and looks recursively to find if the given
- -- path has any function component.
-
procedure Hp (P : Perm_Env);
-- A procedure that outputs the hash table. This function is used only in
-- the debugger to look into a hash table.
@@ -698,28 +620,13 @@ package body Sem_SPARK is
-- A procedure that is called when deep globals or aliased globals are used
-- without any global aspect.
- function Is_Borrowed_In (E : Entity_Id) return Boolean;
- -- Function that tells if the given entity is a borrowed in a formal
- -- parameter, that is, if it is an access-to-variable type.
-
function Is_Deep (E : Entity_Id) return Boolean;
-- A function that can tell if a type is deep or not. Returns true if the
-- type passed as argument is deep.
- function Is_Shallow (E : Entity_Id) return Boolean;
- -- A function that can tell if a type is shallow or not. Returns true if
- -- the type passed as argument is shallow.
-
- function Loop_Of_Exit (N : Node_Id) return Entity_Id;
- -- A function that takes an exit statement node and returns the entity of
- -- the loop that this statement is exiting from.
-
- procedure Merge_Envs (Target : in out Perm_Env; Source : in out Perm_Env);
- -- Merge Target and Source into Target, and then deallocate the Source
-
procedure Perm_Error
- (N : Node_Id;
- Perm : Perm_Kind;
+ (N : Node_Id;
+ Perm : Perm_Kind;
Found_Perm : Perm_Kind);
-- A procedure that is called when the permissions found contradict the
-- rules established by the RM. This function is called with the node, its
@@ -742,7 +649,7 @@ package body Sem_SPARK is
procedure Return_Declarations (L : List_Id);
-- Check correct permissions on every declared object at the end of a
-- callee. Used at the end of the body of a callable entity. Checks that
- -- paths of all borrowed formal parameters and global have Read_Write
+ -- paths of all borrowed formal parameters and global have Unrestricted
-- permission.
procedure Return_Globals (Subp : Entity_Id);
@@ -750,65 +657,32 @@ package body Sem_SPARK is
-- of the subprogram indeed have RW permission at the end of the subprogram
-- execution.
- procedure Return_Parameter_Or_Global
- (Id : Entity_Id;
- Mode : Formal_Kind;
- Subp : Entity_Id;
- Global_Var : Boolean);
- -- Auxiliary procedure to Return_Parameters and Return_Globals
-
- procedure Return_Parameters (Subp : Entity_Id);
- -- Takes a subprogram as input, and checks that all borrowed parameters of
- -- the subprogram indeed have RW permission at the end of the subprogram
- -- execution.
+ procedure Return_The_Global
+ (Id : Entity_Id;
+ Mode : Formal_Kind;
+ Subp : Entity_Id);
+ -- Auxiliary procedure to Return_Globals
+ -- There is no need to return parameters because they will be reassigned
+ -- their state once the subprogram returns. Local variables that have
+ -- borrowed, observed, or moved an actual parameter go out of the scope.
procedure Set_Perm_Extensions (T : Perm_Tree_Access; P : Perm_Kind);
-- This procedure takes an access to a permission tree and modifies the
-- tree so that any strict extensions of the given tree become of the
-- access specified by parameter P.
- procedure Set_Perm_Extensions_Move (T : Perm_Tree_Access; E : Entity_Id);
- -- Set permissions to
- -- No for any extension with more .all
- -- W for any deep extension with same number of .all
- -- RW for any shallow extension with same number of .all
-
- function Set_Perm_Prefixes_Assign (N : Node_Id) return Perm_Tree_Access;
- -- This function takes a name as an input and sets in the permission
- -- tree the given permission to the given name. The general rule here is
- -- that everybody updates the permission of the subtree it is returning.
- -- The permission of the assigned path has been set to RW by the caller.
- --
- -- Case where we have to normalize a tree after the correct permissions
- -- have been assigned already. We look for the right subtree at the given
- -- path, actualize its permissions, and then call the normalization on its
- -- parent.
- --
- -- Example: We assign x.y and x.z then during Set_Perm_Prefixes_Move will
- -- change the permission of x to RW because all of its components have
- -- permission have permission RW.
-
- function Set_Perm_Prefixes_Borrow_Out (N : Node_Id) return Perm_Tree_Access;
+ function Set_Perm_Prefixes_Borrow (N : Node_Id) return Perm_Tree_Access;
-- This function modifies the permissions of a given node_id in the
-- permission environment as well as in all the prefixes of the path,
-- given that the path is borrowed with mode out.
- function Set_Perm_Prefixes_Move
- (N : Node_Id; Mode : Checking_Mode)
+ function Set_Perm_Prefixes
+ (N : Node_Id;
+ New_Perm : Perm_Kind)
return Perm_Tree_Access;
- pragma Precondition (Mode = Move or Mode = Super_Move);
- -- Given a node and a mode (that can be either Move or Super_Move), this
- -- function modifies the permissions of a given node_id in the permission
- -- environment as well as all the prefixes of the path, given that the path
- -- is moved with or without 'Access. The general rule here is everybody
- -- updates the permission of the subtree they are returning.
- --
- -- This case describes a move either under 'Access or without 'Access.
-
- function Set_Perm_Prefixes_Observe (N : Node_Id) return Perm_Tree_Access;
- -- This function modifies the permissions of a given node_id in the
- -- permission environment as well as all the prefixes of the path,
- -- given that the path is observed.
+ -- This function sets the permissions of a given node_id in the
+ -- permission environment as well as in all the prefixes of the path
+ -- to the one given in parameter (P).
procedure Setup_Globals (Subp : Entity_Id);
-- Takes a subprogram as input, and sets up the environment by adding
@@ -824,6 +698,15 @@ package body Sem_SPARK is
-- Takes a subprogram as input, and sets up the environment by adding
-- formal parameters with appropriate permissions.
+ function Has_Ownership_Aspect_True
+ (N : Node_Id;
+ Msg : String)
+ return Boolean;
+ -- Takes a node as an input, and finds out whether it has ownership aspect
+ -- True or False. This function is recursive whenever the node has a
+ -- composite type. Access-to-objects have ownership aspect False if they
+ -- have a general access type.
+
----------------------
-- Global Variables --
----------------------
@@ -861,31 +744,6 @@ package body Sem_SPARK is
-- after declaration. Hence we can exclude from analysis variables that
-- are just declared and never accessed, typically at package declaration.
- ----------
- -- "<=" --
- ----------
-
- function "<=" (P1, P2 : Perm_Kind) return Boolean
- is
- begin
- return P2 >= P1;
- end "<=";
-
- ----------
- -- ">=" --
- ----------
-
- function ">=" (P1, P2 : Perm_Kind) return Boolean
- is
- begin
- case P2 is
- when No_Access => return True;
- when Read_Only => return P1 in Read_Perm;
- when Write_Only => return P1 in Write_Perm;
- when Read_Write => return P1 = Read_Write;
- end case;
- end ">=";
-
--------------------------
-- Check_Call_Statement --
--------------------------
@@ -893,64 +751,40 @@ package body Sem_SPARK is
procedure Check_Call_Statement (Call : Node_Id) is
Saved_Env : Perm_Env;
- procedure Iterate_Call is new
- Iterate_Call_Parameters (Check_Param);
- procedure Iterate_Call_Observes is new
- Iterate_Call_Parameters (Check_Param_Observes);
- procedure Iterate_Call_Outs is new
- Iterate_Call_Parameters (Check_Param_Outs);
- procedure Iterate_Call_Read is new
- Iterate_Call_Parameters (Check_Param_Read);
+ procedure Iterate_Call_In is new
+ Iterate_Call_Parameters (Check_Param_In);
+ procedure Iterate_Call_Out is new
+ Iterate_Call_Parameters (Check_Param_Out);
begin
-- Save environment, so that the modifications done by analyzing the
-- parameters are not kept at the end of the call.
- Copy_Env (Current_Perm_Env,
- Saved_Env);
-
- -- We first check the Read access on every in parameter
-
- Current_Checking_Mode := Read;
- Iterate_Call_Read (Call);
- Check_Globals (Get_Pragma
- (Get_Called_Entity (Call), Pragma_Global), Read);
-
- -- We first observe, then borrow with mode out, and then with other
- -- modes. This ensures that we do not have to check for by-copy types
- -- specially, because we read them before borrowing them.
- Iterate_Call_Observes (Call);
- Check_Globals (Get_Pragma
- (Get_Called_Entity (Call), Pragma_Global),
- Observe);
+ Copy_Env (Current_Perm_Env, Saved_Env);
- Iterate_Call_Outs (Call);
- Check_Globals (Get_Pragma
- (Get_Called_Entity (Call), Pragma_Global),
- Borrow_Out);
+ -- We first check the globals then parameters to handle the
+ -- No_Parameter_Aliasing Restriction. An out or in-out global is
+ -- considered as borrowing while a parameter with the same mode is
+ -- a move. This order disallow passing a part of a variable to a
+ -- subprogram if it is referenced as a global by the callable (when
+ -- writable).
+ -- For paremeters, we fisrt check in parameters and then the out ones.
+ -- This is to avoid Observing or Borrowing objects that are already
+ -- moved. This order is not mandatory but allows to catch runtime
+ -- errors like null pointer dereferencement at the analysis time.
- Iterate_Call (Call);
- Check_Globals (Get_Pragma
- (Get_Called_Entity (Call), Pragma_Global), Move);
+ Current_Checking_Mode := Read;
+ Check_Globals (Get_Pragma (Get_Called_Entity (Call), Pragma_Global));
+ Iterate_Call_In (Call);
+ Iterate_Call_Out (Call);
-- Restore environment, because after borrowing/observing actual
-- parameters, they get their permission reverted to the ones before
-- the call.
Free_Env (Current_Perm_Env);
-
- Copy_Env (Saved_Env,
- Current_Perm_Env);
-
+ Copy_Env (Saved_Env, Current_Perm_Env);
Free_Env (Saved_Env);
-
- -- We assign the out parameters (necessarily borrowed per RM)
- Current_Checking_Mode := Assign;
- Iterate_Call (Call);
- Check_Globals (Get_Pragma
- (Get_Called_Entity (Call), Pragma_Global),
- Assign);
-
end Check_Call_Statement;
-------------------------
@@ -959,15 +793,12 @@ package body Sem_SPARK is
procedure Check_Callable_Body (Body_N : Node_Id) is
- Mode_Before : constant Checking_Mode := Current_Checking_Mode;
-
- Saved_Env : Perm_Env;
+ Mode_Before : constant Checking_Mode := Current_Checking_Mode;
+ Saved_Env : Perm_Env;
Saved_Init_Map : Initialization_Map;
-
- New_Env : Perm_Env;
-
- Body_Id : constant Entity_Id := Defining_Entity (Body_N);
- Spec_Id : constant Entity_Id := Unique_Entity (Body_Id);
+ New_Env : Perm_Env;
+ Body_Id : constant Entity_Id := Defining_Entity (Body_N);
+ Spec_Id : constant Entity_Id := Unique_Entity (Body_Id);
begin
-- Check if SPARK pragma is not set to Off
@@ -989,9 +820,8 @@ package body Sem_SPARK is
-- Save initialization map
Copy_Init_Map (Current_Initialization_Map, Saved_Init_Map);
-
Current_Checking_Mode := Read;
- Current_Perm_Env := New_Env;
+ Current_Perm_Env := New_Env;
-- Add formals and globals to the environment with adequate permissions
@@ -1010,23 +840,18 @@ package body Sem_SPARK is
if Ekind_In (Spec_Id, E_Procedure, E_Entry)
and then not No_Return (Spec_Id)
then
- Return_Parameters (Spec_Id);
Return_Globals (Spec_Id);
end if;
-- Free the environments
Free_Env (Current_Perm_Env);
-
- Copy_Env (Saved_Env,
- Current_Perm_Env);
-
+ Copy_Env (Saved_Env, Current_Perm_Env);
Free_Env (Saved_Env);
-- Restore initialization map
Copy_Init_Map (Saved_Init_Map, Current_Initialization_Map);
-
Reset (Saved_Init_Map);
-- The assignment of all out parameters will be done by caller
@@ -1039,51 +864,248 @@ package body Sem_SPARK is
-----------------------
procedure Check_Declaration (Decl : Node_Id) is
+
+ Target_Ent : constant Entity_Id := Defining_Identifier (Decl);
+ Target_Typ : Node_Id renames Etype (Target_Ent);
+ Check : Boolean := True;
begin
case N_Declaration'(Nkind (Decl)) is
when N_Full_Type_Declaration =>
+ if not Has_Ownership_Aspect_True (Target_Ent, "type declaration")
+ then
+ Check := False;
+ end if;
- -- Nothing to do here ??? NOT TRUE IF CONSTRAINT ON TYPE
-
- null;
+ -- ??? What about component declarations with defaults.
when N_Object_Declaration =>
+ if (Is_Access_Type (Target_Typ)
+ or else Is_Deep (Target_Typ))
+ and then not Has_Ownership_Aspect_True
+ (Target_Ent, "Object declaration ")
+ then
+ Check := False;
+ end if;
+
+ if Is_Anonymous_Access_Type (Target_Typ)
+ and then not Present (Expression (Decl))
+ then
+
+ -- ??? Check the case of default value (AI)
+ -- ??? How an anonymous access type can be with default exp?
+
+ Error_Msg_NE ("? object declaration & has OAF (Anonymous "
+ & "access-to-object with no initialization)",
+ Decl, Target_Ent);
+
+ -- If it it an initialization
+
+ elsif Present (Expression (Decl)) and Check then
+
+ -- Find out the operation to be done on the right-hand side
+
+ -- Initializing object, access type
+
+ if Is_Access_Type (Target_Typ) then
+
+ -- Initializing object, constant access type
- -- First move the right-hand side
+ if Is_Constant_Object (Target_Ent) then
- Current_Checking_Mode := Move;
- Check_Node (Expression (Decl));
+ -- Initializing object, constant access to variable type
+
+ if not Is_Access_Constant (Target_Typ) then
+ Current_Checking_Mode := Borrow;
+
+ -- Initializing object, constant access to constant type
+
+ -- Initializing object,
+ -- constant access to constant anonymous type.
+
+ elsif Is_Anonymous_Access_Type (Target_Typ) then
+
+ -- This is an object declaration so the target
+ -- of the assignement is a stand-alone object.
+
+ Current_Checking_Mode := Observe;
+
+ -- Initializing object, constant access to constant
+ -- named type.
+
+ else
+ -- If named then it is a general access type
+ -- Hence, Has_Ownership_Aspec_True is False.
+
+ raise Program_Error;
+ end if;
+
+ -- Initializing object, variable access type
+
+ else
+ -- Initializing object, variable access to variable type
+
+ if not Is_Access_Constant (Target_Typ) then
+
+ -- Initializing object, variable named access to
+ -- variable type.
+
+ if not Is_Anonymous_Access_Type (Target_Typ) then
+ Current_Checking_Mode := Move;
+
+ -- Initializing object, variable anonymous access to
+ -- variable type.
+
+ else
+ -- This is an object declaration so the target
+ -- object of the assignement is a stand-alone
+ -- object.
+
+ Current_Checking_Mode := Borrow;
+ end if;
+
+ -- Initializing object, variable access to constant type
+
+ else
+ -- Initializing object,
+ -- variable named access to constant type.
+
+ if not Is_Anonymous_Access_Type (Target_Typ) then
+ Error_Msg_N ("assignment not allowed, Ownership "
+ & "Aspect False (Anonymous Access "
+ & "Object)", Decl);
+ Check := False;
+
+ -- Initializing object,
+ -- variable anonymous access to constant type.
+
+ else
+ -- This is an object declaration so the target
+ -- of the assignement is a stand-alone object.
+
+ Current_Checking_Mode := Observe;
+ end if;
+ end if;
+ end if;
+
+ -- Initializing object, composite (deep) type
+
+ elsif Is_Deep (Target_Typ) then
+
+ -- Initializing object, constant composite type
+
+ if Is_Constant_Object (Target_Ent) then
+ Current_Checking_Mode := Observe;
+
+ -- Initializing object, variable composite type
+
+ else
+
+ -- Initializing object, variable anonymous composite type
+
+ if Nkind (Object_Definition (Decl)) =
+ N_Constrained_Array_Definition
+
+ -- An N_Constrained_Array_Definition is an anonymous
+ -- array (to be checked). Record types are always
+ -- named and are considered in the else part.
+
+ then
+ declare
+ Com_Ty : constant Node_Id :=
+ Component_Type (Etype (Target_Typ));
+ begin
+
+ if Is_Access_Type (Com_Ty) then
+
+ -- If components are of anonymous type
+
+ if Is_Anonymous_Access_Type (Com_Ty) then
+ if Is_Access_Constant (Com_Ty) then
+ Current_Checking_Mode := Observe;
+
+ else
+ Current_Checking_Mode := Borrow;
+ end if;
+
+ else
+ Current_Checking_Mode := Move;
+ end if;
+
+ elsif Is_Deep (Com_Ty) then
+
+ -- This is certainly named so it is a move
+
+ Current_Checking_Mode := Move;
+ end if;
+ end;
+
+ else
+ Current_Checking_Mode := Move;
+ end if;
+ end if;
+
+ elsif Nkind_In (Expression (Decl),
+ N_Attribute_Reference,
+ N_Attribute_Reference,
+ N_Expanded_Name,
+ N_Explicit_Dereference,
+ N_Indexed_Component,
+ N_Reference,
+ N_Selected_Component,
+ N_Slice)
+ then
+ if Is_Access_Type (Etype (Prefix (Expression (Decl))))
+ or else Is_Deep (Etype (Prefix (Expression (Decl))))
+ then
+ Current_Checking_Mode := Observe;
+ Check := True;
+ end if;
+ end if;
+ end if;
+
+ if Check then
+ Check_Node (Expression (Decl));
+ end if;
+
+ -- If lhs is not a pointer, we still give it the appropriate
+ -- state which is useless but not harmful.
declare
- Deep : constant Boolean :=
- Is_Deep (Etype (Defining_Identifier (Decl)));
Elem : Perm_Tree_Access;
+ Deep : constant Boolean := Is_Deep (Target_Typ);
begin
- Elem := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Deep,
- Permission => Read_Write,
- Children_Permission => Read_Write));
-
- -- If unitialized declaration, then set to Write_Only. If a
- -- pointer declaration, it has a null default initialization.
-
- if No (Expression (Decl))
- and then not Has_Full_Default_Initialization
- (Etype (Defining_Identifier (Decl)))
- and then not Is_Access_Type
- (Etype (Defining_Identifier (Decl)))
-
- -- Objects of shallow types are considered as always
- -- initialized, leaving the checking of initialization to
- -- flow analysis.
-
- and then Deep
- then
- Elem.all.Tree.Permission := Write_Only;
- Elem.all.Tree.Children_Permission := Write_Only;
+ -- Note that all declared variables are set to the unrestricted
+ -- state.
+ --
+ -- If variables are not initialized:
+ -- unrestricted to every declared object.
+ -- Exp:
+ -- R : Rec
+ -- S : Rec := (...)
+ -- R := S
+ -- The assignement R := S is not allowed in the new rules
+ -- if R is not unrestricted.
+ --
+ -- If variables are initialized:
+ -- If it is a move, then the target is unrestricted
+ -- If it is a borrow, then the target is unrestricted
+ -- If it is an observe, then the target should be observed
+
+ if Current_Checking_Mode = Observe then
+ Elem := new Perm_Tree_Wrapper'
+ (Tree =>
+ (Kind => Entire_Object,
+ Is_Node_Deep => Deep,
+ Permission => Observed,
+ Children_Permission => Observed));
+ else
+ Elem := new Perm_Tree_Wrapper'
+ (Tree =>
+ (Kind => Entire_Object,
+ Is_Node_Deep => Deep,
+ Permission => Unrestricted,
+ Children_Permission => Unrestricted));
end if;
-- Create new tree for defining identifier
@@ -1091,7 +1113,6 @@ package body Sem_SPARK is
Set (Current_Perm_Env,
Unique_Entity (Defining_Identifier (Decl)),
Elem);
-
pragma Assert (Get_First (Current_Perm_Env) /= null);
end;
@@ -1099,19 +1120,17 @@ package body Sem_SPARK is
Check_Node (Subtype_Indication (Decl));
when N_Iterator_Specification =>
- pragma Assert (Is_Shallow (Etype (Defining_Identifier (Decl))));
null;
when N_Loop_Parameter_Specification =>
- pragma Assert (Is_Shallow (Etype (Defining_Identifier (Decl))));
null;
-- Checking should not be called directly on these nodes
- when N_Component_Declaration
- | N_Function_Specification
+ when N_Function_Specification
| N_Entry_Declaration
| N_Procedure_Specification
+ | N_Component_Declaration
=>
raise Program_Error;
@@ -1141,29 +1160,33 @@ package body Sem_SPARK is
Mode_Before : constant Checking_Mode := Current_Checking_Mode;
begin
case N_Subexpr'(Nkind (Expr)) is
- when N_Procedure_Call_Statement =>
+ when N_Procedure_Call_Statement
+ | N_Function_Call
+ =>
Check_Call_Statement (Expr);
when N_Identifier
| N_Expanded_Name
=>
-- Check if identifier is pointing to nothing (On/Off/...)
+
if not Present (Entity (Expr)) then
return;
end if;
-- Do not analyze things that are not of object Kind
+
if Ekind (Entity (Expr)) not in Object_Kind then
return;
end if;
-- Consider as ident
+
Process_Path (Expr);
-- Switch to read mode and then check the readability of each operand
when N_Binary_Op =>
-
Current_Checking_Mode := Read;
Check_Node (Left_Opnd (Expr));
Check_Node (Right_Opnd (Expr));
@@ -1175,7 +1198,6 @@ package body Sem_SPARK is
| N_Op_Not
| N_Op_Plus
=>
- pragma Assert (Is_Shallow (Etype (Expr)));
Current_Checking_Mode := Read;
Check_Node (Right_Opnd (Expr));
@@ -1184,32 +1206,7 @@ package body Sem_SPARK is
when N_Attribute_Reference =>
case Attribute_Name (Expr) is
when Name_Access =>
- case Current_Checking_Mode is
- when Read =>
- Check_Node (Prefix (Expr));
-
- when Move =>
- Current_Checking_Mode := Super_Move;
- Check_Node (Prefix (Expr));
-
- -- Only assign names, not expressions
-
- when Assign =>
- raise Program_Error;
-
- -- Prefix in Super_Move should be a name, error here
-
- when Super_Move =>
- raise Program_Error;
-
- -- Could only borrow names of mode out, not n'Access
-
- when Borrow_Out =>
- raise Program_Error;
-
- when Observe =>
- Check_Node (Prefix (Expr));
- end case;
+ Error_Msg_N ("access attribute not allowed in SPARK", Expr);
when Name_Last
| Name_First
@@ -1239,7 +1236,7 @@ package body Sem_SPARK is
Check_Node (Prefix (Expr));
when Name_Pred
- | Name_Succ
+ | Name_Succ
=>
Check_List (Expressions (Expr));
Check_Node (Prefix (Expr));
@@ -1254,12 +1251,12 @@ package body Sem_SPARK is
-- analysis.
when Name_Address
- | Name_Alignment
- | Name_Component_Size
- | Name_First_Bit
- | Name_Last_Bit
- | Name_Size
- | Name_Position
+ | Name_Alignment
+ | Name_Component_Size
+ | Name_First_Bit
+ | Name_Last_Bit
+ | Name_Size
+ | Name_Position
=>
null;
@@ -1270,7 +1267,6 @@ package body Sem_SPARK is
| Name_Val
=>
null;
-
-- Other attributes that fall out of the scope of the analysis
when others =>
@@ -1292,17 +1288,12 @@ package body Sem_SPARK is
when N_And_Then
| N_Or_Else
=>
- pragma Assert (Is_Shallow (Etype (Expr)));
Current_Checking_Mode := Read;
Check_Node (Left_Opnd (Expr));
Check_Node (Right_Opnd (Expr));
-- Check the arguments of the call
- when N_Function_Call =>
- Current_Checking_Mode := Read;
- Check_List (Parameter_Associations (Expr));
-
when N_Explicit_Dereference =>
Process_Path (Expr);
@@ -1315,20 +1306,16 @@ package body Sem_SPARK is
-- Accumulator for the different branches
New_Env : Perm_Env;
-
- Elmt : Node_Id := First (Expressions (Expr));
+ Elmt : Node_Id := First (Expressions (Expr));
begin
Current_Checking_Mode := Read;
-
Check_Node (Elmt);
-
Current_Checking_Mode := Mode_Before;
-- Save environment
- Copy_Env (Current_Perm_Env,
- Saved_Env);
+ Copy_Env (Current_Perm_Env, Saved_Env);
-- Here we have the original env in saved, current with a fresh
-- copy, and new aliased.
@@ -1341,15 +1328,10 @@ package body Sem_SPARK is
-- Here the new_environment contains curr env after then block
-- ELSE part
-
-- Restore environment before if
- Copy_Env (Current_Perm_Env,
- New_Env);
-
+ Copy_Env (Current_Perm_Env, New_Env);
Free_Env (Current_Perm_Env);
-
- Copy_Env (Saved_Env,
- Current_Perm_Env);
+ Copy_Env (Saved_Env, Current_Perm_Env);
-- Here new environment contains the environment after then and
-- current the fresh copy of old one.
@@ -1357,14 +1339,9 @@ package body Sem_SPARK is
Next (Elmt);
Check_Node (Elmt);
- Merge_Envs (New_Env,
- Current_Perm_Env);
-
-- CLEANUP
- Copy_Env (New_Env,
- Current_Perm_Env);
-
+ Copy_Env (New_Env, Current_Perm_Env);
Free_Env (New_Env);
Free_Env (Saved_Env);
end;
@@ -1380,6 +1357,7 @@ package body Sem_SPARK is
when N_Quantified_Expression =>
declare
Saved_Env : Perm_Env;
+
begin
Copy_Env (Current_Perm_Env, Saved_Env);
Current_Checking_Mode := Read;
@@ -1391,7 +1369,6 @@ package body Sem_SPARK is
Copy_Env (Saved_Env, Current_Perm_Env);
Free_Env (Saved_Env);
end;
-
-- Analyze the list of associations in the aggregate
when N_Aggregate =>
@@ -1408,19 +1385,16 @@ package body Sem_SPARK is
-- Accumulator for the different branches
New_Env : Perm_Env;
-
Elmt : Node_Id := First (Alternatives (Expr));
begin
Current_Checking_Mode := Read;
Check_Node (Expression (Expr));
-
Current_Checking_Mode := Mode_Before;
-- Save environment
- Copy_Env (Current_Perm_Env,
- Saved_Env);
+ Copy_Env (Current_Perm_Env, Saved_Env);
-- Here we have the original env in saved, current with a fresh
-- copy, and new aliased.
@@ -1429,43 +1403,29 @@ package body Sem_SPARK is
Check_Node (Elmt);
Next (Elmt);
-
- Copy_Env (Current_Perm_Env,
- New_Env);
-
+ Copy_Env (Current_Perm_Env, New_Env);
Free_Env (Current_Perm_Env);
-- Other alternatives
while Present (Elmt) loop
- -- Restore environment
- Copy_Env (Saved_Env,
- Current_Perm_Env);
+ -- Restore environment
+ Copy_Env (Saved_Env, Current_Perm_Env);
Check_Node (Elmt);
-
- -- Merge Current_Perm_Env into New_Env
-
- Merge_Envs (New_Env,
- Current_Perm_Env);
-
Next (Elmt);
end loop;
-
-- CLEANUP
- Copy_Env (New_Env,
- Current_Perm_Env);
+ Copy_Env (Saved_Env, Current_Perm_Env);
Free_Env (New_Env);
Free_Env (Saved_Env);
end;
-
-- Analyze the list of associates in the aggregate as well as the
-- ancestor part.
when N_Extension_Aggregate =>
-
Check_Node (Ancestor_Part (Expr));
Check_List (Expressions (Expr));
@@ -1507,7 +1467,6 @@ package body Sem_SPARK is
| N_Raise_xxx_Error
=>
null;
-
-- The following nodes are never generated in GNATprove mode
when N_Expression_With_Actions
@@ -1515,7 +1474,6 @@ package body Sem_SPARK is
| N_Unchecked_Expression
=>
raise Program_Error;
-
end case;
end Check_Expression;
@@ -1523,150 +1481,63 @@ package body Sem_SPARK is
-- Check_Globals --
-------------------
- procedure Check_Globals (N : Node_Id; Check_Mode : Checking_Mode) is
+ procedure Check_Globals (N : Node_Id) is
begin
if Nkind (N) = N_Empty then
return;
end if;
declare
- pragma Assert
- (List_Length (Pragma_Argument_Associations (N)) = 1);
-
- PAA : constant Node_Id :=
- First (Pragma_Argument_Associations (N));
+ pragma Assert (List_Length (Pragma_Argument_Associations (N)) = 1);
+ PAA : constant Node_Id := First (Pragma_Argument_Associations (N));
pragma Assert (Nkind (PAA) = N_Pragma_Argument_Association);
-
Row : Node_Id;
The_Mode : Name_Id;
RHS : Node_Id;
- procedure Process (Mode : Name_Id;
- The_Global : Entity_Id);
-
- procedure Process (Mode : Name_Id;
- The_Global : Node_Id)
- is
- Ident_Elt : constant Entity_Id :=
+ procedure Process (Mode : Name_Id; The_Global : Entity_Id);
+ procedure Process (Mode : Name_Id; The_Global : Node_Id) is
+ Ident_Elt : constant Entity_Id :=
Unique_Entity (Entity (The_Global));
-
Mode_Before : constant Checking_Mode := Current_Checking_Mode;
begin
if Ekind (Ident_Elt) = E_Abstract_State then
return;
end if;
-
- case Check_Mode is
- when Read =>
- case Mode is
- when Name_Input
- | Name_Proof_In
- =>
- Check_Node (The_Global);
-
- when Name_Output
- | Name_In_Out
- =>
- null;
-
- when others =>
- raise Program_Error;
-
- end case;
-
- when Observe =>
- case Mode is
- when Name_Input
- | Name_Proof_In
- =>
- if not Is_Borrowed_In (Ident_Elt) then
- -- Observed in
-
- Current_Checking_Mode := Observe;
- Check_Node (The_Global);
- end if;
-
- when others =>
- null;
-
- end case;
-
- when Borrow_Out =>
-
- case Mode is
- when Name_Output =>
- -- Borrowed out
- Current_Checking_Mode := Borrow_Out;
- Check_Node (The_Global);
-
- when others =>
- null;
-
- end case;
-
- when Move =>
- case Mode is
- when Name_Input
- | Name_Proof_In
- =>
- if Is_Borrowed_In (Ident_Elt) then
- -- Borrowed in
-
- Current_Checking_Mode := Move;
- else
- -- Observed
-
- return;
- end if;
-
- when Name_Output =>
- return;
-
- when Name_In_Out =>
- -- Borrowed in out
-
- Current_Checking_Mode := Move;
-
- when others =>
- raise Program_Error;
- end case;
-
+ case Mode is
+ when Name_Input
+ | Name_Proof_In
+ =>
+ Current_Checking_Mode := Observe;
Check_Node (The_Global);
- when Assign =>
- case Mode is
- when Name_Input
- | Name_Proof_In
- =>
- null;
-
- when Name_Output
- | Name_In_Out
- =>
- -- Borrowed out or in out
-
- Process_Path (The_Global);
- when others =>
- raise Program_Error;
- end case;
+ when Name_Output
+ | Name_In_Out
+ =>
+ -- ??? Borrow not Move?
+ Current_Checking_Mode := Borrow;
+ Check_Node (The_Global);
when others =>
raise Program_Error;
end case;
-
Current_Checking_Mode := Mode_Before;
end Process;
begin
if Nkind (Expression (PAA)) = N_Null then
+
-- global => null
-- No globals, nothing to do
+
return;
elsif Nkind_In (Expression (PAA), N_Identifier, N_Expanded_Name) then
+
-- global => foo
-- A single input
+
Process (Name_Input, Expression (PAA));
elsif Nkind (Expression (PAA)) = N_Aggregate
@@ -1674,6 +1545,7 @@ package body Sem_SPARK is
then
-- global => (foo, bar)
-- Inputs
+
RHS := First (Expressions (Expression (PAA)));
while Present (RHS) loop
case Nkind (RHS) is
@@ -1687,7 +1559,6 @@ package body Sem_SPARK is
when others =>
raise Program_Error;
-
end case;
RHS := Next (RHS);
end loop;
@@ -1707,8 +1578,8 @@ package body Sem_SPARK is
while Present (Row) loop
pragma Assert (List_Length (Choices (Row)) = 1);
The_Mode := Chars (First (Choices (Row)));
-
RHS := Expression (Row);
+
case Nkind (RHS) is
when N_Aggregate =>
RHS := First (Expressions (RHS));
@@ -1719,7 +1590,6 @@ package body Sem_SPARK is
when others =>
Process (The_Mode, RHS);
-
end case;
RHS := Next (RHS);
end loop;
@@ -1737,9 +1607,7 @@ package body Sem_SPARK is
when others =>
raise Program_Error;
-
end case;
-
Row := Next (Row);
end loop;
end;
@@ -1770,339 +1638,6 @@ package body Sem_SPARK is
procedure Check_Loop_Statement (Loop_N : Node_Id) is
- -- Local Subprograms
-
- procedure Check_Is_Less_Restrictive_Env
- (Exiting_Env : Perm_Env;
- Entry_Env : Perm_Env);
- -- This procedure checks that the Exiting_Env environment is less
- -- restrictive than the Entry_Env environment.
-
- procedure Check_Is_Less_Restrictive_Tree
- (New_Tree : Perm_Tree_Access;
- Orig_Tree : Perm_Tree_Access;
- E : Entity_Id);
- -- Auxiliary procedure to check that the tree New_Tree is less
- -- restrictive than the tree Orig_Tree for the entity E.
-
- procedure Perm_Error_Loop_Exit
- (E : Entity_Id;
- Loop_Id : Node_Id;
- Perm : Perm_Kind;
- Found_Perm : Perm_Kind);
- -- A procedure that is called when the permissions found contradict
- -- the rules established by the RM at the exit of loops. This function
- -- is called with the entity, the node of the enclosing loop, the
- -- permission that was expected and the permission found, and issues
- -- an appropriate error message.
-
- -----------------------------------
- -- Check_Is_Less_Restrictive_Env --
- -----------------------------------
-
- procedure Check_Is_Less_Restrictive_Env
- (Exiting_Env : Perm_Env;
- Entry_Env : Perm_Env)
- is
- Comp_Entry : Perm_Tree_Maps.Key_Option;
- Iter_Entry, Iter_Exit : Perm_Tree_Access;
-
- begin
- Comp_Entry := Get_First_Key (Entry_Env);
- while Comp_Entry.Present loop
- Iter_Entry := Get (Entry_Env, Comp_Entry.K);
- pragma Assert (Iter_Entry /= null);
- Iter_Exit := Get (Exiting_Env, Comp_Entry.K);
- pragma Assert (Iter_Exit /= null);
- Check_Is_Less_Restrictive_Tree
- (New_Tree => Iter_Exit,
- Orig_Tree => Iter_Entry,
- E => Comp_Entry.K);
- Comp_Entry := Get_Next_Key (Entry_Env);
- end loop;
- end Check_Is_Less_Restrictive_Env;
-
- ------------------------------------
- -- Check_Is_Less_Restrictive_Tree --
- ------------------------------------
-
- procedure Check_Is_Less_Restrictive_Tree
- (New_Tree : Perm_Tree_Access;
- Orig_Tree : Perm_Tree_Access;
- E : Entity_Id)
- is
- -----------------------
- -- Local Subprograms --
- -----------------------
-
- procedure Check_Is_Less_Restrictive_Tree_Than
- (Tree : Perm_Tree_Access;
- Perm : Perm_Kind;
- E : Entity_Id);
- -- Auxiliary procedure to check that the tree N is less restrictive
- -- than the given permission P.
-
- procedure Check_Is_More_Restrictive_Tree_Than
- (Tree : Perm_Tree_Access;
- Perm : Perm_Kind;
- E : Entity_Id);
- -- Auxiliary procedure to check that the tree N is more restrictive
- -- than the given permission P.
-
- -----------------------------------------
- -- Check_Is_Less_Restrictive_Tree_Than --
- -----------------------------------------
-
- procedure Check_Is_Less_Restrictive_Tree_Than
- (Tree : Perm_Tree_Access;
- Perm : Perm_Kind;
- E : Entity_Id)
- is
- begin
- if not (Permission (Tree) >= Perm) then
- Perm_Error_Loop_Exit
- (E, Loop_N, Permission (Tree), Perm);
- end if;
-
- case Kind (Tree) is
- when Entire_Object =>
- if not (Children_Permission (Tree) >= Perm) then
- Perm_Error_Loop_Exit
- (E, Loop_N, Children_Permission (Tree), Perm);
-
- end if;
-
- when Reference =>
- Check_Is_Less_Restrictive_Tree_Than
- (Get_All (Tree), Perm, E);
-
- when Array_Component =>
- Check_Is_Less_Restrictive_Tree_Than
- (Get_Elem (Tree), Perm, E);
-
- when Record_Component =>
- declare
- Comp : Perm_Tree_Access;
- begin
- Comp := Perm_Tree_Maps.Get_First (Component (Tree));
- while Comp /= null loop
- Check_Is_Less_Restrictive_Tree_Than (Comp, Perm, E);
- Comp :=
- Perm_Tree_Maps.Get_Next (Component (Tree));
- end loop;
-
- Check_Is_Less_Restrictive_Tree_Than
- (Other_Components (Tree), Perm, E);
- end;
- end case;
- end Check_Is_Less_Restrictive_Tree_Than;
-
- -----------------------------------------
- -- Check_Is_More_Restrictive_Tree_Than --
- -----------------------------------------
-
- procedure Check_Is_More_Restrictive_Tree_Than
- (Tree : Perm_Tree_Access;
- Perm : Perm_Kind;
- E : Entity_Id)
- is
- begin
- if not (Perm >= Permission (Tree)) then
- Perm_Error_Loop_Exit
- (E, Loop_N, Permission (Tree), Perm);
- end if;
-
- case Kind (Tree) is
- when Entire_Object =>
- if not (Perm >= Children_Permission (Tree)) then
- Perm_Error_Loop_Exit
- (E, Loop_N, Children_Permission (Tree), Perm);
- end if;
-
- when Reference =>
- Check_Is_More_Restrictive_Tree_Than
- (Get_All (Tree), Perm, E);
-
- when Array_Component =>
- Check_Is_More_Restrictive_Tree_Than
- (Get_Elem (Tree), Perm, E);
-
- when Record_Component =>
- declare
- Comp : Perm_Tree_Access;
- begin
- Comp := Perm_Tree_Maps.Get_First (Component (Tree));
- while Comp /= null loop
- Check_Is_More_Restrictive_Tree_Than (Comp, Perm, E);
- Comp :=
- Perm_Tree_Maps.Get_Next (Component (Tree));
- end loop;
-
- Check_Is_More_Restrictive_Tree_Than
- (Other_Components (Tree), Perm, E);
- end;
- end case;
- end Check_Is_More_Restrictive_Tree_Than;
-
- -- Start of processing for Check_Is_Less_Restrictive_Tree
-
- begin
- if not (Permission (New_Tree) <= Permission (Orig_Tree)) then
- Perm_Error_Loop_Exit
- (E => E,
- Loop_Id => Loop_N,
- Perm => Permission (New_Tree),
- Found_Perm => Permission (Orig_Tree));
- end if;
-
- case Kind (New_Tree) is
-
- -- Potentially folded tree. We check the other tree Orig_Tree to
- -- check whether it is folded or not. If folded we just compare
- -- their Permission and Children_Permission, if not, then we
- -- look at the Children_Permission of the folded tree against
- -- the unfolded tree Orig_Tree.
-
- when Entire_Object =>
- case Kind (Orig_Tree) is
- when Entire_Object =>
- if not (Children_Permission (New_Tree) <=
- Children_Permission (Orig_Tree))
- then
- Perm_Error_Loop_Exit
- (E, Loop_N,
- Children_Permission (New_Tree),
- Children_Permission (Orig_Tree));
- end if;
-
- when Reference =>
- Check_Is_More_Restrictive_Tree_Than
- (Get_All (Orig_Tree), Children_Permission (New_Tree), E);
-
- when Array_Component =>
- Check_Is_More_Restrictive_Tree_Than
- (Get_Elem (Orig_Tree), Children_Permission (New_Tree), E);
-
- when Record_Component =>
- declare
- Comp : Perm_Tree_Access;
- begin
- Comp := Perm_Tree_Maps.Get_First
- (Component (Orig_Tree));
- while Comp /= null loop
- Check_Is_More_Restrictive_Tree_Than
- (Comp, Children_Permission (New_Tree), E);
- Comp := Perm_Tree_Maps.Get_Next
- (Component (Orig_Tree));
- end loop;
-
- Check_Is_More_Restrictive_Tree_Than
- (Other_Components (Orig_Tree),
- Children_Permission (New_Tree), E);
- end;
- end case;
-
- when Reference =>
- case Kind (Orig_Tree) is
- when Entire_Object =>
- Check_Is_Less_Restrictive_Tree_Than
- (Get_All (New_Tree), Children_Permission (Orig_Tree), E);
-
- when Reference =>
- Check_Is_Less_Restrictive_Tree
- (Get_All (New_Tree), Get_All (Orig_Tree), E);
-
- when others =>
- raise Program_Error;
- end case;
-
- when Array_Component =>
- case Kind (Orig_Tree) is
- when Entire_Object =>
- Check_Is_Less_Restrictive_Tree_Than
- (Get_Elem (New_Tree), Children_Permission (Orig_Tree), E);
-
- when Array_Component =>
- Check_Is_Less_Restrictive_Tree
- (Get_Elem (New_Tree), Get_Elem (Orig_Tree), E);
-
- when others =>
- raise Program_Error;
- end case;
-
- when Record_Component =>
- declare
- CompN : Perm_Tree_Access;
- begin
- CompN :=
- Perm_Tree_Maps.Get_First (Component (New_Tree));
- case Kind (Orig_Tree) is
- when Entire_Object =>
- while CompN /= null loop
- Check_Is_Less_Restrictive_Tree_Than
- (CompN, Children_Permission (Orig_Tree), E);
-
- CompN :=
- Perm_Tree_Maps.Get_Next (Component (New_Tree));
- end loop;
-
- Check_Is_Less_Restrictive_Tree_Than
- (Other_Components (New_Tree),
- Children_Permission (Orig_Tree),
- E);
-
- when Record_Component =>
- declare
-
- KeyO : Perm_Tree_Maps.Key_Option;
- CompO : Perm_Tree_Access;
- begin
- KeyO := Perm_Tree_Maps.Get_First_Key
- (Component (Orig_Tree));
- while KeyO.Present loop
- pragma Assert (CompO /= null);
-
- Check_Is_Less_Restrictive_Tree (CompN, CompO, E);
-
- KeyO := Perm_Tree_Maps.Get_Next_Key
- (Component (Orig_Tree));
- CompN := Perm_Tree_Maps.Get
- (Component (New_Tree), KeyO.K);
- CompO := Perm_Tree_Maps.Get
- (Component (Orig_Tree), KeyO.K);
- end loop;
-
- Check_Is_Less_Restrictive_Tree
- (Other_Components (New_Tree),
- Other_Components (Orig_Tree),
- E);
- end;
-
- when others =>
- raise Program_Error;
- end case;
- end;
- end case;
- end Check_Is_Less_Restrictive_Tree;
-
- --------------------------
- -- Perm_Error_Loop_Exit --
- --------------------------
-
- procedure Perm_Error_Loop_Exit
- (E : Entity_Id;
- Loop_Id : Node_Id;
- Perm : Perm_Kind;
- Found_Perm : Perm_Kind)
- is
- begin
- Error_Msg_Node_2 := Loop_Id;
- Error_Msg_N ("insufficient permission for & when exiting loop &", E);
- Perm_Mismatch (Exp_Perm => Perm,
- Act_Perm => Found_Perm,
- N => Loop_Id);
- end Perm_Error_Loop_Exit;
-
-- Local variables
Loop_Name : constant Entity_Id := Entity (Identifier (Loop_N));
@@ -2126,6 +1661,7 @@ package body Sem_SPARK is
if Present (Iteration_Scheme (Loop_N)) then
declare
Exit_Env : constant Perm_Env_Access := new Perm_Env;
+
begin
Copy_Env (From => Current_Perm_Env, To => Exit_Env.all);
Set (Current_Loops_Accumulators, Loop_Name, Exit_Env);
@@ -2137,12 +1673,6 @@ package body Sem_SPARK is
Check_Node (Iteration_Scheme (Loop_N));
Check_List (Statements (Loop_N));
- -- Check that environment gets less restrictive at end of loop
-
- Check_Is_Less_Restrictive_Env
- (Exiting_Env => Current_Perm_Env,
- Entry_Env => Loop_Env.all);
-
-- Set environment to the one for exiting the loop
declare
@@ -2208,6 +1738,7 @@ package body Sem_SPARK is
when N_Package_Declaration =>
declare
Spec : constant Node_Id := Specification (N);
+
begin
Current_Checking_Mode := Read;
Check_List (Visible_Declarations (Spec));
@@ -2274,7 +1805,6 @@ package body Sem_SPARK is
| N_Delay_Alternative
| N_Derived_Type_Definition
| N_Designator
- | N_Discriminant_Association
| N_Discriminant_Specification
| N_Elsif_Part
| N_Entry_Body_Formal_Part
@@ -2366,9 +1896,12 @@ package body Sem_SPARK is
| N_Use_Type_Clause
| N_Validate_Unchecked_Conversion
| N_Variable_Reference_Marker
+ | N_Discriminant_Association
+
+ -- ??? check whether we should do sth special for
+ -- N_Discriminant_Association, or maybe raise a program error.
=>
null;
-
-- The following nodes are rewritten by semantic analysis
when N_Single_Protected_Declaration
@@ -2408,15 +1941,12 @@ package body Sem_SPARK is
-- Save environment
- Copy_Env (Current_Perm_Env,
- Saved_Env);
-
+ Copy_Env (Current_Perm_Env, Saved_Env);
Check_List (Private_Declarations (CorSp));
-- Set mode to Read, and then analyze declarations and statements
Current_Checking_Mode := Read;
-
Check_List (Declarations (Pack));
Check_Node (Handled_Statement_Sequence (Pack));
@@ -2430,137 +1960,129 @@ package body Sem_SPARK is
-- declaration) from environment.
Free_Env (Current_Perm_Env);
- Copy_Env (Saved_Env,
- Current_Perm_Env);
+ Copy_Env (Saved_Env, Current_Perm_Env);
end Check_Package_Body;
- -----------------
- -- Check_Param --
- -----------------
+ --------------------
+ -- Check_Param_In --
+ --------------------
- procedure Check_Param (Formal : Entity_Id; Actual : Node_Id) is
+ procedure Check_Param_In (Formal : Entity_Id; Actual : Node_Id) is
Mode : constant Entity_Kind := Ekind (Formal);
Mode_Before : constant Checking_Mode := Current_Checking_Mode;
-
begin
- case Current_Checking_Mode is
- when Read =>
- case Formal_Kind'(Mode) is
- when E_In_Parameter =>
- if Is_Borrowed_In (Formal) then
- -- Borrowed in
-
- Current_Checking_Mode := Move;
- else
- -- Observed
+ case Formal_Kind'(Mode) is
- return;
- end if;
+ -- Formal IN parameter
- when E_Out_Parameter =>
- return;
+ when E_In_Parameter =>
- when E_In_Out_Parameter =>
- -- Borrowed in out
+ -- Formal IN parameter, access type
- Current_Checking_Mode := Move;
+ if Is_Access_Type (Etype (Formal)) then
- end case;
+ -- Formal IN parameter, access to variable type
- Check_Node (Actual);
+ if not Is_Access_Constant (Etype (Formal)) then
- when Assign =>
- case Formal_Kind'(Mode) is
- when E_In_Parameter =>
- null;
+ -- Formal IN parameter, named/anonymous access to variable
+ -- type.
- when E_Out_Parameter
- | E_In_Out_Parameter
- =>
- -- Borrowed out or in out
+ Current_Checking_Mode := Borrow;
+ Check_Node (Actual);
- Process_Path (Actual);
+ -- Formal IN parameter, access to constant type
+ -- Formal IN parameter, access to named constant type
- end case;
+ elsif not Is_Anonymous_Access_Type (Etype (Formal)) then
+ Error_Msg_N ("assignment not allowed, Ownership Aspect"
+ & " False (Named general access type)",
+ Formal);
- when others =>
- raise Program_Error;
+ -- Formal IN parameter, access to anonymous constant type
- end case;
- Current_Checking_Mode := Mode_Before;
- end Check_Param;
+ else
+ Current_Checking_Mode := Observe;
+ Check_Node (Actual);
+ end if;
- --------------------------
- -- Check_Param_Observes --
- --------------------------
+ -- Formal IN parameter, composite type
- procedure Check_Param_Observes (Formal : Entity_Id; Actual : Node_Id) is
- Mode : constant Entity_Kind := Ekind (Formal);
- Mode_Before : constant Checking_Mode := Current_Checking_Mode;
+ elsif Is_Deep (Etype (Formal)) then
- begin
- case Mode is
- when E_In_Parameter =>
- if not Is_Borrowed_In (Formal) then
- -- Observed in
+ -- Composite formal types should be named
+ -- Formal IN parameter, composite named type
Current_Checking_Mode := Observe;
Check_Node (Actual);
end if;
- when others =>
+ when E_Out_Parameter
+ | E_In_Out_Parameter
+ =>
null;
-
end case;
Current_Checking_Mode := Mode_Before;
- end Check_Param_Observes;
+ end Check_Param_In;
----------------------
- -- Check_Param_Outs --
+ -- Check_Param_Out --
----------------------
- procedure Check_Param_Outs (Formal : Entity_Id; Actual : Node_Id) is
- Mode : constant Entity_Kind := Ekind (Formal);
+ procedure Check_Param_Out (Formal : Entity_Id; Actual : Node_Id) is
+ Mode : constant Entity_Kind := Ekind (Formal);
Mode_Before : constant Checking_Mode := Current_Checking_Mode;
begin
+ case Formal_Kind'(Mode) is
- case Mode is
- when E_Out_Parameter =>
- -- Borrowed out
- Current_Checking_Mode := Borrow_Out;
- Check_Node (Actual);
+ -- Formal OUT/IN OUT parameter
- when others =>
- null;
+ when E_Out_Parameter
+ | E_In_Out_Parameter
+ =>
- end case;
+ -- Formal OUT/IN OUT parameter, access type
- Current_Checking_Mode := Mode_Before;
- end Check_Param_Outs;
+ if Is_Access_Type (Etype (Formal)) then
- ----------------------
- -- Check_Param_Read --
- ----------------------
+ -- Formal OUT/IN OUT parameter, access to variable type
- procedure Check_Param_Read (Formal : Entity_Id; Actual : Node_Id) is
- Mode : constant Entity_Kind := Ekind (Formal);
+ if not Is_Access_Constant (Etype (Formal)) then
- begin
- pragma Assert (Current_Checking_Mode = Read);
+ -- Cannot have anonymous out access parameter
+ -- Formal out/in out parameter, access to named variable
+ -- type.
- case Formal_Kind'(Mode) is
- when E_In_Parameter =>
- Check_Node (Actual);
+ Current_Checking_Mode := Move;
+ Check_Node (Actual);
- when E_Out_Parameter
- | E_In_Out_Parameter
- =>
- null;
+ -- Formal out/in out parameter, access to constant type
+
+ else
+ Error_Msg_N ("assignment not allowed, Ownership Aspect False"
+ & " (Named general access type)", Formal);
+
+ end if;
+ -- Formal out/in out parameter, composite type
+
+ elsif Is_Deep (Etype (Formal)) then
+
+ -- Composite formal types should be named
+ -- Formal out/in out Parameter, Composite Named type.
+
+ Current_Checking_Mode := Borrow;
+ Check_Node (Actual);
+ end if;
+
+ when E_In_Parameter =>
+ null;
end case;
- end Check_Param_Read;
+
+ Current_Checking_Mode := Mode_Before;
+ end Check_Param_Out;
-------------------------
-- Check_Safe_Pointers --
@@ -2605,13 +2127,13 @@ package body Sem_SPARK is
-- Local variables
Prag : Node_Id;
+
-- SPARK_Mode pragma in application
-- Start of processing for Check_Safe_Pointers
begin
Initialize;
-
case Nkind (N) is
when N_Compilation_Unit =>
Check_Safe_Pointers (Unit (N));
@@ -2647,6 +2169,42 @@ package body Sem_SPARK is
procedure Check_Statement (Stmt : Node_Id) is
Mode_Before : constant Checking_Mode := Current_Checking_Mode;
+ State_N : Perm_Kind;
+ Check : Boolean := True;
+ St_Name : Node_Id;
+ Ty_St_Name : Node_Id;
+
+ function Get_Root (Comp_Stmt : Node_Id) return Node_Id;
+ -- Return the root of the name given as input
+
+ function Get_Root (Comp_Stmt : Node_Id) return Node_Id is
+ begin
+ case Nkind (Comp_Stmt) is
+ when N_Identifier
+ | N_Expanded_Name
+ => return Comp_Stmt;
+
+ when N_Type_Conversion
+ | N_Unchecked_Type_Conversion
+ | N_Qualified_Expression
+ =>
+ return Get_Root (Expression (Comp_Stmt));
+
+ when N_Parameter_Specification =>
+ return Get_Root (Defining_Identifier (Comp_Stmt));
+
+ when N_Selected_Component
+ | N_Indexed_Component
+ | N_Slice
+ | N_Explicit_Dereference
+ =>
+ return Get_Root (Prefix (Comp_Stmt));
+
+ when others =>
+ raise Program_Error;
+ end case;
+ end Get_Root;
+
begin
case N_Statement_Other_Than_Procedure_Call'(Nkind (Stmt)) is
when N_Entry_Call_Statement =>
@@ -2655,25 +2213,189 @@ package body Sem_SPARK is
-- Move right-hand side first, and then assign left-hand side
when N_Assignment_Statement =>
- if Is_Deep (Etype (Expression (Stmt))) then
- Current_Checking_Mode := Move;
- else
- Current_Checking_Mode := Read;
- end if;
- Check_Node (Expression (Stmt));
- Current_Checking_Mode := Assign;
- Check_Node (Name (Stmt));
+ St_Name := Name (Stmt);
+ Ty_St_Name := Etype (Name (Stmt));
+
+ -- Check that is not a *general* access type
+
+ if Has_Ownership_Aspect_True (St_Name, "assigning to") then
+
+ -- Assigning to access type
+
+ if Is_Access_Type (Ty_St_Name) then
+
+ -- Assigning to access to variable type
+
+ if not Is_Access_Constant (Ty_St_Name) then
+
+ -- Assigning to named access to variable type
+
+ if not Is_Anonymous_Access_Type (Ty_St_Name) then
+ Current_Checking_Mode := Move;
+
+ -- Assigning to anonymous access to variable type
+
+ else
+ -- Target /= source root
+
+ if Nkind_In (Expression (Stmt), N_Allocator, N_Null)
+ or else St_Name /= Get_Root (Expression (Stmt))
+ then
+ Error_Msg_N ("assignment not allowed, anonymous "
+ & "access Object with Different Root",
+ Stmt);
+ Check := False;
+
+ -- Target = source root
+
+ else
+ -- Here we do nothing on the source nor on the
+ -- target. However, we check the the legality rule:
+ -- "The source shall be an owning access object
+ -- denoted by a name that is not in the observed
+ -- state".
+
+ State_N := Get_Perm (Expression (Stmt));
+ if State_N = Observed then
+ Error_Msg_N ("assignment not allowed, Anonymous "
+ & "access object with the same root"
+ & " but source Observed", Stmt);
+ Check := False;
+ end if;
+ end if;
+ end if;
+
+ -- else access-to-constant
+
+ -- Assigning to anonymous access-to-constant type
+
+ elsif Is_Anonymous_Access_Type (Ty_St_Name) then
+
+ -- ??? Check the follwing condition. We may have to
+ -- add that the root is in the observed state too.
+
+ State_N := Get_Perm (Expression (Stmt));
+ if State_N /= Observed then
+ Error_Msg_N ("assignment not allowed, anonymous "
+ & "access-to-constant object not in "
+ & "the observed state)", Stmt);
+ Check := False;
+
+ else
+ Error_Msg_N ("?here check accessibility level cited in"
+ & " the second legality rule of assign",
+ Stmt);
+ Check := False;
+ end if;
+
+ -- Assigning to named access-to-constant type:
+ -- This case should have been detected when checking
+ -- Has_Onwership_Aspect_True (Name (Stmt), "msg").
+
+ else
+ raise Program_Error;
+ end if;
+
+ -- Assigning to composite (deep) type.
+
+ elsif Is_Deep (Ty_St_Name) then
+ if Ekind (Ty_St_Name) = E_Record_Type then
+ declare
+ Elmt : Entity_Id :=
+ First_Component_Or_Discriminant (Ty_St_Name);
+
+ begin
+ while Present (Elmt) loop
+ if Is_Anonymous_Access_Type (Etype (Elmt)) or
+ Ekind (Elmt) = E_General_Access_Type
+ then
+ Error_Msg_N ("assignment not allowed, Ownership "
+ & "Aspect False (Components have "
+ & "Ownership Aspect False)", Stmt);
+ Check := False;
+ exit;
+ end if;
+
+ Next_Component_Or_Discriminant (Elmt);
+ end loop;
+ end;
+
+ -- Record types are always named so this is a move
+
+ if Check then
+ Current_Checking_Mode := Move;
+ end if;
+ end if;
+
+ -- Now handle legality rules of using a borrowed, observed,
+ -- or moved name as a prefix in an assignment.
+
+ else
+ if Nkind_In (St_Name,
+ N_Attribute_Reference,
+ N_Expanded_Name,
+ N_Explicit_Dereference,
+ N_Indexed_Component,
+ N_Reference,
+ N_Selected_Component,
+ N_Slice)
+ then
+
+ if Is_Access_Type (Etype (Prefix (St_Name))) or
+ Is_Deep (Etype (Prefix (St_Name)))
+ then
+
+ -- We set the Check variable to True so that we can
+ -- Check_Node of the expression and the name first
+ -- under the assumption of Current_Checking_Mode =
+ -- Read => nothing to be done for the RHS if the
+ -- following check on the expression fails, and
+ -- Current_Checking_Mode := Assign => the name should
+ -- not be borrowed or observed so that we can use it
+ -- as a prefix in the target of an assignement.
+ --
+ -- Note that we do not need to check the OA here
+ -- because we are allowed to read and write "through"
+ -- an object of OAF (example: traversing a DS).
+
+ Check := True;
+ end if;
+ end if;
+
+ if Nkind_In (Expression (Stmt),
+ N_Attribute_Reference,
+ N_Expanded_Name,
+ N_Explicit_Dereference,
+ N_Indexed_Component,
+ N_Reference,
+ N_Selected_Component,
+ N_Slice)
+ then
+
+ if Is_Access_Type (Etype (Prefix (Expression (Stmt))))
+ or else Is_Deep (Etype (Prefix (Expression (Stmt))))
+ then
+ Current_Checking_Mode := Observe;
+ Check := True;
+ end if;
+ end if;
+ end if;
+
+ if Check then
+ Check_Node (Expression (Stmt));
+ Current_Checking_Mode := Assign;
+ Check_Node (St_Name);
+ end if;
+ end if;
when N_Block_Statement =>
declare
Saved_Env : Perm_Env;
-
begin
-- Save environment
- Copy_Env (Current_Perm_Env,
- Saved_Env);
+ Copy_Env (Current_Perm_Env, Saved_Env);
-- Analyze declarations and Handled_Statement_Sequences
@@ -2684,8 +2406,7 @@ package body Sem_SPARK is
-- Restore environment
Free_Env (Current_Perm_Env);
- Copy_Env (Saved_Env,
- Current_Perm_Env);
+ Copy_Env (Saved_Env, Current_Perm_Env);
end;
when N_Case_Statement =>
@@ -2695,7 +2416,6 @@ package body Sem_SPARK is
-- Accumulator for the different branches
New_Env : Perm_Env;
-
Elmt : Node_Id := First (Alternatives (Stmt));
begin
@@ -2705,8 +2425,7 @@ package body Sem_SPARK is
-- Save environment
- Copy_Env (Current_Perm_Env,
- Saved_Env);
+ Copy_Env (Current_Perm_Env, Saved_Env);
-- Here we have the original env in saved, current with a fresh
-- copy, and new aliased.
@@ -2715,33 +2434,21 @@ package body Sem_SPARK is
Check_Node (Elmt);
Next (Elmt);
-
- Copy_Env (Current_Perm_Env,
- New_Env);
+ Copy_Env (Current_Perm_Env, New_Env);
Free_Env (Current_Perm_Env);
-- Other alternatives
while Present (Elmt) loop
- -- Restore environment
- Copy_Env (Saved_Env,
- Current_Perm_Env);
+ -- Restore environment
+ Copy_Env (Saved_Env, Current_Perm_Env);
Check_Node (Elmt);
-
- -- Merge Current_Perm_Env into New_Env
-
- Merge_Envs (New_Env,
- Current_Perm_Env);
-
Next (Elmt);
end loop;
- -- CLEANUP
- Copy_Env (New_Env,
- Current_Perm_Env);
-
+ Copy_Env (Saved_Env, Current_Perm_Env);
Free_Env (New_Env);
Free_Env (Saved_Env);
end;
@@ -2755,7 +2462,7 @@ package body Sem_SPARK is
when N_Loop_Statement =>
Check_Loop_Statement (Stmt);
- -- If deep type expression, then move, else read
+ -- If deep type expression, then move, else read
when N_Simple_Return_Statement =>
case Nkind (Expression (Stmt)) is
@@ -2767,65 +2474,42 @@ package body Sem_SPARK is
Subp : constant Entity_Id :=
Return_Applies_To (Return_Statement_Entity (Stmt));
begin
- Return_Parameters (Subp);
Return_Globals (Subp);
end;
when others =>
if Is_Deep (Etype (Expression (Stmt))) then
Current_Checking_Mode := Move;
- elsif Is_Shallow (Etype (Expression (Stmt))) then
- Current_Checking_Mode := Read;
else
- raise Program_Error;
+ Check := False;
end if;
- Check_Node (Expression (Stmt));
+ if Check then
+ Check_Node (Expression (Stmt));
+ end if;
end case;
when N_Extended_Return_Statement =>
Check_List (Return_Object_Declarations (Stmt));
Check_Node (Handled_Statement_Sequence (Stmt));
-
Return_Declarations (Return_Object_Declarations (Stmt));
-
declare
-- ??? This does not take into account the fact that a simple
-- return inside an extended return statement applies to the
-- extended return statement.
Subp : constant Entity_Id :=
Return_Applies_To (Return_Statement_Entity (Stmt));
+
begin
- Return_Parameters (Subp);
Return_Globals (Subp);
end;
- -- Merge the current_Perm_Env with the accumulator for the given loop
+ -- Nothing to do when exiting a loop. No merge needed
when N_Exit_Statement =>
- declare
- Loop_Name : constant Entity_Id := Loop_Of_Exit (Stmt);
-
- Saved_Accumulator : constant Perm_Env_Access :=
- Get (Current_Loops_Accumulators, Loop_Name);
-
- Environment_Copy : constant Perm_Env_Access :=
- new Perm_Env;
- begin
-
- Copy_Env (Current_Perm_Env,
- Environment_Copy.all);
-
- if Saved_Accumulator = null then
- Set (Current_Loops_Accumulators,
- Loop_Name, Environment_Copy);
- else
- Merge_Envs (Saved_Accumulator.all,
- Environment_Copy.all);
- end if;
- end;
+ null;
- -- Copy environment, run on each branch, and then merge
+ -- Copy environment, run on each branch
when N_If_Statement =>
declare
@@ -2836,13 +2520,11 @@ package body Sem_SPARK is
New_Env : Perm_Env;
begin
-
Check_Node (Condition (Stmt));
-- Save environment
- Copy_Env (Current_Perm_Env,
- Saved_Env);
+ Copy_Env (Current_Perm_Env, Saved_Env);
-- Here we have the original env in saved, current with a fresh
-- copy.
@@ -2850,34 +2532,25 @@ package body Sem_SPARK is
-- THEN PART
Check_List (Then_Statements (Stmt));
-
- Copy_Env (Current_Perm_Env,
- New_Env);
-
+ Copy_Env (Current_Perm_Env, New_Env);
Free_Env (Current_Perm_Env);
-- Here the new_environment contains curr env after then block
-- ELSIF part
+
declare
Elmt : Node_Id;
begin
Elmt := First (Elsif_Parts (Stmt));
while Present (Elmt) loop
- -- Transfer into accumulator, and restore from save
- Copy_Env (Saved_Env,
- Current_Perm_Env);
+ -- Transfer into accumulator, and restore from save
+ Copy_Env (Saved_Env, Current_Perm_Env);
Check_Node (Condition (Elmt));
Check_List (Then_Statements (Stmt));
-
- -- Merge Current_Perm_Env into New_Env
-
- Merge_Envs (New_Env,
- Current_Perm_Env);
-
Next (Elmt);
end loop;
end;
@@ -2886,21 +2559,16 @@ package body Sem_SPARK is
-- Restore environment before if
- Copy_Env (Saved_Env,
- Current_Perm_Env);
+ Copy_Env (Saved_Env, Current_Perm_Env);
-- Here new environment contains the environment after then and
-- current the fresh copy of old one.
Check_List (Else_Statements (Stmt));
- Merge_Envs (New_Env,
- Current_Perm_Env);
-
-- CLEANUP
- Copy_Env (New_Env,
- Current_Perm_Env);
+ Copy_Env (Saved_Env, Current_Perm_Env);
Free_Env (New_Env);
Free_Env (Saved_Env);
@@ -2956,8 +2624,7 @@ package body Sem_SPARK is
-- which means that the association permission is RW.
when Function_Call =>
- return Read_Write;
-
+ return Unrestricted;
end case;
end Get_Perm;
@@ -2980,7 +2647,6 @@ package body Sem_SPARK is
=>
declare
P : constant Entity_Id := Entity (N);
-
C : constant Perm_Tree_Access :=
Get (Current_Perm_Env, Unique_Entity (P));
@@ -2990,13 +2656,13 @@ package body Sem_SPARK is
-- of elaboration of package.
Set (Current_Initialization_Map, Unique_Entity (P), True);
-
if C = null then
-- No null possible here, there are no parents for the path.
-- This means we are using a global variable without adding
-- it in environment with a global aspect.
Illegal_Global_Usage (N);
+
else
return (R => Unfolded, Tree_Access => C);
end if;
@@ -3023,8 +2689,7 @@ package body Sem_SPARK is
when N_Selected_Component =>
declare
- C : constant Perm_Or_Tree :=
- Get_Perm_Or_Tree (Prefix (N));
+ C : constant Perm_Or_Tree := Get_Perm_Or_Tree (Prefix (N));
begin
case C.R is
@@ -3035,7 +2700,6 @@ package body Sem_SPARK is
when Unfolded =>
pragma Assert (C.Tree_Access /= null);
-
pragma Assert (Kind (C.Tree_Access) = Entire_Object
or else
Kind (C.Tree_Access) = Record_Component);
@@ -3044,30 +2708,32 @@ package body Sem_SPARK is
declare
Selected_Component : constant Entity_Id :=
Entity (Selector_Name (N));
-
Selected_C : constant Perm_Tree_Access :=
Perm_Tree_Maps.Get
(Component (C.Tree_Access), Selected_Component);
begin
if Selected_C = null then
- return (R => Unfolded,
+ return (R => Unfolded,
Tree_Access =>
Other_Components (C.Tree_Access));
+
else
- return (R => Unfolded,
+ return (R => Unfolded,
Tree_Access => Selected_C);
end if;
end;
+
elsif Kind (C.Tree_Access) = Entire_Object then
- return (R => Folded, Found_Permission =>
+ return (R => Folded,
+ Found_Permission =>
Children_Permission (C.Tree_Access));
+
else
raise Program_Error;
end if;
end case;
end;
-
-- We get the permission tree of its prefix, and then get either the
-- subtree associated with that specific selection, or if we have a
-- leaf that folds its children, we take the children's permission
@@ -3077,8 +2743,7 @@ package body Sem_SPARK is
| N_Slice
=>
declare
- C : constant Perm_Or_Tree :=
- Get_Perm_Or_Tree (Prefix (N));
+ C : constant Perm_Or_Tree := Get_Perm_Or_Tree (Prefix (N));
begin
case C.R is
@@ -3089,25 +2754,24 @@ package body Sem_SPARK is
when Unfolded =>
pragma Assert (C.Tree_Access /= null);
-
pragma Assert (Kind (C.Tree_Access) = Entire_Object
or else
Kind (C.Tree_Access) = Array_Component);
if Kind (C.Tree_Access) = Array_Component then
pragma Assert (Get_Elem (C.Tree_Access) /= null);
-
return (R => Unfolded,
Tree_Access => Get_Elem (C.Tree_Access));
+
elsif Kind (C.Tree_Access) = Entire_Object then
return (R => Folded, Found_Permission =>
Children_Permission (C.Tree_Access));
+
else
raise Program_Error;
end if;
end case;
end;
-
-- We get the permission tree of its prefix, and then get either the
-- subtree associated with that specific selection, or if we have a
-- leaf that folds its children, we take the children's permission
@@ -3115,8 +2779,7 @@ package body Sem_SPARK is
when N_Explicit_Dereference =>
declare
- C : constant Perm_Or_Tree :=
- Get_Perm_Or_Tree (Prefix (N));
+ C : constant Perm_Or_Tree := Get_Perm_Or_Tree (Prefix (N));
begin
case C.R is
@@ -3127,29 +2790,32 @@ package body Sem_SPARK is
when Unfolded =>
pragma Assert (C.Tree_Access /= null);
-
pragma Assert (Kind (C.Tree_Access) = Entire_Object
or else
Kind (C.Tree_Access) = Reference);
if Kind (C.Tree_Access) = Reference then
if Get_All (C.Tree_Access) = null then
+
-- Hash_Table_Error
+
raise Program_Error;
+
else
return
(R => Unfolded,
Tree_Access => Get_All (C.Tree_Access));
end if;
+
elsif Kind (C.Tree_Access) = Entire_Object then
return (R => Folded, Found_Permission =>
Children_Permission (C.Tree_Access));
+
else
raise Program_Error;
end if;
end case;
end;
-
-- The name contains a function call, hence the given path is always
-- new. We do not have to check for anything.
@@ -3165,10 +2831,7 @@ package body Sem_SPARK is
-- Get_Perm_Tree --
-------------------
- function Get_Perm_Tree
- (N : Node_Id)
- return Perm_Tree_Access
- is
+ function Get_Perm_Tree (N : Node_Id) return Perm_Tree_Access is
begin
case Nkind (N) is
@@ -3183,7 +2846,6 @@ package body Sem_SPARK is
=>
declare
P : constant Node_Id := Entity (N);
-
C : constant Perm_Tree_Access :=
Get (Current_Perm_Env, Unique_Entity (P));
@@ -3193,13 +2855,13 @@ package body Sem_SPARK is
-- of elaboration of package.
Set (Current_Initialization_Map, Unique_Entity (P), True);
-
if C = null then
-- No null possible here, there are no parents for the path.
-- This means we are using a global variable without adding
-- it in environment with a global aspect.
Illegal_Global_Usage (N);
+
else
return C;
end if;
@@ -3220,11 +2882,11 @@ package body Sem_SPARK is
when N_Selected_Component =>
declare
- C : constant Perm_Tree_Access :=
- Get_Perm_Tree (Prefix (N));
+ C : constant Perm_Tree_Access := Get_Perm_Tree (Prefix (N));
begin
if C = null then
+
-- If null then it means we went through a function call
return null;
@@ -3234,6 +2896,7 @@ package body Sem_SPARK is
or else Kind (C) = Record_Component);
if Kind (C) = Record_Component then
+
-- The tree is unfolded. We just return the subtree.
declare
@@ -3247,9 +2910,9 @@ package body Sem_SPARK is
if Selected_C = null then
return Other_Components (C);
end if;
-
return Selected_C;
end;
+
elsif Kind (C) = Entire_Object then
declare
-- Expand the tree. Replace the node with
@@ -3265,7 +2928,6 @@ package body Sem_SPARK is
Children_Permission (C);
begin
-
-- We change the current node from Entire_Object to
-- Record_Component with same permission and an empty
-- hash table as component list.
@@ -3288,6 +2950,7 @@ package body Sem_SPARK is
-- We fill the hash table with all sons of the record,
-- with basic Entire_Objects nodes.
+
Elem := First_Component_Or_Discriminant
(Etype (Prefix (N)));
@@ -3301,10 +2964,8 @@ package body Sem_SPARK is
Perm_Tree_Maps.Set
(C.all.Tree.Component, Elem, Son);
-
Next_Component_Or_Discriminant (Elem);
end loop;
-
-- we return the tree to the sons, so that the recursion
-- can continue.
@@ -3318,16 +2979,13 @@ package body Sem_SPARK is
begin
pragma Assert (Selected_C /= null);
-
return Selected_C;
end;
-
end;
else
raise Program_Error;
end if;
end;
-
-- We set the permission tree of its prefix, and then we extract from
-- the returned pointer the subtree. If folded, we unroll the tree at
-- one step.
@@ -3336,8 +2994,7 @@ package body Sem_SPARK is
| N_Slice
=>
declare
- C : constant Perm_Tree_Access :=
- Get_Perm_Tree (Prefix (N));
+ C : constant Perm_Tree_Access := Get_Perm_Tree (Prefix (N));
begin
if C = null then
@@ -3345,16 +3002,16 @@ package body Sem_SPARK is
return null;
end if;
-
pragma Assert (Kind (C) = Entire_Object
or else Kind (C) = Array_Component);
if Kind (C) = Array_Component then
+
-- The tree is unfolded. We just return the elem subtree
pragma Assert (Get_Elem (C) = null);
-
return Get_Elem (C);
+
elsif Kind (C) = Entire_Object then
declare
-- Expand the tree. Replace node with Array_Component.
@@ -3377,14 +3034,12 @@ package body Sem_SPARK is
Is_Node_Deep => Is_Node_Deep (C),
Permission => Permission (C),
Get_Elem => Son);
-
return Get_Elem (C);
end;
else
raise Program_Error;
end if;
end;
-
-- We get the permission tree of its prefix, and then get either the
-- subtree associated with that specific selection, or if we have a
-- leaf that folds its children, we unroll the tree.
@@ -3397,6 +3052,7 @@ package body Sem_SPARK is
C := Get_Perm_Tree (Prefix (N));
if C = null then
+
-- If null, we went through a function call
return null;
@@ -3406,14 +3062,17 @@ package body Sem_SPARK is
or else Kind (C) = Reference);
if Kind (C) = Reference then
+
-- The tree is unfolded. We return the elem subtree
if Get_All (C) = null then
+
-- Hash_Table_Error
+
raise Program_Error;
end if;
-
return Get_All (C);
+
elsif Kind (C) = Entire_Object then
declare
-- Expand the tree. Replace the node with Reference.
@@ -3432,19 +3091,16 @@ package body Sem_SPARK is
-- Reference with same permission and the previous son.
pragma Assert (Is_Node_Deep (C));
-
C.all.Tree := (Kind => Reference,
Is_Node_Deep => Is_Node_Deep (C),
Permission => Permission (C),
Get_All => Son);
-
return Get_All (C);
end;
else
raise Program_Error;
end if;
end;
-
-- No permission tree for function calls
when N_Function_Call =>
@@ -3455,245 +3111,6 @@ package body Sem_SPARK is
end case;
end Get_Perm_Tree;
- ---------
- -- Glb --
- ---------
-
- function Glb (P1, P2 : Perm_Kind) return Perm_Kind
- is
- begin
- case P1 is
- when No_Access =>
- return No_Access;
-
- when Read_Only =>
- case P2 is
- when No_Access
- | Write_Only
- =>
- return No_Access;
-
- when Read_Perm =>
- return Read_Only;
- end case;
-
- when Write_Only =>
- case P2 is
- when No_Access
- | Read_Only
- =>
- return No_Access;
-
- when Write_Perm =>
- return Write_Only;
- end case;
-
- when Read_Write =>
- return P2;
- end case;
- end Glb;
-
- ---------------
- -- Has_Alias --
- ---------------
-
- function Has_Alias
- (N : Node_Id)
- return Boolean
- is
- function Has_Alias_Deep (Typ : Entity_Id) return Boolean;
- function Has_Alias_Deep (Typ : Entity_Id) return Boolean
- is
- Comp : Node_Id;
- begin
-
- if Is_Array_Type (Typ)
- and then Has_Aliased_Components (Typ)
- then
- return True;
-
- -- Note: Has_Aliased_Components applies only to arrays
-
- elsif Is_Record_Type (Typ) then
- -- It is possible to have an aliased discriminant, so they must be
- -- checked along with normal components.
-
- Comp := First_Component_Or_Discriminant (Typ);
- while Present (Comp) loop
- if Is_Aliased (Comp)
- or else Is_Aliased (Etype (Comp))
- then
- return True;
- end if;
-
- if Has_Alias_Deep (Etype (Comp)) then
- return True;
- end if;
-
- Next_Component_Or_Discriminant (Comp);
- end loop;
- return False;
- else
- return Is_Aliased (Typ);
- end if;
- end Has_Alias_Deep;
-
- begin
- case Nkind (N) is
-
- when N_Identifier
- | N_Expanded_Name
- =>
- return Is_Aliased (Entity (N)) or else Has_Alias_Deep (Etype (N));
-
- when N_Defining_Identifier =>
- return Is_Aliased (N) or else Has_Alias_Deep (Etype (N));
-
- when N_Type_Conversion
- | N_Unchecked_Type_Conversion
- | N_Qualified_Expression
- =>
- return Has_Alias (Expression (N));
-
- when N_Parameter_Specification =>
- return Has_Alias (Defining_Identifier (N));
-
- when N_Selected_Component =>
- case Nkind (Selector_Name (N)) is
- when N_Identifier =>
- if Is_Aliased (Entity (Selector_Name (N))) then
- return True;
- end if;
-
- when others => null;
-
- end case;
-
- return Has_Alias (Prefix (N));
-
- when N_Indexed_Component
- | N_Slice
- =>
- return Has_Alias (Prefix (N));
-
- when N_Explicit_Dereference =>
- return True;
-
- when N_Function_Call =>
- return False;
-
- when N_Attribute_Reference =>
- if Is_Deep (Etype (Prefix (N))) then
- raise Program_Error;
- end if;
- return False;
-
- when others =>
- return False;
- end case;
- end Has_Alias;
-
- -------------------------
- -- Has_Array_Component --
- -------------------------
-
- function Has_Array_Component (N : Node_Id) return Boolean is
- begin
- case Nkind (N) is
- -- Base identifier. There is no array component here.
-
- when N_Identifier
- | N_Expanded_Name
- | N_Defining_Identifier
- =>
- return False;
-
- -- We check if the expression inside the conversion has an array
- -- component.
-
- when N_Type_Conversion
- | N_Unchecked_Type_Conversion
- | N_Qualified_Expression
- =>
- return Has_Array_Component (Expression (N));
-
- -- We check if the prefix has an array component
-
- when N_Selected_Component =>
- return Has_Array_Component (Prefix (N));
-
- -- We found the array component, return True
-
- when N_Indexed_Component
- | N_Slice
- =>
- return True;
-
- -- We check if the prefix has an array component
-
- when N_Explicit_Dereference =>
- return Has_Array_Component (Prefix (N));
-
- when N_Function_Call =>
- return False;
-
- when others =>
- raise Program_Error;
- end case;
- end Has_Array_Component;
-
- ----------------------------
- -- Has_Function_Component --
- ----------------------------
-
- function Has_Function_Component (N : Node_Id) return Boolean is
- begin
- case Nkind (N) is
- -- Base identifier. There is no function component here.
-
- when N_Identifier
- | N_Expanded_Name
- | N_Defining_Identifier
- =>
- return False;
-
- -- We check if the expression inside the conversion has a function
- -- component.
-
- when N_Type_Conversion
- | N_Unchecked_Type_Conversion
- | N_Qualified_Expression
- =>
- return Has_Function_Component (Expression (N));
-
- -- We check if the prefix has a function component
-
- when N_Selected_Component =>
- return Has_Function_Component (Prefix (N));
-
- -- We check if the prefix has a function component
-
- when N_Indexed_Component
- | N_Slice
- =>
- return Has_Function_Component (Prefix (N));
-
- -- We check if the prefix has a function component
-
- when N_Explicit_Dereference =>
- return Has_Function_Component (Prefix (N));
-
- -- We found the function component, return True
-
- when N_Function_Call =>
- return True;
-
- when others =>
- raise Program_Error;
-
- end case;
- end Has_Function_Component;
-
--------
-- Hp --
--------
@@ -3717,29 +3134,17 @@ package body Sem_SPARK is
begin
Error_Msg_NE ("cannot use global variable & of deep type", N, N);
Error_Msg_N ("\without prior declaration in a Global aspect", N);
-
Errout.Finalize (Last_Call => True);
Errout.Output_Messages;
Exit_Program (E_Errors);
end Illegal_Global_Usage;
- --------------------
- -- Is_Borrowed_In --
- --------------------
-
- function Is_Borrowed_In (E : Entity_Id) return Boolean is
- begin
- return Is_Access_Type (Etype (E))
- and then not Is_Access_Constant (Etype (E));
- end Is_Borrowed_In;
-
-------------
-- Is_Deep --
-------------
function Is_Deep (E : Entity_Id) return Boolean is
function Is_Private_Entity_Mode_Off (E : Entity_Id) return Boolean;
-
function Is_Private_Entity_Mode_Off (E : Entity_Id) return Boolean is
Decl : Node_Id;
Pack_Decl : Node_Id;
@@ -3762,9 +3167,9 @@ package body Sem_SPARK is
and then Get_SPARK_Mode_From_Annotation
(SPARK_Aux_Pragma (Defining_Entity (Pack_Decl))) = Off;
end Is_Private_Entity_Mode_Off;
+
begin
pragma Assert (Is_Type (E));
-
case Ekind (E) is
when Scalar_Kind =>
return False;
@@ -3793,7 +3198,7 @@ package body Sem_SPARK is
when E_Record_Type
| E_Record_Subtype
- =>
+ =>
declare
Elmt : Entity_Id;
@@ -3806,7 +3211,6 @@ package body Sem_SPARK is
Next_Component_Or_Discriminant (Elmt);
end if;
end loop;
-
return False;
end;
@@ -3821,10 +3225,9 @@ package body Sem_SPARK is
end if;
end if;
- when E_Incomplete_Type =>
- return True;
-
- when E_Incomplete_Subtype =>
+ when E_Incomplete_Type
+ | E_Incomplete_Subtype
+ =>
return True;
-- No problem with synchronized types
@@ -3845,311 +3248,6 @@ package body Sem_SPARK is
end Is_Deep;
----------------
- -- Is_Shallow --
- ----------------
-
- function Is_Shallow (E : Entity_Id) return Boolean is
- begin
- pragma Assert (Is_Type (E));
- return not Is_Deep (E);
- end Is_Shallow;
-
- ------------------
- -- Loop_Of_Exit --
- ------------------
-
- function Loop_Of_Exit (N : Node_Id) return Entity_Id is
- Nam : Node_Id := Name (N);
- Stmt : Node_Id := N;
- begin
- if No (Nam) then
- while Present (Stmt) loop
- Stmt := Parent (Stmt);
- if Nkind (Stmt) = N_Loop_Statement then
- Nam := Identifier (Stmt);
- exit;
- end if;
- end loop;
- end if;
- return Entity (Nam);
- end Loop_Of_Exit;
- ---------
- -- Lub --
- ---------
-
- function Lub (P1, P2 : Perm_Kind) return Perm_Kind
- is
- begin
- case P1 is
- when No_Access =>
- return P2;
-
- when Read_Only =>
- case P2 is
- when No_Access
- | Read_Only
- =>
- return Read_Only;
-
- when Write_Perm =>
- return Read_Write;
- end case;
-
- when Write_Only =>
- case P2 is
- when No_Access
- | Write_Only
- =>
- return Write_Only;
-
- when Read_Perm =>
- return Read_Write;
- end case;
-
- when Read_Write =>
- return Read_Write;
- end case;
- end Lub;
-
- ----------------
- -- Merge_Envs --
- ----------------
-
- procedure Merge_Envs
- (Target : in out Perm_Env;
- Source : in out Perm_Env)
- is
- procedure Merge_Trees
- (Target : Perm_Tree_Access;
- Source : Perm_Tree_Access);
-
- procedure Merge_Trees
- (Target : Perm_Tree_Access;
- Source : Perm_Tree_Access)
- is
- procedure Apply_Glb_Tree
- (A : Perm_Tree_Access;
- P : Perm_Kind);
-
- procedure Apply_Glb_Tree
- (A : Perm_Tree_Access;
- P : Perm_Kind)
- is
- begin
- A.all.Tree.Permission := Glb (Permission (A), P);
-
- case Kind (A) is
- when Entire_Object =>
- A.all.Tree.Children_Permission :=
- Glb (Children_Permission (A), P);
-
- when Reference =>
- Apply_Glb_Tree (Get_All (A), P);
-
- when Array_Component =>
- Apply_Glb_Tree (Get_Elem (A), P);
-
- when Record_Component =>
- declare
- Comp : Perm_Tree_Access;
- begin
- Comp := Perm_Tree_Maps.Get_First (Component (A));
- while Comp /= null loop
- Apply_Glb_Tree (Comp, P);
- Comp := Perm_Tree_Maps.Get_Next (Component (A));
- end loop;
-
- Apply_Glb_Tree (Other_Components (A), P);
- end;
- end case;
- end Apply_Glb_Tree;
-
- Perm : constant Perm_Kind :=
- Glb (Permission (Target), Permission (Source));
-
- begin
- pragma Assert (Is_Node_Deep (Target) = Is_Node_Deep (Source));
- Target.all.Tree.Permission := Perm;
-
- case Kind (Target) is
- when Entire_Object =>
- declare
- Child_Perm : constant Perm_Kind :=
- Children_Permission (Target);
-
- begin
- case Kind (Source) is
- when Entire_Object =>
- Target.all.Tree.Children_Permission :=
- Glb (Child_Perm, Children_Permission (Source));
-
- when Reference =>
- Copy_Tree (Source, Target);
- Target.all.Tree.Permission := Perm;
- Apply_Glb_Tree (Get_All (Target), Child_Perm);
-
- when Array_Component =>
- Copy_Tree (Source, Target);
- Target.all.Tree.Permission := Perm;
- Apply_Glb_Tree (Get_Elem (Target), Child_Perm);
-
- when Record_Component =>
- Copy_Tree (Source, Target);
- Target.all.Tree.Permission := Perm;
- declare
- Comp : Perm_Tree_Access;
-
- begin
- Comp :=
- Perm_Tree_Maps.Get_First (Component (Target));
- while Comp /= null loop
- -- Apply glb tree on every component subtree
-
- Apply_Glb_Tree (Comp, Child_Perm);
- Comp := Perm_Tree_Maps.Get_Next
- (Component (Target));
- end loop;
- end;
- Apply_Glb_Tree (Other_Components (Target), Child_Perm);
-
- end case;
- end;
- when Reference =>
- case Kind (Source) is
- when Entire_Object =>
- Apply_Glb_Tree (Get_All (Target),
- Children_Permission (Source));
-
- when Reference =>
- Merge_Trees (Get_All (Target), Get_All (Source));
-
- when others =>
- raise Program_Error;
-
- end case;
-
- when Array_Component =>
- case Kind (Source) is
- when Entire_Object =>
- Apply_Glb_Tree (Get_Elem (Target),
- Children_Permission (Source));
-
- when Array_Component =>
- Merge_Trees (Get_Elem (Target), Get_Elem (Source));
-
- when others =>
- raise Program_Error;
-
- end case;
-
- when Record_Component =>
- case Kind (Source) is
- when Entire_Object =>
- declare
- Child_Perm : constant Perm_Kind :=
- Children_Permission (Source);
-
- Comp : Perm_Tree_Access;
-
- begin
- Comp := Perm_Tree_Maps.Get_First
- (Component (Target));
- while Comp /= null loop
- -- Apply glb tree on every component subtree
-
- Apply_Glb_Tree (Comp, Child_Perm);
- Comp :=
- Perm_Tree_Maps.Get_Next (Component (Target));
- end loop;
- Apply_Glb_Tree (Other_Components (Target), Child_Perm);
- end;
-
- when Record_Component =>
- declare
- Key_Source : Perm_Tree_Maps.Key_Option;
- CompTarget : Perm_Tree_Access;
- CompSource : Perm_Tree_Access;
-
- begin
- Key_Source := Perm_Tree_Maps.Get_First_Key
- (Component (Source));
-
- while Key_Source.Present loop
- CompSource := Perm_Tree_Maps.Get
- (Component (Source), Key_Source.K);
- CompTarget := Perm_Tree_Maps.Get
- (Component (Target), Key_Source.K);
-
- pragma Assert (CompSource /= null);
- Merge_Trees (CompTarget, CompSource);
-
- Key_Source := Perm_Tree_Maps.Get_Next_Key
- (Component (Source));
- end loop;
-
- Merge_Trees (Other_Components (Target),
- Other_Components (Source));
- end;
-
- when others =>
- raise Program_Error;
-
- end case;
- end case;
- end Merge_Trees;
-
- CompTarget : Perm_Tree_Access;
- CompSource : Perm_Tree_Access;
- KeyTarget : Perm_Tree_Maps.Key_Option;
-
- begin
- KeyTarget := Get_First_Key (Target);
- -- Iterate over every tree of the environment in the target, and merge
- -- it with the source if there is such a similar one that exists. If
- -- there is none, then skip.
- while KeyTarget.Present loop
-
- CompSource := Get (Source, KeyTarget.K);
- CompTarget := Get (Target, KeyTarget.K);
-
- pragma Assert (CompTarget /= null);
-
- if CompSource /= null then
- Merge_Trees (CompTarget, CompSource);
- Remove (Source, KeyTarget.K);
- end if;
-
- KeyTarget := Get_Next_Key (Target);
- end loop;
-
- -- Iterate over every tree of the environment of the source. And merge
- -- again. If there is not any tree of the target then just copy the tree
- -- from source to target.
- declare
- KeySource : Perm_Tree_Maps.Key_Option;
- begin
- KeySource := Get_First_Key (Source);
- while KeySource.Present loop
-
- CompSource := Get (Source, KeySource.K);
- CompTarget := Get (Target, KeySource.K);
-
- if CompTarget = null then
- CompTarget := new Perm_Tree_Wrapper'(CompSource.all);
- Copy_Tree (CompSource, CompTarget);
- Set (Target, KeySource.K, CompTarget);
- else
- Merge_Trees (CompTarget, CompSource);
- end if;
-
- KeySource := Get_Next_Key (Source);
- end loop;
- end;
-
- Free_Env (Source);
- end Merge_Envs;
-
- ----------------
-- Perm_Error --
----------------
@@ -4202,7 +3300,6 @@ package body Sem_SPARK is
raise Program_Error;
end case;
end Set_Root_Object;
-
-- Local variables
Root : Entity_Id;
@@ -4245,8 +3342,8 @@ package body Sem_SPARK is
------------------
procedure Process_Path (N : Node_Id) is
- Root : constant Entity_Id := Get_Enclosing_Object (N);
-
+ Root : constant Entity_Id := Get_Enclosing_Object (N);
+ State_N : Perm_Kind;
begin
-- We ignore if yielding to synchronized
@@ -4256,200 +3353,153 @@ package body Sem_SPARK is
return;
end if;
- -- We ignore shallow unaliased. They are checked in flow analysis,
- -- allowing backward compatibility.
+ State_N := Get_Perm (N);
- if Current_Checking_Mode /= Super_Move
- and then not Has_Alias (N)
- and then Is_Shallow (Etype (N))
- then
- return;
- end if;
-
- declare
- Perm_N : constant Perm_Kind := Get_Perm (N);
+ case Current_Checking_Mode is
- begin
+ -- Check permission R, do nothing
- case Current_Checking_Mode is
- -- Check permission R, do nothing
+ when Read =>
- when Read =>
- if Perm_N not in Read_Perm then
- Perm_Error (N, Read_Only, Perm_N);
- return;
- end if;
+ -- This condition should be removed when removing the read
+ -- checking mode.
- -- If shallow type no need for RW, only R
+ return;
- when Move =>
- if Is_Shallow (Etype (N)) then
- if Perm_N not in Read_Perm then
- Perm_Error (N, Read_Only, Perm_N);
- return;
- end if;
- else
- -- Check permission RW if deep
+ when Move =>
- if Perm_N /= Read_Write then
- Perm_Error (N, Read_Write, Perm_N);
- return;
- end if;
+ -- The rhs object in an assignment statement (including copy in
+ -- and copy back) should be in the Unrestricted or Moved state.
+ -- Otherwise the move is not allowed.
+ -- This applies to both stand-alone and composite objects.
+ -- If the state of the source is Moved, then a warning message
+ -- is prompt to make the user aware of reading a nullified
+ -- object.
- declare
- -- Set permission to W to the path and any of its prefix
-
- Tree : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Move (N, Move);
+ if State_N /= Unrestricted and State_N /= Moved then
+ Perm_Error (N, Unrestricted, State_N);
+ return;
+ end if;
- begin
- if Tree = null then
- -- We went through a function call, no permission to
- -- modify.
+ -- In the AI, after moving a path nothing to do since the rhs
+ -- object was in the Unrestricted state and it shall be
+ -- refreshed to Unrestricted. The object should be nullified
+ -- however. To avoid moving again a name that has already been
+ -- moved, in this implementation we set the state of the moved
+ -- object to "Moved". This shall be used to prompt a warning
+ -- when manipulating a null pointer and also to implement
+ -- the no aliasing parameter restriction.
+
+ if State_N = Moved then
+ Error_Msg_N ("?the source or one of its extensions has"
+ & " already been moved", N);
+ end if;
- return;
- end if;
+ declare
+ -- Set state to Borrowed to the path and any of its prefixes
- -- Set permissions to
- -- No for any extension with more .all
- -- W for any deep extension with same number of .all
- -- RW for any shallow extension with same number of .all
+ Tree : constant Perm_Tree_Access :=
+ Set_Perm_Prefixes (N, Moved);
- Set_Perm_Extensions_Move (Tree, Etype (N));
- end;
- end if;
+ begin
+ if Tree = null then
- -- Check permission RW
+ -- We went through a function call, no permission to
+ -- modify.
- when Super_Move =>
- if Perm_N /= Read_Write then
- Perm_Error (N, Read_Write, Perm_N);
return;
end if;
- declare
- -- Set permission to No to the path and any of its prefix up
- -- to the first .all and then W.
-
- Tree : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Move (N, Super_Move);
+ -- Set state to Borrowed on any strict extension of the path
- begin
- if Tree = null then
- -- We went through a function call, no permission to
- -- modify.
-
- return;
- end if;
-
- -- Set permissions to No on any strict extension of the path
+ Set_Perm_Extensions (Tree, Moved);
+ end;
- Set_Perm_Extensions (Tree, No_Access);
- end;
+ when Assign =>
- -- Check permission W
+ -- The lhs object in an assignment statement (including copy in
+ -- and copy back) should be in the Unrestricted state.
+ -- Otherwise the move is not allowed.
+ -- This applies to both stand-alone and composite objects.
- when Assign =>
- if Perm_N not in Write_Perm then
- Perm_Error (N, Write_Only, Perm_N);
- return;
- end if;
+ if State_N /= Unrestricted and State_N /= Moved then
+ Perm_Error (N, Unrestricted, State_N);
+ return;
+ end if;
- -- If the tree has an array component, then the permissions do
- -- not get modified by the assignment.
+ -- After assigning to a path nothing to do since it was in the
+ -- Unrestricted state and it would be refreshed to
+ -- Unrestricted.
- if Has_Array_Component (N) then
- return;
- end if;
+ when Borrow =>
- -- Same if has function component
+ -- Borrowing is only allowed on Unrestricted objects.
- if Has_Function_Component (N) then -- Dead code?
- return;
- end if;
+ if State_N /= Unrestricted and State_N /= Moved then
+ Perm_Error (N, Unrestricted, State_N);
+ end if;
- declare
- -- Get the permission tree for the path
+ if State_N = Moved then
+ Error_Msg_N ("?the source or one of its extensions has"
+ & " already been moved", N);
+ end if;
- Tree : constant Perm_Tree_Access :=
- Get_Perm_Tree (N);
+ declare
+ -- Set state to Borrowed to the path and any of its prefixes
- Dummy : Perm_Tree_Access;
+ Tree : constant Perm_Tree_Access :=
+ Set_Perm_Prefixes (N, Borrowed);
- begin
- if Tree = null then
- -- We went through a function call, no permission to
- -- modify.
+ begin
+ if Tree = null then
- return;
- end if;
+ -- We went through a function call, no permission to
+ -- modify.
- -- Set permission RW for it and all of its extensions
+ return;
+ end if;
- Tree.all.Tree.Permission := Read_Write;
+ -- Set state to Borrowed on any strict extension of the path
- Set_Perm_Extensions (Tree, Read_Write);
+ Set_Perm_Extensions (Tree, Borrowed);
+ end;
- -- Normalize the permission tree
+ when Observe =>
+ if State_N /= Unrestricted
+ and then State_N /= Observed
+ then
+ Perm_Error (N, Observed, State_N);
+ end if;
- Dummy := Set_Perm_Prefixes_Assign (N);
- end;
+ declare
+ -- Set permission to Observed on the path and any of its
+ -- prefixes if it is of a deep type. Actually, some operation
+ -- like reading from an object of access type is considered as
+ -- observe while it should not affect the permissions of
+ -- the considered tree.
- -- Check permission W
+ Tree : Perm_Tree_Access;
- when Borrow_Out =>
- if Perm_N not in Write_Perm then
- Perm_Error (N, Write_Only, Perm_N);
+ begin
+ if Is_Deep (Etype (N)) then
+ Tree := Set_Perm_Prefixes (N, Observed);
+ else
+ Tree := null;
end if;
- declare
- -- Set permission to No to the path and any of its prefixes
-
- Tree : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Borrow_Out (N);
-
- begin
- if Tree = null then
- -- We went through a function call, no permission to
- -- modify.
-
- return;
- end if;
-
- -- Set permissions to No on any strict extension of the path
+ if Tree = null then
- Set_Perm_Extensions (Tree, No_Access);
- end;
+ -- We went through a function call, no permission to
+ -- modify.
- when Observe =>
- if Perm_N not in Read_Perm then
- Perm_Error (N, Read_Only, Perm_N);
- end if;
-
- if Is_By_Copy_Type (Etype (N)) then
return;
end if;
- declare
- -- Set permission to No on the path and any of its prefixes
-
- Tree : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Observe (N);
-
- begin
- if Tree = null then
- -- We went through a function call, no permission to
- -- modify.
+ -- Set permissions to No on any strict extension of the path
- return;
- end if;
-
- -- Set permissions to No on any strict extension of the path
-
- Set_Perm_Extensions (Tree, Read_Only);
- end;
- end case;
- end;
+ Set_Perm_Extensions (Tree, Observed);
+ end;
+ end case;
end Process_Path;
-------------------------
@@ -4457,7 +3507,6 @@ package body Sem_SPARK is
-------------------------
procedure Return_Declarations (L : List_Id) is
-
procedure Return_Declaration (Decl : Node_Id);
-- Check correct permissions for every declared object
@@ -4468,6 +3517,7 @@ package body Sem_SPARK is
procedure Return_Declaration (Decl : Node_Id) is
begin
if Nkind (Decl) = N_Object_Declaration then
+
-- Check RW for object declared, unless the object has never been
-- initialized.
@@ -4477,15 +3527,6 @@ package body Sem_SPARK is
return;
end if;
- -- We ignore shallow unaliased. They are checked in flow analysis,
- -- allowing backward compatibility.
-
- if not Has_Alias (Defining_Identifier (Decl))
- and then Is_Shallow (Etype (Defining_Identifier (Decl)))
- then
- return;
- end if;
-
declare
Elem : constant Perm_Tree_Access :=
Get (Current_Perm_Env,
@@ -4493,22 +3534,23 @@ package body Sem_SPARK is
begin
if Elem = null then
+
-- Here we are on a declaration. Hence it should have been
-- added in the environment when analyzing this node with
-- mode Read. Hence it is not possible to find a null
-- pointer here.
-- Hash_Table_Error
+
raise Program_Error;
end if;
- if Permission (Elem) /= Read_Write then
- Perm_Error (Decl, Read_Write, Permission (Elem));
+ if Permission (Elem) /= Unrestricted then
+ Perm_Error (Decl, Unrestricted, Permission (Elem));
end if;
end;
end if;
end Return_Declaration;
-
-- Local Variables
N : Node_Id;
@@ -4528,7 +3570,6 @@ package body Sem_SPARK is
--------------------
procedure Return_Globals (Subp : Entity_Id) is
-
procedure Return_Globals_From_List
(First_Item : Node_Id;
Kind : Formal_Kind);
@@ -4557,7 +3598,7 @@ package body Sem_SPARK is
if Ekind (E) = E_Abstract_State then
null;
else
- Return_Parameter_Or_Global (E, Kind, Subp, Global_Var => True);
+ Return_The_Global (E, Kind, Subp);
end if;
Next_Global (Item);
end loop;
@@ -4572,7 +3613,9 @@ package body Sem_SPARK is
begin
case Global_Mode is
- when Name_Input | Name_Proof_In =>
+ when Name_Input
+ | Name_Proof_In
+ =>
Kind := E_In_Parameter;
when Name_Output =>
Kind := E_Out_Parameter;
@@ -4602,71 +3645,54 @@ package body Sem_SPARK is
-- Return_Parameter_Or_Global --
--------------------------------
- procedure Return_Parameter_Or_Global
- (Id : Entity_Id;
- Mode : Formal_Kind;
- Subp : Entity_Id;
- Global_Var : Boolean)
+ procedure Return_The_Global
+ (Id : Entity_Id;
+ Mode : Formal_Kind;
+ Subp : Entity_Id)
is
Elem : constant Perm_Tree_Access := Get (Current_Perm_Env, Id);
pragma Assert (Elem /= null);
begin
- -- Shallow unaliased parameters and globals cannot introduce pointer
- -- aliasing.
-
- if not Has_Alias (Id) and then Is_Shallow (Etype (Id)) then
- null;
-
-- Observed IN parameters and globals need not return a permission to
-- the caller.
- elsif Mode = E_In_Parameter
- and then (not Is_Borrowed_In (Id) or else Global_Var)
+ if Mode = E_In_Parameter
+
+ -- Check this for read-only globals.
+
then
- null;
+ if Permission (Elem) /= Unrestricted
+ and then Permission (Elem) /= Observed
+ then
+ Perm_Error_Subprogram_End
+ (E => Id,
+ Subp => Subp,
+ Perm => Observed,
+ Found_Perm => Permission (Elem));
+ end if;
- -- All other parameters and globals should return with mode RW to the
- -- caller.
+ -- All globals of mode out or in/out should return with mode
+ -- Unrestricted.
else
- if Permission (Elem) /= Read_Write then
+ if Permission (Elem) /= Unrestricted then
Perm_Error_Subprogram_End
(E => Id,
Subp => Subp,
- Perm => Read_Write,
+ Perm => Unrestricted,
Found_Perm => Permission (Elem));
end if;
end if;
- end Return_Parameter_Or_Global;
-
- -----------------------
- -- Return_Parameters --
- -----------------------
-
- procedure Return_Parameters (Subp : Entity_Id) is
- Formal : Entity_Id;
-
- begin
- Formal := First_Formal (Subp);
- while Present (Formal) loop
- Return_Parameter_Or_Global (Formal, Ekind (Formal), Subp, False);
- Next_Formal (Formal);
- end loop;
- end Return_Parameters;
+ end Return_The_Global;
-------------------------
-- Set_Perm_Extensions --
-------------------------
- procedure Set_Perm_Extensions
- (T : Perm_Tree_Access;
- P : Perm_Kind)
- is
+ procedure Set_Perm_Extensions (T : Perm_Tree_Access; P : Perm_Kind) is
procedure Free_Perm_Tree_Children (T : Perm_Tree_Access);
-
- procedure Free_Perm_Tree_Children (T : Perm_Tree_Access)
- is
+ procedure Free_Perm_Tree_Children (T : Perm_Tree_Access) is
begin
case Kind (T) is
when Entire_Object =>
@@ -4709,316 +3735,59 @@ package body Sem_SPARK is
end Set_Perm_Extensions;
------------------------------
- -- Set_Perm_Extensions_Move --
+ -- Set_Perm_Prefixes --
------------------------------
- procedure Set_Perm_Extensions_Move
- (T : Perm_Tree_Access;
- E : Entity_Id)
+ function Set_Perm_Prefixes
+ (N : Node_Id;
+ New_Perm : Perm_Kind)
+ return Perm_Tree_Access
is
begin
- if not Is_Node_Deep (T) then
- -- We are a shallow extension with same number of .all
-
- Set_Perm_Extensions (T, Read_Write);
- return;
- end if;
-
- -- We are a deep extension here (or the moved deep path)
-
- T.all.Tree.Permission := Write_Only;
-
- case T.all.Tree.Kind is
- -- Unroll the tree depending on the type
-
- when Entire_Object =>
- case Ekind (E) is
- when Scalar_Kind
- | E_String_Literal_Subtype
- =>
- Set_Perm_Extensions (T, No_Access);
-
- -- No need to unroll here, directly put sons to No_Access
-
- when Access_Kind =>
- if Ekind (E) in Access_Subprogram_Kind then
- null;
- else
- Set_Perm_Extensions (T, No_Access);
- end if;
-
- -- No unrolling done, too complicated
-
- when E_Class_Wide_Subtype
- | E_Class_Wide_Type
- | E_Incomplete_Type
- | E_Incomplete_Subtype
- | E_Exception_Type
- | E_Task_Type
- | E_Task_Subtype
- =>
- Set_Perm_Extensions (T, No_Access);
-
- -- Expand the tree. Replace the node with Array component.
-
- when E_Array_Type
- | E_Array_Subtype =>
- declare
- Son : Perm_Tree_Access;
-
- begin
- Son := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Node_Deep (T),
- Permission => Read_Write,
- Children_Permission => Read_Write));
-
- Set_Perm_Extensions_Move (Son, Component_Type (E));
-
- -- We change the current node from Entire_Object to
- -- Reference with Write_Only and the previous son.
-
- pragma Assert (Is_Node_Deep (T));
-
- T.all.Tree := (Kind => Array_Component,
- Is_Node_Deep => Is_Node_Deep (T),
- Permission => Write_Only,
- Get_Elem => Son);
- end;
-
- -- Unroll, and set permission extensions with component type
-
- when E_Record_Type
- | E_Record_Subtype
- | E_Record_Type_With_Private
- | E_Record_Subtype_With_Private
- | E_Protected_Type
- | E_Protected_Subtype
- =>
- declare
- -- Expand the tree. Replace the node with
- -- Record_Component.
-
- Elem : Node_Id;
-
- Son : Perm_Tree_Access;
-
- begin
- -- We change the current node from Entire_Object to
- -- Record_Component with same permission and an empty
- -- hash table as component list.
-
- pragma Assert (Is_Node_Deep (T));
-
- T.all.Tree :=
- (Kind => Record_Component,
- Is_Node_Deep => Is_Node_Deep (T),
- Permission => Write_Only,
- Component => Perm_Tree_Maps.Nil,
- Other_Components =>
- new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => True,
- Permission => Read_Write,
- Children_Permission => Read_Write)
- )
- );
-
- -- We fill the hash table with all sons of the record,
- -- with basic Entire_Objects nodes.
- Elem := First_Component_Or_Discriminant (E);
- while Present (Elem) loop
- Son := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Deep (Etype (Elem)),
- Permission => Read_Write,
- Children_Permission => Read_Write));
-
- Set_Perm_Extensions_Move (Son, Etype (Elem));
-
- Perm_Tree_Maps.Set
- (T.all.Tree.Component, Elem, Son);
-
- Next_Component_Or_Discriminant (Elem);
- end loop;
- end;
-
- when E_Private_Type
- | E_Private_Subtype
- | E_Limited_Private_Type
- | E_Limited_Private_Subtype
- =>
- Set_Perm_Extensions_Move (T, Underlying_Type (E));
-
- when others =>
- raise Program_Error;
- end case;
-
- when Reference =>
- -- Now the son does not have the same number of .all
- Set_Perm_Extensions (T, No_Access);
-
- when Array_Component =>
- Set_Perm_Extensions_Move (Get_Elem (T), Component_Type (E));
-
- when Record_Component =>
- declare
- Comp : Perm_Tree_Access;
- It : Node_Id;
-
- begin
- It := First_Component_Or_Discriminant (E);
- while It /= Empty loop
- Comp := Perm_Tree_Maps.Get (Component (T), It);
- pragma Assert (Comp /= null);
- Set_Perm_Extensions_Move (Comp, It);
- It := Next_Component_Or_Discriminant (E);
- end loop;
-
- Set_Perm_Extensions (Other_Components (T), No_Access);
- end;
- end case;
- end Set_Perm_Extensions_Move;
-
- ------------------------------
- -- Set_Perm_Prefixes_Assign --
- ------------------------------
-
- function Set_Perm_Prefixes_Assign (N : Node_Id) return Perm_Tree_Access is
- C : constant Perm_Tree_Access := Get_Perm_Tree (N);
-
- begin
- pragma Assert (Current_Checking_Mode = Assign);
-
- -- The function should not be called if has_function_component
-
- pragma Assert (C /= null);
-
- case Kind (C) is
- when Entire_Object =>
- pragma Assert (Children_Permission (C) = Read_Write);
-
- -- Maroua: Children could have read_only perm. Why Read_Write?
-
- C.all.Tree.Permission := Read_Write;
-
- when Reference =>
- pragma Assert (Get_All (C) /= null);
-
- C.all.Tree.Permission :=
- Lub (Permission (C), Permission (Get_All (C)));
-
- when Array_Component =>
- pragma Assert (C.all.Tree.Get_Elem /= null);
-
- -- Given that it is not possible to know which element has been
- -- assigned, then the permissions do not get changed in case of
- -- Array_Component.
-
- null;
-
- when Record_Component =>
- declare
- Comp : Perm_Tree_Access;
- Perm : Perm_Kind := Read_Write;
-
- begin
- -- We take the Glb of all the descendants, and then update the
- -- permission of the node with it.
-
- Comp := Perm_Tree_Maps.Get_First (Component (C));
- while Comp /= null loop
- Perm := Glb (Perm, Permission (Comp));
- Comp := Perm_Tree_Maps.Get_Next (Component (C));
- end loop;
-
- Perm := Glb (Perm, Permission (Other_Components (C)));
-
- C.all.Tree.Permission := Lub (Permission (C), Perm);
- end;
- end case;
case Nkind (N) is
- -- Base identifier. End recursion here.
-
when N_Identifier
| N_Expanded_Name
| N_Defining_Identifier
=>
- return null;
-
- when N_Type_Conversion
- | N_Unchecked_Type_Conversion
- | N_Qualified_Expression
- =>
- return Set_Perm_Prefixes_Assign (Expression (N));
-
- when N_Parameter_Specification =>
- raise Program_Error;
-
- -- Continue recursion on prefix
-
- when N_Selected_Component =>
- return Set_Perm_Prefixes_Assign (Prefix (N));
-
- -- Continue recursion on prefix
-
- when N_Indexed_Component
- | N_Slice
- =>
- return Set_Perm_Prefixes_Assign (Prefix (N));
-
- -- Continue recursion on prefix
-
- when N_Explicit_Dereference =>
- return Set_Perm_Prefixes_Assign (Prefix (N));
-
- when N_Function_Call =>
- raise Program_Error;
-
- when others =>
- raise Program_Error;
-
- end case;
- end Set_Perm_Prefixes_Assign;
-
- ----------------------------------
- -- Set_Perm_Prefixes_Borrow_Out --
- ----------------------------------
-
- function Set_Perm_Prefixes_Borrow_Out
- (N : Node_Id)
- return Perm_Tree_Access
- is
- begin
- pragma Assert (Current_Checking_Mode = Borrow_Out);
-
- case Nkind (N) is
- -- Base identifier. Set permission to No.
+ if Nkind (N) = N_Defining_Identifier
+ and then New_Perm = Borrowed
+ then
+ raise Program_Error;
+ end if;
- when N_Identifier
- | N_Expanded_Name
- =>
declare
- P : constant Node_Id := Entity (N);
+ P : Node_Id;
+ C : Perm_Tree_Access;
- C : constant Perm_Tree_Access :=
- Get (Current_Perm_Env, Unique_Entity (P));
+ begin
+ if Nkind (N) = N_Defining_Identifier then
+ P := N;
+ else
+ P := Entity (N);
+ end if;
+ C := Get (Current_Perm_Env, Unique_Entity (P));
pragma Assert (C /= null);
- begin
-- Setting the initialization map to True, so that this
-- variable cannot be ignored anymore when looking at end
-- of elaboration of package.
Set (Current_Initialization_Map, Unique_Entity (P), True);
+ if New_Perm = Observed
+ and then C = null
+ then
- C.all.Tree.Permission := No_Access;
+ -- No null possible here, there are no parents for the path.
+ -- This means we are using a global variable without adding
+ -- it in environment with a global aspect.
+
+ Illegal_Global_Usage (N);
+ end if;
+
+ C.all.Tree.Permission := New_Perm;
return C;
end;
@@ -5026,11 +3795,9 @@ package body Sem_SPARK is
| N_Unchecked_Type_Conversion
| N_Qualified_Expression
=>
- return Set_Perm_Prefixes_Borrow_Out (Expression (N));
+ return Set_Perm_Prefixes (Expression (N), New_Perm);
- when N_Parameter_Specification
- | N_Defining_Identifier
- =>
+ when N_Parameter_Specification =>
raise Program_Error;
-- We set the permission tree of its prefix, and then we extract
@@ -5041,19 +3808,16 @@ package body Sem_SPARK is
when N_Selected_Component =>
declare
C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Borrow_Out (Prefix (N));
+ Set_Perm_Prefixes (Prefix (N), New_Perm);
begin
if C = null then
+
-- We went through a function call, do nothing
return null;
end if;
- -- The permission of the returned node should be No
-
- pragma Assert (Permission (C) = No_Access);
-
pragma Assert (Kind (C) = Entire_Object
or else Kind (C) = Record_Component);
@@ -5075,11 +3839,10 @@ package body Sem_SPARK is
end if;
pragma Assert (Selected_C /= null);
-
- Selected_C.all.Tree.Permission := No_Access;
-
+ Selected_C.all.Tree.Permission := New_Perm;
return Selected_C;
end;
+
elsif Kind (C) = Entire_Object then
declare
-- Expand the tree. Replace the node with
@@ -5094,9 +3857,8 @@ package body Sem_SPARK is
-- We create the unrolled nodes, that will all have same
-- permission than parent.
- Son : Perm_Tree_Access;
-
- ChildrenPerm : constant Perm_Kind :=
+ Son : Perm_Tree_Access;
+ Children_Perm : constant Perm_Kind :=
Children_Permission (C);
begin
@@ -5114,12 +3876,13 @@ package body Sem_SPARK is
(Tree =>
(Kind => Entire_Object,
Is_Node_Deep => True,
- Permission => ChildrenPerm,
- Children_Permission => ChildrenPerm)
+ Permission => Children_Perm,
+ Children_Permission => Children_Perm)
));
-- We fill the hash table with all sons of the record,
-- with basic Entire_Objects nodes.
+
Elem := First_Component_Or_Discriminant
(Etype (Prefix (N)));
@@ -5128,23 +3891,19 @@ package body Sem_SPARK is
(Tree =>
(Kind => Entire_Object,
Is_Node_Deep => Is_Deep (Etype (Elem)),
- Permission => ChildrenPerm,
- Children_Permission => ChildrenPerm));
-
- Perm_Tree_Maps.Set
- (C.all.Tree.Component, Elem, Son);
+ Permission => Children_Perm,
+ Children_Permission => Children_Perm));
+ Perm_Tree_Maps.Set (C.all.Tree.Component, Elem, Son);
Next_Component_Or_Discriminant (Elem);
end loop;
-
- -- Now we set the right field to No_Access, and then we
+ -- Now we set the right field to Borrowed, and then we
-- return the tree to the sons, so that the recursion can
-- continue.
declare
Selected_Component : constant Entity_Id :=
Entity (Selector_Name (N));
-
Selected_C : Perm_Tree_Access :=
Perm_Tree_Maps.Get
(Component (C), Selected_Component);
@@ -5155,9 +3914,7 @@ package body Sem_SPARK is
end if;
pragma Assert (Selected_C /= null);
-
- Selected_C.all.Tree.Permission := No_Access;
-
+ Selected_C.all.Tree.Permission := New_Perm;
return Selected_C;
end;
end;
@@ -5176,33 +3933,28 @@ package body Sem_SPARK is
=>
declare
C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Borrow_Out (Prefix (N));
+ Set_Perm_Prefixes (Prefix (N), New_Perm);
begin
if C = null then
+
-- We went through a function call, do nothing
return null;
end if;
- -- The permission of the returned node should be either W
- -- (because the recursive call sets <= Write_Only) or No
- -- (if another path has been moved with 'Access).
-
- pragma Assert (Permission (C) = No_Access);
-
pragma Assert (Kind (C) = Entire_Object
or else Kind (C) = Array_Component);
if Kind (C) = Array_Component then
+
-- The tree is unfolded. We just modify the permission and
-- return the elem subtree.
pragma Assert (Get_Elem (C) /= null);
-
- C.all.Tree.Get_Elem.all.Tree.Permission := No_Access;
-
+ C.all.Tree.Get_Elem.all.Tree.Permission := New_Perm;
return Get_Elem (C);
+
elsif Kind (C) = Entire_Object then
declare
-- Expand the tree. Replace node with Array_Component.
@@ -5214,18 +3966,21 @@ package body Sem_SPARK is
(Tree =>
(Kind => Entire_Object,
Is_Node_Deep => Is_Node_Deep (C),
- Permission => No_Access,
+ Permission => New_Perm,
Children_Permission => Children_Permission (C)));
+ -- Children_Permission => Children_Permission (C)
+ -- this line should be checked maybe New_Perm
+ -- instead of Children_Permission (C)
+
-- We change the current node from Entire_Object
-- to Array_Component with same permission and the
-- previously defined son.
C.all.Tree := (Kind => Array_Component,
Is_Node_Deep => Is_Node_Deep (C),
- Permission => No_Access,
+ Permission => New_Perm,
Get_Elem => Son);
-
return Get_Elem (C);
end;
else
@@ -5241,30 +3996,28 @@ package body Sem_SPARK is
when N_Explicit_Dereference =>
declare
C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Borrow_Out (Prefix (N));
+ Set_Perm_Prefixes (Prefix (N), New_Perm);
begin
if C = null then
+
-- We went through a function call. Do nothing.
return null;
end if;
- -- The permission of the returned node should be No
-
- pragma Assert (Permission (C) = No_Access);
pragma Assert (Kind (C) = Entire_Object
or else Kind (C) = Reference);
if Kind (C) = Reference then
+
-- The tree is unfolded. We just modify the permission and
-- return the elem subtree.
pragma Assert (Get_All (C) /= null);
-
- C.all.Tree.Get_All.all.Tree.Permission := No_Access;
-
+ C.all.Tree.Get_All.all.Tree.Permission := New_Perm;
return Get_All (C);
+
elsif Kind (C) = Entire_Object then
declare
-- Expand the tree. Replace the node with Reference.
@@ -5276,21 +4029,20 @@ package body Sem_SPARK is
(Tree =>
(Kind => Entire_Object,
Is_Node_Deep => Is_Deep (Etype (N)),
- Permission => No_Access,
+ Permission => New_Perm,
Children_Permission => Children_Permission (C)));
-- We change the current node from Entire_Object to
- -- Reference with No_Access and the previous son.
+ -- Reference with Borrowed and the previous son.
pragma Assert (Is_Node_Deep (C));
-
C.all.Tree := (Kind => Reference,
Is_Node_Deep => Is_Node_Deep (C),
- Permission => No_Access,
+ Permission => New_Perm,
Get_All => Son);
-
return Get_All (C);
end;
+
else
raise Program_Error;
end if;
@@ -5302,59 +4054,34 @@ package body Sem_SPARK is
when others =>
raise Program_Error;
end case;
- end Set_Perm_Prefixes_Borrow_Out;
+ end Set_Perm_Prefixes;
- ----------------------------
- -- Set_Perm_Prefixes_Move --
- ----------------------------
+ ------------------------------
+ -- Set_Perm_Prefixes_Borrow --
+ ------------------------------
- function Set_Perm_Prefixes_Move
- (N : Node_Id; Mode : Checking_Mode)
- return Perm_Tree_Access
+ function Set_Perm_Prefixes_Borrow (N : Node_Id) return Perm_Tree_Access
is
begin
+ pragma Assert (Current_Checking_Mode = Borrow);
case Nkind (N) is
- -- Base identifier. Set permission to W or No depending on Mode.
-
when N_Identifier
| N_Expanded_Name
=>
declare
P : constant Node_Id := Entity (N);
C : constant Perm_Tree_Access :=
- Get (Current_Perm_Env, Unique_Entity (P));
+ Get (Current_Perm_Env, Unique_Entity (P));
+ pragma Assert (C /= null);
begin
- -- The base tree can be RW (first move from this base path) or
- -- W (already some extensions values moved), or even No_Access
- -- (extensions moved with 'Access). But it cannot be Read_Only
- -- (we get an error).
-
- if Permission (C) = Read_Only then
- raise Unrecoverable_Error;
- end if;
-
-- Setting the initialization map to True, so that this
-- variable cannot be ignored anymore when looking at end
-- of elaboration of package.
Set (Current_Initialization_Map, Unique_Entity (P), True);
-
- if C = null then
- -- No null possible here, there are no parents for the path.
- -- This means we are using a global variable without adding
- -- it in environment with a global aspect.
-
- Illegal_Global_Usage (N);
- end if;
-
- if Mode = Super_Move then
- C.all.Tree.Permission := No_Access;
- else
- C.all.Tree.Permission := Glb (Write_Only, Permission (C));
- end if;
-
+ C.all.Tree.Permission := Borrowed;
return C;
end;
@@ -5362,7 +4089,7 @@ package body Sem_SPARK is
| N_Unchecked_Type_Conversion
| N_Qualified_Expression
=>
- return Set_Perm_Prefixes_Move (Expression (N), Mode);
+ return Set_Perm_Prefixes_Borrow (Expression (N));
when N_Parameter_Specification
| N_Defining_Identifier
@@ -5370,79 +4097,51 @@ package body Sem_SPARK is
raise Program_Error;
-- We set the permission tree of its prefix, and then we extract
- -- from the returned pointer our subtree and assign an adequate
+ -- our subtree from the returned pointer and assign an adequate
-- permission to it, if unfolded. If folded, we unroll the tree
- -- at one step.
+ -- in one step.
when N_Selected_Component =>
declare
C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Move (Prefix (N), Mode);
+ Set_Perm_Prefixes_Borrow (Prefix (N));
begin
if C = null then
+
-- We went through a function call, do nothing
return null;
end if;
- -- The permission of the returned node should be either W
- -- (because the recursive call sets <= Write_Only) or No
- -- (if another path has been moved with 'Access).
-
- pragma Assert (Permission (C) = No_Access
- or else Permission (C) = Write_Only);
-
- if Mode = Super_Move then
- -- The permission of the returned node should be No (thanks
- -- to the recursion).
-
- pragma Assert (Permission (C) = No_Access);
- null;
- end if;
+ -- The permission of the returned node should be No
+ pragma Assert (Permission (C) = Borrowed);
pragma Assert (Kind (C) = Entire_Object
or else Kind (C) = Record_Component);
if Kind (C) = Record_Component then
+
-- The tree is unfolded. We just modify the permission and
-- return the record subtree.
declare
Selected_Component : constant Entity_Id :=
Entity (Selector_Name (N));
-
Selected_C : Perm_Tree_Access :=
Perm_Tree_Maps.Get
(Component (C), Selected_Component);
begin
if Selected_C = null then
- -- If the hash table returns no element, then we fall
- -- into the part of Other_Components.
- pragma Assert (Is_Tagged_Type (Etype (Prefix (N))));
-
Selected_C := Other_Components (C);
end if;
pragma Assert (Selected_C /= null);
-
- -- The Selected_C can have permissions:
- -- RW : first move in this path
- -- W : Already other moves in this path
- -- No : Already other moves with 'Access
-
- pragma Assert (Permission (Selected_C) /= Read_Only);
- if Mode = Super_Move then
- Selected_C.all.Tree.Permission := No_Access;
- else
- Selected_C.all.Tree.Permission :=
- Glb (Write_Only, Permission (Selected_C));
-
- end if;
-
+ Selected_C.all.Tree.Permission := Borrowed;
return Selected_C;
end;
+
elsif Kind (C) = Entire_Object then
declare
-- Expand the tree. Replace the node with
@@ -5454,17 +4153,12 @@ package body Sem_SPARK is
Hashtbl : Perm_Tree_Maps.Instance;
- -- We are in Move or Super_Move mode, hence we can assume
- -- that the Children_permission is RW, given that there
- -- are no other paths that could have been moved.
-
- pragma Assert (Children_Permission (C) = Read_Write);
-
- -- We create the unrolled nodes, that will all have RW
- -- permission given that we are in move mode. We will
- -- then set the right node to W.
+ -- We create the unrolled nodes, that will all have same
+ -- permission than parent.
Son : Perm_Tree_Access;
+ ChildrenPerm : constant Perm_Kind :=
+ Children_Permission (C);
begin
-- We change the current node from Entire_Object to
@@ -5472,21 +4166,22 @@ package body Sem_SPARK is
-- hash table as component list.
C.all.Tree :=
- (Kind => Record_Component,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => Permission (C),
- Component => Hashtbl,
+ (Kind => Record_Component,
+ Is_Node_Deep => Is_Node_Deep (C),
+ Permission => Permission (C),
+ Component => Hashtbl,
Other_Components =>
new Perm_Tree_Wrapper'
(Tree =>
(Kind => Entire_Object,
Is_Node_Deep => True,
- Permission => Read_Write,
- Children_Permission => Read_Write)
+ Permission => ChildrenPerm,
+ Children_Permission => ChildrenPerm)
));
-- We fill the hash table with all sons of the record,
-- with basic Entire_Objects nodes.
+
Elem := First_Component_Or_Discriminant
(Etype (Prefix (N)));
@@ -5495,26 +4190,21 @@ package body Sem_SPARK is
(Tree =>
(Kind => Entire_Object,
Is_Node_Deep => Is_Deep (Etype (Elem)),
- Permission => Read_Write,
- Children_Permission => Read_Write));
-
- Perm_Tree_Maps.Set
- (C.all.Tree.Component, Elem, Son);
-
+ Permission => ChildrenPerm,
+ Children_Permission => ChildrenPerm));
+ Perm_Tree_Maps.Set (C.all.Tree.Component, Elem, Son);
Next_Component_Or_Discriminant (Elem);
end loop;
- -- Now we set the right field to Write_Only or No_Access
- -- depending on mode, and then we return the tree to the
- -- sons, so that the recursion can continue.
+ -- Now we set the right field to Borrowed, and then we
+ -- return the tree to the sons, so that the recursion can
+ -- continue.
declare
Selected_Component : constant Entity_Id :=
Entity (Selector_Name (N));
-
- Selected_C : Perm_Tree_Access :=
- Perm_Tree_Maps.Get
- (Component (C), Selected_Component);
+ Selected_C : Perm_Tree_Access := Perm_Tree_Maps.Get
+ (Component (C), Selected_Component);
begin
if Selected_C = null then
@@ -5522,22 +4212,11 @@ package body Sem_SPARK is
end if;
pragma Assert (Selected_C /= null);
-
- -- Given that this is a newly created Select_C, we can
- -- safely assume that its permission is Read_Write.
-
- pragma Assert (Permission (Selected_C) =
- Read_Write);
-
- if Mode = Super_Move then
- Selected_C.all.Tree.Permission := No_Access;
- else
- Selected_C.all.Tree.Permission := Write_Only;
- end if;
-
+ Selected_C.all.Tree.Permission := Borrowed;
return Selected_C;
end;
end;
+
else
raise Program_Error;
end if;
@@ -5545,72 +4224,41 @@ package body Sem_SPARK is
-- We set the permission tree of its prefix, and then we extract
-- from the returned pointer the subtree and assign an adequate
- -- permission to it, if unfolded. If folded, we unroll the tree
- -- at one step.
+ -- permission to it, if unfolded. If folded, we unroll the tree in
+ -- one step.
when N_Indexed_Component
| N_Slice
=>
declare
C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Move (Prefix (N), Mode);
+ Set_Perm_Prefixes_Borrow (Prefix (N));
begin
if C = null then
+
-- We went through a function call, do nothing
return null;
end if;
- -- The permission of the returned node should be either
- -- W (because the recursive call sets <= Write_Only)
- -- or No (if another path has been moved with 'Access)
-
- if Mode = Super_Move then
- pragma Assert (Permission (C) = No_Access);
- null;
- else
- pragma Assert (Permission (C) = Write_Only
- or else Permission (C) = No_Access);
- null;
- end if;
-
+ pragma Assert (Permission (C) = Borrowed);
pragma Assert (Kind (C) = Entire_Object
or else Kind (C) = Array_Component);
if Kind (C) = Array_Component then
+
-- The tree is unfolded. We just modify the permission and
-- return the elem subtree.
- if Get_Elem (C) = null then
- -- Hash_Table_Error
- raise Program_Error;
- end if;
-
- -- The Get_Elem can have permissions :
- -- RW : first move in this path
- -- W : Already other moves in this path
- -- No : Already other moves with 'Access
-
- pragma Assert (Permission (Get_Elem (C)) /= Read_Only);
-
- if Mode = Super_Move then
- C.all.Tree.Get_Elem.all.Tree.Permission := No_Access;
- else
- C.all.Tree.Get_Elem.all.Tree.Permission :=
- Glb (Write_Only, Permission (Get_Elem (C)));
- end if;
-
+ pragma Assert (Get_Elem (C) /= null);
+ C.all.Tree.Get_Elem.all.Tree.Permission := Borrowed;
return Get_Elem (C);
+
elsif Kind (C) = Entire_Object then
declare
-- Expand the tree. Replace node with Array_Component.
- -- We are in move mode, hence we can assume that the
- -- Children_permission is RW.
-
- pragma Assert (Children_Permission (C) = Read_Write);
-
Son : Perm_Tree_Access;
begin
@@ -5618,14 +4266,8 @@ package body Sem_SPARK is
(Tree =>
(Kind => Entire_Object,
Is_Node_Deep => Is_Node_Deep (C),
- Permission => Read_Write,
- Children_Permission => Read_Write));
-
- if Mode = Super_Move then
- Son.all.Tree.Permission := No_Access;
- else
- Son.all.Tree.Permission := Write_Only;
- end if;
+ Permission => Borrowed,
+ Children_Permission => Children_Permission (C)));
-- We change the current node from Entire_Object
-- to Array_Component with same permission and the
@@ -5633,11 +4275,11 @@ package body Sem_SPARK is
C.all.Tree := (Kind => Array_Component,
Is_Node_Deep => Is_Node_Deep (C),
- Permission => Permission (C),
+ Permission => Borrowed,
Get_Elem => Son);
-
return Get_Elem (C);
end;
+
else
raise Program_Error;
end if;
@@ -5651,415 +4293,56 @@ package body Sem_SPARK is
when N_Explicit_Dereference =>
declare
C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Move (Prefix (N), Move);
+ Set_Perm_Prefixes_Borrow (Prefix (N));
begin
if C = null then
- -- We went through a function call: do nothing
-
- return null;
- end if;
-
- -- The permission of the returned node should be only
- -- W (because the recursive call sets <= Write_Only)
- -- No is NOT POSSIBLE here
-
- pragma Assert (Permission (C) = Write_Only);
-
- pragma Assert (Kind (C) = Entire_Object
- or else Kind (C) = Reference);
-
- if Kind (C) = Reference then
- -- The tree is unfolded. We just modify the permission and
- -- return the elem subtree.
-
- if Get_All (C) = null then
- -- Hash_Table_Error
- raise Program_Error;
- end if;
-
- -- The Get_All can have permissions :
- -- RW : first move in this path
- -- W : Already other moves in this path
- -- No : Already other moves with 'Access
-
- pragma Assert (Permission (Get_All (C)) /= Read_Only);
-
- if Mode = Super_Move then
- C.all.Tree.Get_All.all.Tree.Permission := No_Access;
- else
- Get_All (C).all.Tree.Permission :=
- Glb (Write_Only, Permission (Get_All (C)));
- end if;
- return Get_All (C);
- elsif Kind (C) = Entire_Object then
- declare
- -- Expand the tree. Replace the node with Reference.
-
- -- We are in Move or Super_Move mode, hence we can assume
- -- that the Children_permission is RW.
-
- pragma Assert (Children_Permission (C) = Read_Write);
-
- Son : Perm_Tree_Access;
-
- begin
- Son := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Deep (Etype (N)),
- Permission => Read_Write,
- Children_Permission => Read_Write));
-
- if Mode = Super_Move then
- Son.all.Tree.Permission := No_Access;
- else
- Son.all.Tree.Permission := Write_Only;
- end if;
-
- -- We change the current node from Entire_Object to
- -- Reference with Write_Only and the previous son.
-
- pragma Assert (Is_Node_Deep (C));
-
- C.all.Tree := (Kind => Reference,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => Write_Only,
- -- Write_only is equal to C.Permission
- Get_All => Son);
-
- return Get_All (C);
- end;
- else
- raise Program_Error;
- end if;
- end;
-
- when N_Function_Call =>
- return null;
-
- when others =>
- raise Program_Error;
- end case;
-
- end Set_Perm_Prefixes_Move;
-
- -------------------------------
- -- Set_Perm_Prefixes_Observe --
- -------------------------------
-
- function Set_Perm_Prefixes_Observe
- (N : Node_Id)
- return Perm_Tree_Access
- is
- begin
- pragma Assert (Current_Checking_Mode = Observe);
-
- case Nkind (N) is
- -- Base identifier. Set permission to R.
-
- when N_Identifier
- | N_Expanded_Name
- | N_Defining_Identifier
- =>
- declare
- P : Node_Id;
- C : Perm_Tree_Access;
-
- begin
- if Nkind (N) = N_Defining_Identifier then
- P := N;
- else
- P := Entity (N);
- end if;
-
- C := Get (Current_Perm_Env, Unique_Entity (P));
- -- Setting the initialization map to True, so that this
- -- variable cannot be ignored anymore when looking at end
- -- of elaboration of package.
-
- Set (Current_Initialization_Map, Unique_Entity (P), True);
-
- if C = null then
- -- No null possible here, there are no parents for the path.
- -- This means we are using a global variable without adding
- -- it in environment with a global aspect.
-
- Illegal_Global_Usage (N);
- end if;
-
- C.all.Tree.Permission := Glb (Read_Only, Permission (C));
-
- return C;
- end;
-
- when N_Type_Conversion
- | N_Unchecked_Type_Conversion
- | N_Qualified_Expression
- =>
- return Set_Perm_Prefixes_Observe (Expression (N));
-
- when N_Parameter_Specification =>
- raise Program_Error;
-
- -- We set the permission tree of its prefix, and then we extract
- -- from the returned pointer our subtree and assign an adequate
- -- permission to it, if unfolded. If folded, we unroll the tree
- -- at one step.
-
- when N_Selected_Component =>
- declare
- C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Observe (Prefix (N));
-
- begin
- if C = null then
- -- We went through a function call, do nothing
-
- return null;
- end if;
-
- pragma Assert (Kind (C) = Entire_Object
- or else Kind (C) = Record_Component);
-
- if Kind (C) = Record_Component then
- -- The tree is unfolded. We just modify the permission and
- -- return the record subtree. We put the permission to the
- -- glb of read_only and its current permission, to consider
- -- the case of observing x.y while x.z has been moved. Then
- -- x should be No_Access.
-
- declare
- Selected_Component : constant Entity_Id :=
- Entity (Selector_Name (N));
-
- Selected_C : Perm_Tree_Access :=
- Perm_Tree_Maps.Get
- (Component (C), Selected_Component);
-
- begin
- if Selected_C = null then
- Selected_C := Other_Components (C);
- end if;
-
- pragma Assert (Selected_C /= null);
-
- Selected_C.all.Tree.Permission :=
- Glb (Read_Only, Permission (Selected_C));
-
- return Selected_C;
- end;
- elsif Kind (C) = Entire_Object then
- declare
- -- Expand the tree. Replace the node with
- -- Record_Component.
-
- Elem : Node_Id;
-
- -- Create an empty hash table
-
- Hashtbl : Perm_Tree_Maps.Instance;
-
- -- We create the unrolled nodes, that will all have RW
- -- permission given that we are in move mode. We will
- -- then set the right node to W.
-
- Son : Perm_Tree_Access;
-
- Child_Perm : constant Perm_Kind :=
- Children_Permission (C);
-
- begin
- -- We change the current node from Entire_Object to
- -- Record_Component with same permission and an empty
- -- hash table as component list.
- C.all.Tree :=
- (Kind => Record_Component,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => Permission (C),
- Component => Hashtbl,
- Other_Components =>
- new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => True,
- Permission => Child_Perm,
- Children_Permission => Child_Perm)
- ));
-
- -- We fill the hash table with all sons of the record,
- -- with basic Entire_Objects nodes.
- Elem := First_Component_Or_Discriminant
- (Etype (Prefix (N)));
-
- while Present (Elem) loop
- Son := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Deep (Etype (Elem)),
- Permission => Child_Perm,
- Children_Permission => Child_Perm));
-
- Perm_Tree_Maps.Set
- (C.all.Tree.Component, Elem, Son);
-
- Next_Component_Or_Discriminant (Elem);
- end loop;
-
- -- Now we set the right field to Read_Only. and then we
- -- return the tree to the sons, so that the recursion can
- -- continue.
-
- declare
- Selected_Component : constant Entity_Id :=
- Entity (Selector_Name (N));
-
- Selected_C : Perm_Tree_Access :=
- Perm_Tree_Maps.Get
- (Component (C), Selected_Component);
-
- begin
- if Selected_C = null then
- Selected_C := Other_Components (C);
- end if;
-
- pragma Assert (Selected_C /= null);
-
- Selected_C.all.Tree.Permission :=
- Glb (Read_Only, Child_Perm);
-
- return Selected_C;
- end;
- end;
- else
- raise Program_Error;
- end if;
- end;
-
- -- We set the permission tree of its prefix, and then we extract from
- -- the returned pointer the subtree and assign an adequate permission
- -- to it, if unfolded. If folded, we unroll the tree at one step.
-
- when N_Indexed_Component
- | N_Slice
- =>
- declare
- C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Observe (Prefix (N));
-
- begin
- if C = null then
- -- We went through a function call, do nothing
+ -- We went through a function call. Do nothing.
return null;
end if;
- pragma Assert (Kind (C) = Entire_Object
- or else Kind (C) = Array_Component);
-
- if Kind (C) = Array_Component then
- -- The tree is unfolded. We just modify the permission and
- -- return the elem subtree.
-
- pragma Assert (Get_Elem (C) /= null);
-
- C.all.Tree.Get_Elem.all.Tree.Permission :=
- Glb (Read_Only, Permission (Get_Elem (C)));
-
- return Get_Elem (C);
- elsif Kind (C) = Entire_Object then
- declare
- -- Expand the tree. Replace node with Array_Component.
-
- Son : Perm_Tree_Access;
-
- Child_Perm : constant Perm_Kind :=
- Glb (Read_Only, Children_Permission (C));
-
- begin
- Son := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => Child_Perm,
- Children_Permission => Child_Perm));
-
- -- We change the current node from Entire_Object
- -- to Array_Component with same permission and the
- -- previously defined son.
-
- C.all.Tree := (Kind => Array_Component,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => Child_Perm,
- Get_Elem => Son);
-
- return Get_Elem (C);
- end;
-
- else
- raise Program_Error;
- end if;
- end;
-
- -- We set the permission tree of its prefix, and then we extract from
- -- the returned pointer the subtree and assign an adequate permission
- -- to it, if unfolded. If folded, we unroll the tree at one step.
-
- when N_Explicit_Dereference =>
- declare
- C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Observe (Prefix (N));
-
- begin
- if C = null then
- -- We went through a function call, do nothing
-
- return null;
- end if;
+ -- The permission of the returned node should be No
+ pragma Assert (Permission (C) = Borrowed);
pragma Assert (Kind (C) = Entire_Object
or else Kind (C) = Reference);
if Kind (C) = Reference then
+
-- The tree is unfolded. We just modify the permission and
-- return the elem subtree.
pragma Assert (Get_All (C) /= null);
-
- C.all.Tree.Get_All.all.Tree.Permission :=
- Glb (Read_Only, Permission (Get_All (C)));
-
+ C.all.Tree.Get_All.all.Tree.Permission := Borrowed;
return Get_All (C);
+
elsif Kind (C) = Entire_Object then
declare
-- Expand the tree. Replace the node with Reference.
Son : Perm_Tree_Access;
- Child_Perm : constant Perm_Kind :=
- Glb (Read_Only, Children_Permission (C));
-
begin
Son := new Perm_Tree_Wrapper'
(Tree =>
(Kind => Entire_Object,
Is_Node_Deep => Is_Deep (Etype (N)),
- Permission => Child_Perm,
- Children_Permission => Child_Perm));
+ Permission => Borrowed,
+ Children_Permission => Children_Permission (C)));
-- We change the current node from Entire_Object to
- -- Reference with Write_Only and the previous son.
+ -- Reference with Borrowed and the previous son.
pragma Assert (Is_Node_Deep (C));
-
C.all.Tree := (Kind => Reference,
Is_Node_Deep => Is_Node_Deep (C),
- Permission => Child_Perm,
+ Permission => Borrowed,
Get_All => Son);
-
return Get_All (C);
end;
+
else
raise Program_Error;
end if;
@@ -6070,16 +4353,14 @@ package body Sem_SPARK is
when others =>
raise Program_Error;
-
end case;
- end Set_Perm_Prefixes_Observe;
+ end Set_Perm_Prefixes_Borrow;
-------------------
-- Setup_Globals --
-------------------
procedure Setup_Globals (Subp : Entity_Id) is
-
procedure Setup_Globals_From_List
(First_Item : Node_Id;
Kind : Formal_Kind);
@@ -6123,12 +4404,17 @@ package body Sem_SPARK is
begin
case Global_Mode is
- when Name_Input | Name_Proof_In =>
+ when Name_Input
+ | Name_Proof_In
+ =>
Kind := E_In_Parameter;
+
when Name_Output =>
Kind := E_Out_Parameter;
+
when Name_In_Out =>
Kind := E_In_Out_Parameter;
+
when others =>
raise Program_Error;
end case;
@@ -6165,36 +4451,57 @@ package body Sem_SPARK is
(Tree =>
(Kind => Entire_Object,
Is_Node_Deep => Is_Deep (Etype (Id)),
- Permission => Read_Write,
- Children_Permission => Read_Write));
+ Permission => Unrestricted,
+ Children_Permission => Unrestricted));
case Mode is
- when E_In_Parameter =>
- -- Borrowed IN: RW for everybody
+ -- All out and in out parameters are considered to be unrestricted.
+ -- They are whether borrowed or moved. Ada Rules would restrict
+ -- these permissions further. For example an in parameter cannot
+ -- be written.
- if Is_Borrowed_In (Id) and not Global_Var then
- Elem.all.Tree.Permission := Read_Write;
- Elem.all.Tree.Children_Permission := Read_Write;
+ -- In the following we deal with in parameters that can be observed.
+ -- We only consider the observing cases.
- -- Observed IN: R for everybody
+ when E_In_Parameter =>
- else
- Elem.all.Tree.Permission := Read_Only;
- Elem.all.Tree.Children_Permission := Read_Only;
- end if;
+ -- Handling global variables as in parameters here
+ -- Remove the following condition once decided how globals
+ -- should be considered.
+
+ if not Global_Var then
+ if (Is_Access_Type (Etype (Id))
+ and then Is_Access_Constant (Etype (Id))
+ and then Is_Anonymous_Access_Type (Etype (Id)))
+ or else
+ (not Is_Access_Type (Etype (Id))
+ and then Is_Deep (Etype (Id))
+ and then not Is_Anonymous_Access_Type (Etype (Id)))
+ then
+ Elem.all.Tree.Permission := Observed;
+ Elem.all.Tree.Children_Permission := Observed;
- -- OUT: borrow, but callee has W only
+ else
+ Elem.all.Tree.Permission := Unrestricted;
+ Elem.all.Tree.Children_Permission := Unrestricted;
+ end if;
- when E_Out_Parameter =>
- Elem.all.Tree.Permission := Write_Only;
- Elem.all.Tree.Children_Permission := Write_Only;
+ else
+ Elem.all.Tree.Permission := Observed;
+ Elem.all.Tree.Children_Permission := Observed;
+ end if;
- -- IN OUT: borrow and callee has RW
+ -- When out or in/out formal or global parameters, we set them to
+ -- the Unrestricted state. "We want to be able to assume that all
+ -- relevant writable globals are unrestricted when a subprogram
+ -- starts executing". Formal parameters of mode out or in/out
+ -- are whether Borrowers or the targets of a move operation:
+ -- they start theirs lives in the subprogram as Unrestricted.
- when E_In_Out_Parameter =>
- Elem.all.Tree.Permission := Read_Write;
- Elem.all.Tree.Children_Permission := Read_Write;
+ when others =>
+ Elem.all.Tree.Permission := Unrestricted;
+ Elem.all.Tree.Children_Permission := Unrestricted;
end case;
Set (Current_Perm_Env, Id, Elem);
@@ -6204,9 +4511,7 @@ package body Sem_SPARK is
-- Setup_Parameters --
----------------------
- procedure Setup_Parameters (Subp : Entity_Id) is
- Formal : Entity_Id;
-
+ procedure Setup_Parameters (Subp : Entity_Id) is Formal : Entity_Id;
begin
Formal := First_Formal (Subp);
while Present (Formal) loop
@@ -6216,4 +4521,85 @@ package body Sem_SPARK is
end loop;
end Setup_Parameters;
+ -------------------------------
+ -- Has_Ownership_Aspect_True --
+ -------------------------------
+
+ function Has_Ownership_Aspect_True
+ (N : Entity_Id;
+ Msg : String)
+ return Boolean
+ is
+ begin
+ case Ekind (Etype (N)) is
+ when Access_Kind =>
+ if Ekind (Etype (N)) = E_General_Access_Type then
+ Error_Msg_NE (Msg & " & not allowed " &
+ "(Named General Access type)", N, N);
+ return False;
+
+ else
+ return True;
+ end if;
+
+ when E_Array_Type
+ | E_Array_Subtype
+ =>
+ declare
+ Com_Ty : constant Node_Id := Component_Type (Etype (N));
+ Ret : Boolean := Has_Ownership_Aspect_True (Com_Ty, "");
+
+ begin
+ if Nkind (Parent (N)) = N_Full_Type_Declaration and
+ Is_Anonymous_Access_Type (Com_Ty)
+ then
+ Ret := False;
+ end if;
+
+ if not Ret then
+ Error_Msg_NE (Msg & " & not allowed "
+ & "(Components of Named General Access type or"
+ & " Anonymous type)", N, N);
+ end if;
+ return Ret;
+ end;
+
+ -- ??? What about hidden components
+
+ when E_Record_Type
+ | E_Record_Subtype
+ =>
+ declare
+ Elmt : Entity_Id;
+ Elmt_T_Perm : Boolean := True;
+ Elmt_Perm, Elmt_Anonym : Boolean;
+
+ begin
+ Elmt := First_Component_Or_Discriminant (Etype (N));
+ while Present (Elmt) loop
+ Elmt_Perm := Has_Ownership_Aspect_True (Elmt,
+ "type of component");
+ Elmt_Anonym := Is_Anonymous_Access_Type (Etype (Elmt));
+ if Elmt_Anonym then
+ Error_Msg_NE
+ ("type of component & not allowed"
+ & " (Components of Anonymous type)", Elmt, Elmt);
+ end if;
+ Elmt_T_Perm := Elmt_T_Perm and Elmt_Perm and not Elmt_Anonym;
+ Next_Component_Or_Discriminant (Elmt);
+ end loop;
+ if not Elmt_T_Perm then
+ Error_Msg_NE
+ (Msg & " & not allowed (One or "
+ & "more components have Ownership Aspect False)",
+ N, N);
+ end if;
+ return Elmt_T_Perm;
+ end;
+
+ when others =>
+ return True;
+ end case;
+
+ end Has_Ownership_Aspect_True;
end Sem_SPARK;
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index bfa2b4f..2b31cf7 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -20997,7 +20997,7 @@ package body Sem_Util is
Sloc_Value : Source_Ptr;
Related_Id : Entity_Id;
Suffix : Character;
- Suffix_Index : Nat := 0;
+ Suffix_Index : Int := 0;
Prefix : Character := ' ') return Entity_Id
is
N : constant Entity_Id :=
@@ -24039,6 +24039,14 @@ package body Sem_Util is
and then Outer = Protected_Body_Subprogram (Curr)
then
return True;
+
+ -- Outside of its scope, a synchronized type may just be private
+
+ elsif Is_Private_Type (Curr)
+ and then Present (Full_View (Curr))
+ and then Is_Concurrent_Type (Full_View (Curr))
+ then
+ return Scope_Within (Full_View (Curr), Outer);
end if;
end loop;
diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads
index aec3644..74d670d 100644
--- a/gcc/ada/sem_util.ads
+++ b/gcc/ada/sem_util.ads
@@ -2326,7 +2326,7 @@ package Sem_Util is
Sloc_Value : Source_Ptr;
Related_Id : Entity_Id;
Suffix : Character;
- Suffix_Index : Nat := 0;
+ Suffix_Index : Int := 0;
Prefix : Character := ' ') return Entity_Id;
-- This function creates an N_Defining_Identifier node for an internal
-- created entity, such as an implicit type or subtype, or a record
diff --git a/gcc/ada/set_targ.adb b/gcc/ada/set_targ.adb
index 0340ee6..4c717c5 100755
--- a/gcc/ada/set_targ.adb
+++ b/gcc/ada/set_targ.adb
@@ -917,6 +917,9 @@ begin
Get_Back_End_Config_File;
begin
if Back_End_Config_File /= null then
+ pragma Gnat_Annotate
+ (CodePeer, Intentional, "test always false",
+ "some variant body will return non null");
Read_Target_Dependent_Values (Back_End_Config_File.all);
-- Otherwise we get all values from the back end directly
diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads
index ae29661..1359c94 100644
--- a/gcc/ada/sinfo.ads
+++ b/gcc/ada/sinfo.ads
@@ -4674,7 +4674,7 @@ package Sinfo is
--------------------------
-- 4.5.7 If Expression --
- ----------------------------
+ --------------------------
-- IF_EXPRESSION ::=
-- if CONDITION then DEPENDENT_EXPRESSION
diff --git a/gcc/ada/sprint.adb b/gcc/ada/sprint.adb
index f19629c..ab7eecb 100644
--- a/gcc/ada/sprint.adb
+++ b/gcc/ada/sprint.adb
@@ -3540,15 +3540,14 @@ package body Sprint is
-- where the aspects are printed inside the package specification.
if Has_Aspects (Node)
- and then not Nkind_In (Node, N_Package_Declaration,
- N_Generic_Package_Declaration)
+ and then not Nkind_In (Node, N_Generic_Package_Declaration,
+ N_Package_Declaration)
+ and then not Is_Empty_List (Aspect_Specifications (Node))
then
Sprint_Aspect_Specifications (Node, Semicolon => True);
end if;
- if Nkind (Node) in N_Subexpr
- and then Do_Range_Check (Node)
- then
+ if Nkind (Node) in N_Subexpr and then Do_Range_Check (Node) then
Write_Str ("}");
end if;
diff --git a/gcc/ada/terminals.c b/gcc/ada/terminals.c
index 7025f57..bd2cdd0 100644
--- a/gcc/ada/terminals.c
+++ b/gcc/ada/terminals.c
@@ -1107,14 +1107,6 @@ __gnat_setup_winsize (void *desc, int rows, int columns)
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
-
-/* On some system termio is either absent or including it will disable termios
- (HP-UX) */
-#if !defined (__hpux__) && !defined (BSD) && !defined (__APPLE__) \
- && !defined (__rtems__) && !defined (__QNXNTO__)
-# include <termio.h>
-#endif
-
#include <sys/ioctl.h>
#include <termios.h>
#include <fcntl.h>
@@ -1130,7 +1122,6 @@ __gnat_setup_winsize (void *desc, int rows, int columns)
# include <sys/signal.h>
#endif
#if defined (__hpux__)
-# include <sys/termio.h>
# include <sys/stropts.h>
#endif
diff --git a/gcc/ada/vxlink-bind.adb b/gcc/ada/vxlink-bind.adb
new file mode 100644
index 0000000..9f45694
--- /dev/null
+++ b/gcc/ada/vxlink-bind.adb
@@ -0,0 +1,390 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- V X L I N K . B I N D --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2018, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+pragma Ada_2012;
+
+with Ada.Text_IO; use Ada.Text_IO;
+with Ada.IO_Exceptions;
+with Ada.Strings.Fixed;
+
+with GNAT.Regpat; use GNAT.Regpat;
+
+package body VxLink.Bind is
+
+ function Split_Lines (S : String) return Strings_List.Vector;
+
+ function Split (S : String; C : Character) return Strings_List.Vector;
+
+ function Parse_Nm_Output (S : String) return Symbol_Sets.Set;
+
+ procedure Emit_Module_Dtor
+ (FP : File_Type);
+
+ procedure Emit_CDtor
+ (FP : File_Type;
+ Var : String;
+ Set : Symbol_Sets.Set);
+
+ -----------------
+ -- Split_Lines --
+ -----------------
+
+ function Split_Lines (S : String) return Strings_List.Vector
+ is
+ Last : Natural := S'First;
+ Ret : Strings_List.Vector;
+ begin
+ for J in S'Range loop
+ if S (J) = ASCII.CR
+ and then J < S'Last
+ and then S (J + 1) = ASCII.LF
+ then
+ Ret.Append (S (Last .. J - 1));
+ Last := J + 2;
+ elsif S (J) = ASCII.LF then
+ Ret.Append (S (Last .. J - 1));
+ Last := J + 1;
+ end if;
+ end loop;
+
+ if Last <= S'Last then
+ Ret.Append (S (Last .. S'Last));
+ end if;
+
+ return Ret;
+ end Split_Lines;
+
+ -----------
+ -- Split --
+ -----------
+
+ function Split (S : String; C : Character) return Strings_List.Vector
+ is
+ Last : Natural := S'First;
+ Ret : Strings_List.Vector;
+ begin
+ for J in S'Range loop
+ if S (J) = C then
+ if J > Last then
+ Ret.Append (S (Last .. J - 1));
+ end if;
+
+ Last := J + 1;
+ end if;
+ end loop;
+
+ if Last <= S'Last then
+ Ret.Append (S (Last .. S'Last));
+ end if;
+
+ return Ret;
+ end Split;
+
+ ---------------------
+ -- Parse_Nm_Output --
+ ---------------------
+
+ function Parse_Nm_Output (S : String) return Symbol_Sets.Set
+ is
+ Nm_Regexp : constant Pattern_Matcher :=
+ Compile ("^[0-9A-Za-z]* ([a-zA-Z]) (.*)$");
+ type CDTor_Type is
+ (CTOR_Diab,
+ CTOR_Gcc,
+ DTOR_Diab,
+ DTOR_Gcc);
+ subtype CTOR_Type is CDTor_Type range CTOR_Diab .. CTOR_Gcc;
+ CTOR_DIAB_Regexp : aliased constant Pattern_Matcher :=
+ Compile ("^__?STI__*([0-9]+)_");
+ CTOR_GCC_Regexp : aliased constant Pattern_Matcher :=
+ Compile ("^__?GLOBAL_.I._*([0-9]+)_");
+ DTOR_DIAB_Regexp : aliased constant Pattern_Matcher :=
+ Compile ("^__?STD__*([0-9]+)_");
+ DTOR_GCC_Regexp : aliased constant Pattern_Matcher :=
+ Compile ("^__?GLOBAL_.D._*([0-9]+)_");
+ type Regexp_Access is access constant Pattern_Matcher;
+ CDTor_Regexps : constant array (CDTor_Type) of Regexp_Access :=
+ (CTOR_Diab => CTOR_DIAB_Regexp'Access,
+ CTOR_Gcc => CTOR_GCC_Regexp'Access,
+ DTOR_Diab => DTOR_DIAB_Regexp'Access,
+ DTOR_Gcc => DTOR_GCC_Regexp'Access);
+ Result : Symbol_Sets.Set;
+
+ begin
+ for Line of Split_Lines (S) loop
+ declare
+ Sym : Symbol;
+ Nm_Grps : Match_Array (0 .. 2);
+ Ctor_Grps : Match_Array (0 .. 1);
+ begin
+ Match (Nm_Regexp, Line, Nm_Grps);
+
+ if Nm_Grps (0) /= No_Match then
+ declare
+ Sym_Type : constant Character :=
+ Line (Nm_Grps (1).First);
+ Sym_Name : constant String :=
+ Line (Nm_Grps (2).First .. Nm_Grps (2).Last);
+ begin
+ Sym :=
+ (Name => To_Unbounded_String (Sym_Name),
+ Cat => Sym_Type,
+ Internal => False,
+ Kind => Sym_Other,
+ Priority => -1);
+
+ for J in CDTor_Regexps'Range loop
+ Match (CDTor_Regexps (J).all, Sym_Name, Ctor_Grps);
+
+ if Ctor_Grps (0) /= No_Match then
+ if J in CTOR_Type then
+ Sym.Kind := Sym_Ctor;
+ else
+ Sym.Kind := Sym_Dtor;
+ end if;
+
+ Sym.Priority := Integer'Value
+ (Line (Ctor_Grps (1).First .. Ctor_Grps (1).Last));
+
+ exit;
+ end if;
+ end loop;
+
+ Result.Include (Sym);
+ end;
+ end if;
+ end;
+ end loop;
+
+ return Result;
+ end Parse_Nm_Output;
+
+ ----------------
+ -- Initialize --
+ ----------------
+
+ procedure Initialize
+ (Binder : out VxLink_Binder;
+ Object_File : String)
+ is
+ Args : Arguments_List;
+ Module_Dtor_Not_Needed : Boolean := False;
+ Module_Dtor_Needed : Boolean := False;
+
+ begin
+ Args.Append (Nm);
+ Args.Append (Object_File);
+
+ declare
+ Output : constant String := Run (Args);
+ Symbols : Symbol_Sets.Set;
+ begin
+ if Is_Error_State then
+ return;
+ end if;
+
+ Symbols := Parse_Nm_Output (Output);
+
+ for Sym of Symbols loop
+ if Sym.Kind = Sym_Ctor then
+ Binder.Constructors.Insert (Sym);
+ elsif Sym.Kind = Sym_Dtor then
+ Binder.Destructors.Insert (Sym);
+ elsif Match ("_?__.*_atexit$", To_String (Sym.Name)) then
+ if Sym.Cat = 'T' then
+ Module_Dtor_Not_Needed := True;
+ elsif Sym.Cat = 'U' then
+ Module_Dtor_Needed := True;
+ end if;
+ end if;
+ end loop;
+
+ Binder.Module_Dtor_Needed :=
+ not Module_Dtor_Not_Needed and then Module_Dtor_Needed;
+ end;
+ end Initialize;
+
+ --------------------
+ -- Parse_Tag_File --
+ --------------------
+
+ procedure Parse_Tag_File
+ (Binder : in out VxLink_Binder;
+ File : String)
+ is
+ FP : Ada.Text_IO.File_Type;
+
+ begin
+ Open
+ (FP,
+ Mode => In_File,
+ Name => File);
+ loop
+ declare
+ Line : constant String :=
+ Ada.Strings.Fixed.Trim
+ (Get_Line (FP), Ada.Strings.Both);
+ Tokens : Strings_List.Vector;
+
+ begin
+ if Line'Length = 0 then
+ -- Skip empty lines
+ null;
+
+ elsif Line (Line'First) = '#' then
+ -- Skip comment
+ null;
+
+ else
+ Tokens := Split (Line, ' ');
+ if Tokens.First_Element = "section" then
+ -- Sections are not used for tags, only when building
+ -- kernels. So skip for now
+ null;
+ else
+ Binder.Tags_List.Append (Line);
+ end if;
+ end if;
+ end;
+ end loop;
+
+ exception
+ when Ada.IO_Exceptions.End_Error =>
+ Close (FP);
+ when others =>
+ Log_Error ("Cannot open file " & File &
+ ". DKM tags won't be generated");
+ end Parse_Tag_File;
+
+ ----------------------
+ -- Emit_Module_Dtor --
+ ----------------------
+
+ procedure Emit_Module_Dtor
+ (FP : File_Type)
+ is
+ Dtor_Name : constant String := "_GLOBAL__D_65536_0_cxa_finalize";
+ begin
+ Put_Line (FP, "extern void __cxa_finalize(void *);");
+ Put_Line (FP, "static void " & Dtor_Name & "()");
+ Put_Line (FP, "{");
+ Put_Line (FP, " __cxa_finalize(&__dso_handle);");
+ Put_Line (FP, "}");
+ Put_Line (FP, "");
+ end Emit_Module_Dtor;
+
+ ----------------
+ -- Emit_CDtor --
+ ----------------
+
+ procedure Emit_CDtor
+ (FP : File_Type;
+ Var : String;
+ Set : Symbol_Sets.Set)
+ is
+ begin
+ for Sym of Set loop
+ if not Sym.Internal then
+ Put_Line (FP, "extern void " & To_String (Sym.Name) & "();");
+ end if;
+ end loop;
+
+ New_Line (FP);
+
+ Put_Line (FP, "extern void (*" & Var & "[])();");
+ Put_Line (FP, "void (*" & Var & "[])() =");
+ Put_Line (FP, " {");
+ for Sym of Set loop
+ Put_Line (FP, " " & To_String (Sym.Name) & ",");
+ end loop;
+ Put_Line (FP, " 0};");
+ New_Line (FP);
+ end Emit_CDtor;
+
+ ---------------
+ -- Emit_CTDT --
+ ---------------
+
+ procedure Emit_CTDT
+ (Binder : in out VxLink_Binder;
+ Namespace : String)
+ is
+ FP : Ada.Text_IO.File_Type;
+ CDtor_File : constant String := Namespace & "-cdtor.c";
+ begin
+ Binder.CTDT_File := To_Unbounded_String (CDtor_File);
+ Create
+ (File => FP,
+ Name => CDtor_File);
+ Put_Line (FP, "#if defined(_HAVE_TOOL_XTORS)");
+ Put_Line (FP, "#include <vxWorks.h>");
+ if Binder.Module_Dtor_Needed then
+ Put_Line (FP, "#define _WRS_NEED_CALL_CXA_FINALIZE");
+ end if;
+ Put_Line (FP, "#include TOOL_HEADER (toolXtors.h)");
+ Put_Line (FP, "#else");
+ Put_Line (FP, "");
+
+ if Binder.Module_Dtor_Needed then
+ Emit_Module_Dtor (FP);
+ end if;
+
+ Emit_CDtor (FP, "_ctors", Binder.Constructors);
+ Emit_CDtor (FP, "_dtors", Binder.Destructors);
+
+ Put_Line (FP, "#endif");
+
+ if not Binder.Tags_List.Is_Empty then
+ New_Line (FP);
+ Put_Line (FP, "/* build variables */");
+ Put_Line (FP, "__asm("" .section \"".wrs_build_vars\"",\""a\"""");");
+ for Tag of Binder.Tags_List loop
+ Put_Line (FP, "__asm("" .ascii \""" & Tag & "\"""");");
+ Put_Line (FP, "__asm("" .byte 0"");");
+ end loop;
+ Put_Line (FP, "__asm("" .ascii \""end\"""");");
+ Put_Line (FP, "__asm("" .byte 0"");");
+ end if;
+
+ Close (FP);
+
+ exception
+ when others =>
+ Close (FP);
+ Set_Error_State ("Internal error");
+ raise;
+ end Emit_CTDT;
+
+ ---------------
+ -- CTDT_File --
+ ---------------
+
+ function CTDT_File (Binder : VxLink_Binder) return String
+ is
+ begin
+ return To_String (Binder.CTDT_File);
+ end CTDT_File;
+
+end VxLink.Bind;
diff --git a/gcc/ada/vxlink-bind.ads b/gcc/ada/vxlink-bind.ads
new file mode 100644
index 0000000..7e6a1b0
--- /dev/null
+++ b/gcc/ada/vxlink-bind.ads
@@ -0,0 +1,87 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- V X L I N K . B I N D --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+pragma Ada_2012;
+
+private with Ada.Containers.Ordered_Sets;
+private with Ada.Strings.Unbounded;
+
+package VxLink.Bind is
+
+ type VxLink_Binder is private;
+
+ procedure Initialize
+ (Binder : out VxLink_Binder;
+ Object_File : String);
+
+ procedure Parse_Tag_File
+ (Binder : in out VxLink_Binder;
+ File : String);
+
+ procedure Emit_CTDT
+ (Binder : in out VxLink_Binder;
+ Namespace : String);
+
+ function CTDT_File (Binder : VxLink_Binder) return String;
+
+private
+
+ use Ada.Strings.Unbounded;
+
+ type Symbol_Kind is (Sym_Ctor, Sym_Dtor, Sym_Other);
+
+ type Symbol is record
+ Name : Unbounded_String;
+ Cat : Character;
+ Internal : Boolean;
+ Kind : Symbol_Kind;
+ Priority : Integer;
+ end record;
+
+ function "=" (S1, S2 : Symbol) return Boolean
+ is (S1.Name = S2.Name and then S1.Cat = S2.Cat);
+
+ function "<" (S1, S2 : Symbol) return Boolean
+ is (if S1.Priority /= S2.Priority
+ then S1.Priority < S2.Priority
+ elsif S1.Name /= S2.Name
+ then S1.Name < S2.Name
+ else S1.Cat < S2.Cat);
+
+ package Symbol_Sets is new Ada.Containers.Ordered_Sets
+ (Symbol,
+ "<" => "<",
+ "=" => "=");
+
+ type VxLink_Binder is record
+ CTDT_File : Unbounded_String;
+ Constructors : Symbol_Sets.Set;
+ Destructors : Symbol_Sets.Set;
+ Module_Dtor_Needed : Boolean;
+ EH_Frame_Needed : Boolean;
+ Tags_List : Strings_List.Vector;
+ end record;
+
+end VxLink.Bind;
diff --git a/gcc/ada/vxlink-link.adb b/gcc/ada/vxlink-link.adb
new file mode 100644
index 0000000..5211074
--- /dev/null
+++ b/gcc/ada/vxlink-link.adb
@@ -0,0 +1,194 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- V X L I N K . L I N K --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2018, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+pragma Ada_2012;
+
+with Ada.Command_Line; use Ada.Command_Line;
+with GNAT.Directory_Operations; use GNAT.Directory_Operations;
+
+package body VxLink.Link is
+
+ Gcc : constant String := VxLink.Gcc;
+
+ ----------------
+ -- Initialize --
+ ----------------
+
+ procedure Initialize
+ (Linker : out VxLink_Linker)
+ is
+ Leading : Boolean := True;
+ Next_Is_Object : Boolean := False;
+
+ begin
+ for J in 1 .. Ada.Command_Line.Argument_Count loop
+ declare
+ Arg : String renames Argument (J);
+ begin
+ if Next_Is_Object then
+ Next_Is_Object := False;
+ Linker.Dest_Object := To_Unbounded_String (Arg);
+ Leading := False;
+
+ elsif Argument (J) = "-o" then
+ Next_Is_Object := True;
+
+ elsif Argument (J) = "-noauto-register" then
+ -- Filter out this argument, and do not generate _ctors/_dtors
+ Linker.Add_CDtors := False;
+ elsif Arg = "-v" and then not Is_Verbose then
+ -- first -v means VxLink should be verbose, two -v passes -v to
+ -- the linker.
+ Set_Verbose (True);
+ else
+ if Arg = "-nostdlib" or Arg = "-nostartfiles" then
+ Linker.Add_CDtors := False;
+ end if;
+
+ if Leading then
+ Linker.Args_Leading.Append (Arg);
+ else
+ Linker.Args_Trailing.Append (Arg);
+ end if;
+ end if;
+ end;
+ end loop;
+
+ if Linker.Dest_Object = Null_Unbounded_String then
+ Set_Error_State ("no output object is defined");
+ elsif Linker.Add_CDtors then
+ -- We'll need to create intermediate artefacts, so we'll use the
+ -- destination object as base namespace just in case we have
+ -- several link operations in the same directory
+ declare
+ Obj : constant String :=
+ Base_Name (To_String (Linker.Dest_Object));
+
+ begin
+ for J in reverse Obj'Range loop
+ if Obj (J) = '.' then
+ Linker.Dest_Base :=
+ To_Unbounded_String (Obj (Obj'First .. J - 1));
+ exit;
+ end if;
+ end loop;
+
+ Linker.Partial_Obj := Linker.Dest_Base & "-partial.o";
+ end;
+ end if;
+ end Initialize;
+
+ -----------------
+ -- Needs_CDtor --
+ -----------------
+
+ function Needs_CDtor (Linker : VxLink_Linker) return Boolean is
+ begin
+ return Linker.Add_CDtors;
+ end Needs_CDtor;
+
+ --------------------
+ -- Partial_Object --
+ --------------------
+
+ function Partial_Object (Linker : VxLink_Linker) return String is
+ begin
+ return To_String (Linker.Partial_Obj);
+ end Partial_Object;
+
+ ---------------
+ -- Namespace --
+ ---------------
+
+ function Namespace (Linker : VxLink_Linker) return String is
+ begin
+ return To_String (Linker.Dest_Base);
+ end Namespace;
+
+ ---------------------
+ -- Do_Initial_Link --
+ ---------------------
+
+ procedure Do_Initial_Link (Linker : VxLink_Linker)
+ is
+ Args : Arguments_List;
+ Gxx_Path : constant String := Gxx;
+ begin
+ if Is_Error_State then
+ return;
+ end if;
+
+ if Gxx_Path'Length /= 0 then
+ Args.Append (Gxx);
+ else
+ Args.Append (Gcc);
+ end if;
+ Args.Append (Linker.Args_Leading);
+ Args.Append ("-o");
+
+ if Linker.Add_CDtors then
+ Args.Append (To_String (Linker.Partial_Obj));
+ else
+ Args.Append (To_String (Linker.Dest_Object));
+ end if;
+
+ Args.Append (Linker.Args_Trailing);
+
+ if not Linker.Add_CDtors then
+ Args.Append ("-nostartfiles");
+ end if;
+
+ Run (Args);
+ end Do_Initial_Link;
+
+ -------------------
+ -- Do_Final_Link --
+ -------------------
+
+ procedure Do_Final_Link
+ (Linker : VxLink_Linker;
+ Ctdt_Obj : String)
+ is
+ Args : Arguments_List;
+ begin
+ if not Linker.Add_CDtors then
+ return;
+ end if;
+
+ if Is_Error_State then
+ return;
+ end if;
+
+ Args.Append (Gcc);
+ Args.Append ("-nostdlib");
+ Args.Append (Ctdt_Obj);
+ Args.Append (To_String (Linker.Partial_Obj));
+ Args.Append ("-o");
+ Args.Append (To_String (Linker.Dest_Object));
+
+ Run (Args);
+ end Do_Final_Link;
+
+end VxLink.Link;
diff --git a/gcc/ada/vxlink-link.ads b/gcc/ada/vxlink-link.ads
new file mode 100644
index 0000000..4c46f48
--- /dev/null
+++ b/gcc/ada/vxlink-link.ads
@@ -0,0 +1,63 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- V X L I N K . L I N K --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+pragma Ada_2012;
+
+private with Ada.Strings.Unbounded;
+
+package VxLink.Link is
+
+ type VxLink_Linker is private;
+
+ procedure Initialize
+ (Linker : out VxLink_Linker);
+
+ function Needs_CDtor (Linker : VxLink_Linker) return Boolean;
+
+ function Partial_Object (Linker : VxLink_Linker) return String;
+
+ function Namespace (Linker : VxLink_Linker) return String;
+
+ procedure Do_Initial_Link
+ (Linker : VxLink_Linker);
+
+ procedure Do_Final_Link
+ (Linker : VxLink_Linker;
+ Ctdt_Obj : String);
+
+private
+
+ use Ada.Strings.Unbounded;
+
+ type VxLink_Linker is record
+ Args_Leading : Arguments_List;
+ Args_Trailing : Arguments_List;
+ Add_CDtors : Boolean := True;
+ Dest_Object : Unbounded_String;
+ Dest_Base : Unbounded_String;
+ Partial_Obj : Unbounded_String;
+ end record;
+
+end VxLink.Link;
diff --git a/gcc/ada/vxlink-main.adb b/gcc/ada/vxlink-main.adb
new file mode 100644
index 0000000..04a22c3
--- /dev/null
+++ b/gcc/ada/vxlink-main.adb
@@ -0,0 +1,81 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- V X L I N K . M A I N --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2018, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- VxLink is a helper tool used as a wrapper around g++/gcc to build VxWorks
+-- DKM (Downloadable Kernel Modules).
+-- Such DKM is a partially linked object that contains entry points for
+-- constructors and destructors. This tool thus uses g++ to generate an
+-- intermediate partially linked object, retrieves the list of constructors
+-- and destructors in it and produces a C file that lists those ctors/dtors
+-- in a way that is understood be VxWorks kernel. It then links this file
+-- with the intermediate object to produce a valid DKM.
+
+pragma Ada_2012;
+
+with GNAT.OS_Lib; use GNAT.OS_Lib;
+
+with VxLink.Link; use VxLink.Link;
+with VxLink.Bind; use VxLink.Bind;
+
+procedure VxLink.Main is
+ Linker : VxLink_Linker;
+ Binder : VxLink_Binder;
+ VSB_Dir : String_Access := Getenv ("VSB_DIR");
+begin
+ Initialize (Linker);
+
+ if Is_Error_State then
+ return;
+ end if;
+
+ Do_Initial_Link (Linker);
+
+ if Is_Error_State then
+ return;
+ end if;
+
+ if not Needs_CDtor (Linker) then
+ -- Initial link is enough, let's return
+ return;
+ end if;
+
+ if VSB_Dir /= null and then VSB_Dir'Length > 0 then
+ declare
+ DKM_Tag_File : constant String :=
+ Normalize_Pathname
+ ("krnl/tags/dkm.tags", VSB_Dir.all);
+ begin
+ if Is_Regular_File (DKM_Tag_File) then
+ Parse_Tag_File (Binder, DKM_Tag_File);
+ end if;
+ end;
+ end if;
+
+ Initialize (Binder, Object_File => Partial_Object (Linker));
+ Emit_CTDT (Binder, Namespace => Namespace (Linker));
+
+ Do_Final_Link (Linker, CTDT_File (Binder));
+ Free (VSB_Dir);
+end VxLink.Main;
diff --git a/gcc/ada/vxlink.adb b/gcc/ada/vxlink.adb
new file mode 100644
index 0000000..400ad22
--- /dev/null
+++ b/gcc/ada/vxlink.adb
@@ -0,0 +1,288 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- V X L I N K --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2018, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+pragma Ada_2012;
+
+with Ada.Command_Line;
+with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
+with Ada.Text_IO;
+
+with GNAT.Directory_Operations; use GNAT.Directory_Operations;
+with GNAT.Expect; use GNAT.Expect;
+with GNAT.OS_Lib; use GNAT.OS_Lib;
+
+package body VxLink is
+
+ Target_Triplet : Unbounded_String := Null_Unbounded_String;
+ Verbose : Boolean := False;
+ Error_State : Boolean := False;
+
+ function Triplet return String;
+
+ function Which (Exe : String) return String;
+
+ -------------
+ -- Triplet --
+ -------------
+
+ function Triplet return String is
+ begin
+ if Target_Triplet = Null_Unbounded_String then
+ declare
+ Exe : constant String := File_Name (Ada.Command_Line.Command_Name);
+ begin
+ for J in reverse Exe'Range loop
+ if Exe (J) = '-' then
+ Target_Triplet := To_Unbounded_String (Exe (Exe'First .. J));
+ exit;
+ end if;
+ end loop;
+ end;
+ end if;
+
+ return To_String (Target_Triplet);
+ end Triplet;
+
+ -----------
+ -- Which --
+ -----------
+
+ function Which (Exe : String) return String
+ is
+ Suffix : GNAT.OS_Lib.String_Access := Get_Executable_Suffix;
+ Basename : constant String := Exe & Suffix.all;
+ Path : GNAT.OS_Lib.String_Access := Getenv ("PATH");
+ Last : Natural := Path'First;
+
+ begin
+ Free (Suffix);
+
+ for J in Path'Range loop
+ if Path (J) = Path_Separator then
+ declare
+ Full : constant String := Normalize_Pathname
+ (Name => Basename,
+ Directory => Path (Last .. J - 1),
+ Resolve_Links => False,
+ Case_Sensitive => True);
+ begin
+ if Is_Executable_File (Full) then
+ Free (Path);
+
+ return Full;
+ end if;
+ end;
+
+ Last := J + 1;
+ end if;
+ end loop;
+
+ Free (Path);
+
+ return "";
+ end Which;
+
+ -----------------
+ -- Set_Verbose --
+ -----------------
+
+ procedure Set_Verbose (Value : Boolean)
+ is
+ begin
+ Verbose := Value;
+ end Set_Verbose;
+
+ ----------------
+ -- Is_Verbose --
+ ----------------
+
+ function Is_Verbose return Boolean
+ is
+ begin
+ return Verbose;
+ end Is_Verbose;
+
+ ---------------------
+ -- Set_Error_State --
+ ---------------------
+
+ procedure Set_Error_State (Message : String)
+ is
+ begin
+ Log_Error ("Error: " & Message);
+ Error_State := True;
+ Ada.Command_Line.Set_Exit_Status (1);
+ end Set_Error_State;
+
+ --------------------
+ -- Is_Error_State --
+ --------------------
+
+ function Is_Error_State return Boolean
+ is
+ begin
+ return Error_State;
+ end Is_Error_State;
+
+ --------------
+ -- Log_Info --
+ --------------
+
+ procedure Log_Info (S : String)
+ is
+ begin
+ if Verbose then
+ Ada.Text_IO.Put_Line (S);
+ end if;
+ end Log_Info;
+
+ ---------------
+ -- Log_Error --
+ ---------------
+
+ procedure Log_Error (S : String)
+ is
+ begin
+ Ada.Text_IO.Put_Line (Ada.Text_IO.Standard_Error, S);
+ end Log_Error;
+
+ ---------
+ -- Run --
+ ---------
+
+ procedure Run (Arguments : Arguments_List)
+ is
+ Output : constant String := Run (Arguments);
+ begin
+ if not Is_Error_State then
+ -- In case of erroneous execution, the function version of run will
+ -- have already displayed the output
+ Ada.Text_IO.Put (Output);
+ end if;
+ end Run;
+
+ ---------
+ -- Run --
+ ---------
+
+ function Run (Arguments : Arguments_List) return String
+ is
+ Args : GNAT.OS_Lib.Argument_List_Access :=
+ new GNAT.OS_Lib.Argument_List
+ (1 .. Natural (Arguments.Length) - 1);
+ Base : constant String := Base_Name (Arguments.First_Element);
+ Status : aliased Integer := 0;
+ Debug_Line : Unbounded_String;
+ Add_Quotes : Boolean;
+
+ begin
+ if Verbose then
+ Append (Debug_Line, Base);
+ end if;
+
+ for J in Arguments.First_Index + 1 .. Arguments.Last_Index loop
+ declare
+ Arg : String renames Arguments.Element (J);
+ begin
+ Args (J - 1) := new String'(Arg);
+
+ if Verbose then
+ Add_Quotes := False;
+
+ for K in Arg'Range loop
+ if Arg (K) = ' ' then
+ Add_Quotes := True;
+ exit;
+ end if;
+ end loop;
+
+ Append (Debug_Line, ' ');
+
+ if Add_Quotes then
+ Append (Debug_Line, '"' & Arg & '"');
+ else
+ Append (Debug_Line, Arg);
+ end if;
+ end if;
+ end;
+ end loop;
+
+ if Verbose then
+ Ada.Text_IO.Put_Line (To_String (Debug_Line));
+ end if;
+
+ declare
+ Ret : constant String :=
+ Get_Command_Output
+ (Command => Arguments.First_Element,
+ Arguments => Args.all,
+ Input => "",
+ Status => Status'Access,
+ Err_To_Out => True);
+ begin
+ GNAT.OS_Lib.Free (Args);
+
+ if Status /= 0 then
+ Ada.Text_IO.Put_Line (Ret);
+ Set_Error_State
+ (Base_Name (Arguments.First_Element) &
+ " returned" & Status'Image);
+ end if;
+
+ return Ret;
+ end;
+ end Run;
+
+ ---------
+ -- Gcc --
+ ---------
+
+ function Gcc return String
+ is
+ begin
+ return Which (Triplet & "gcc");
+ end Gcc;
+
+ ---------
+ -- Gxx --
+ ---------
+
+ function Gxx return String
+ is
+ begin
+ return Which (Triplet & "g++");
+ end Gxx;
+
+ --------
+ -- Nm --
+ --------
+
+ function Nm return String
+ is
+ begin
+ return Which (Triplet & "nm");
+ end Nm;
+
+end VxLink;
diff --git a/gcc/ada/vxlink.ads b/gcc/ada/vxlink.ads
new file mode 100644
index 0000000..37ae5d7
--- /dev/null
+++ b/gcc/ada/vxlink.ads
@@ -0,0 +1,68 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- V X L I N K --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- See vxlink-main.adb for a description of the tool.
+--
+-- This package contains only common utility functions used by the other
+-- child packages.
+
+pragma Ada_2012;
+
+with Ada.Containers.Indefinite_Vectors;
+
+package VxLink is
+
+ package Strings_List is new Ada.Containers.Indefinite_Vectors
+ (Positive, String);
+
+ subtype Arguments_List is Strings_List.Vector;
+
+ procedure Set_Verbose (Value : Boolean);
+ function Is_Verbose return Boolean;
+
+ procedure Set_Error_State (Message : String);
+ function Is_Error_State return Boolean;
+
+ procedure Log_Info (S : String);
+ procedure Log_Error (S : String);
+
+ procedure Run (Arguments : Arguments_List);
+
+ function Run (Arguments : Arguments_List) return String;
+
+ function Gcc return String;
+ -- Current toolchain's gcc command
+
+ function Gxx return String;
+ -- Current toolchain's g++ command
+
+ function Nm return String;
+ -- Current toolchain's nm command
+
+ function Ends_With (Str, Suffix : String) return Boolean
+ is (Str'Length >= Suffix'Length
+ and then Str (Str'Last - Suffix'Length + 1 .. Str'Last) = Suffix);
+
+end VxLink;
diff --git a/gcc/alias.c b/gcc/alias.c
index 2091dfbf..748da2b 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -1554,6 +1554,17 @@ record_set (rtx dest, const_rtx set, void *data ATTRIBUTE_UNUSED)
new_reg_base_value[regno] = 0;
return;
}
+ /* A CLOBBER_HIGH only wipes out the old value if the mode of the old
+ value is greater than that of the clobber. */
+ else if (GET_CODE (set) == CLOBBER_HIGH)
+ {
+ if (new_reg_base_value[regno] != 0
+ && reg_is_clobbered_by_clobber_high (
+ regno, GET_MODE (new_reg_base_value[regno]), XEXP (set, 0)))
+ new_reg_base_value[regno] = 0;
+ return;
+ }
+
src = SET_SRC (set);
}
else
diff --git a/gcc/asan.c b/gcc/asan.c
index e71ab2c..235e219 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -253,7 +253,7 @@ static tree last_alloca_addr;
/* Set of variable declarations that are going to be guarded by
use-after-scope sanitizer. */
-static hash_set<tree> *asan_handled_variables = NULL;
+hash_set<tree> *asan_handled_variables = NULL;
hash_set <tree> *asan_used_labels = NULL;
diff --git a/gcc/asan.h b/gcc/asan.h
index 412af22..2f431b4 100644
--- a/gcc/asan.h
+++ b/gcc/asan.h
@@ -110,6 +110,8 @@ extern bool asan_sanitize_stack_p (void);
extern bool asan_sanitize_allocas_p (void);
+extern hash_set<tree> *asan_handled_variables;
+
/* Return TRUE if builtin with given FCODE will be intercepted by
libasan. */
diff --git a/gcc/attribs.c b/gcc/attribs.c
index efc879b..8b72127 100644
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -430,9 +430,9 @@ diag_attr_exclusions (tree last_decl, tree node, tree attrname,
/* Print a note? */
bool note = last_decl != NULL_TREE;
-
+ auto_diagnostic_group d;
if (TREE_CODE (node) == FUNCTION_DECL
- && DECL_BUILT_IN (node))
+ && fndecl_built_in_p (node))
note &= warning (OPT_Wattributes,
"ignoring attribute %qE in declaration of "
"a built-in function %qD because it conflicts "
@@ -587,6 +587,7 @@ decl_attributes (tree *node, tree attributes, int flags,
/* This is a c++11 attribute that appertains to a
type-specifier, outside of the definition of, a class
type. Ignore it. */
+ auto_diagnostic_group d;
if (warning (OPT_Wattributes, "attribute ignored"))
inform (input_location,
"an attribute that appertains to a type-specifier "
diff --git a/gcc/auto-profile.c b/gcc/auto-profile.c
index 197fa10..68abe32 100644
--- a/gcc/auto-profile.c
+++ b/gcc/auto-profile.c
@@ -867,7 +867,6 @@ autofdo_source_profile::read ()
function_instance::function_instance_stack stack;
function_instance *s = function_instance::read_function_instance (
&stack, gcov_read_counter ());
- afdo_profile_info->sum_all += s->total_count ();
map_[s->name ()] = s;
}
return true;
@@ -958,23 +957,6 @@ read_profile (void)
/* autofdo_module_profile. */
fake_read_autofdo_module_profile ();
-
- /* Read in the working set. */
- if (gcov_read_unsigned () != GCOV_TAG_AFDO_WORKING_SET)
- {
- error ("cannot read working set from %s", auto_profile_file);
- return;
- }
-
- /* Skip the length of the section. */
- gcov_read_unsigned ();
- gcov_working_set_t set[128];
- for (unsigned i = 0; i < 128; i++)
- {
- set[i].num_counters = gcov_read_unsigned ();
- set[i].min_counter = gcov_read_counter ();
- }
- add_working_set (set);
}
/* From AutoFDO profiles, find values inside STMT for that we want to measure
@@ -1685,7 +1667,6 @@ read_autofdo_file (void)
autofdo::afdo_profile_info = XNEW (gcov_summary);
autofdo::afdo_profile_info->runs = 1;
autofdo::afdo_profile_info->sum_max = 0;
- autofdo::afdo_profile_info->sum_all = 0;
/* Read the profile from the profile file. */
autofdo::read_profile ();
@@ -1712,7 +1693,7 @@ afdo_callsite_hot_enough_for_early_inline (struct cgraph_edge *edge)
if (count > 0)
{
bool is_hot;
- const gcov_summary *saved_profile_info = profile_info;
+ gcov_summary *saved_profile_info = profile_info;
/* At early inline stage, profile_info is not set yet. We need to
temporarily set it to afdo_profile_info to calculate hotness. */
profile_info = autofdo::afdo_profile_info;
diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c
index 57edde6..e20df16 100644
--- a/gcc/bb-reorder.c
+++ b/gcc/bb-reorder.c
@@ -91,7 +91,6 @@
*/
#include "config.h"
-#define INCLUDE_ALGORITHM /* stable_sort */
#include "system.h"
#include "coretypes.h"
#include "backend.h"
@@ -2351,13 +2350,20 @@ reorder_basic_blocks_software_trace_cache (void)
FREE (bbd);
}
-/* Return true if edge E1 is more desirable as a fallthrough edge than
- edge E2 is. */
+/* Order edges by execution frequency, higher first. */
-static bool
-edge_order (edge e1, edge e2)
+static int
+edge_order (const void *ve1, const void *ve2)
{
- return e1->count () > e2->count ();
+ edge e1 = *(const edge *) ve1;
+ edge e2 = *(const edge *) ve2;
+ profile_count c1 = e1->count ();
+ profile_count c2 = e2->count ();
+ /* Since profile_count::operator< does not establish a strict weak order
+ in presence of uninitialized counts, use 'max': this makes them appear
+ as if having execution frequency less than any initialized count. */
+ profile_count m = c1.max (c2);
+ return (m == c2) - (m == c1);
}
/* Reorder basic blocks using the "simple" algorithm. This tries to
@@ -2410,7 +2416,7 @@ reorder_basic_blocks_simple (void)
all edges are equally desirable. */
if (optimize_function_for_speed_p (cfun))
- std::stable_sort (edges, edges + n, edge_order);
+ gcc_stablesort (edges, n, sizeof *edges, edge_order);
/* Now decide which of those edges to make fallthrough edges. We set
BB_VISITED if a block already has a fallthrough successor assigned
diff --git a/gcc/builtin-attrs.def b/gcc/builtin-attrs.def
index 300ba65..e245e4d 100644
--- a/gcc/builtin-attrs.def
+++ b/gcc/builtin-attrs.def
@@ -129,6 +129,8 @@ DEF_ATTR_TREE_LIST (ATTR_NOTHROW_LIST, ATTR_NOTHROW, ATTR_NULL, ATTR_NULL)
DEF_ATTR_TREE_LIST (ATTR_NOTHROW_LEAF_LIST, ATTR_LEAF, ATTR_NULL, ATTR_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_NOVOPS_NOTHROW_LEAF_LIST, ATTR_NOVOPS, \
+ ATTR_NULL, ATTR_NOTHROW_LEAF_LIST)
DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_LIST, ATTR_CONST, \
ATTR_NULL, ATTR_NOTHROW_LIST)
DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_LEAF_LIST, ATTR_CONST, \
diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def
index b01095c..f13da6a 100644
--- a/gcc/builtin-types.def
+++ b/gcc/builtin-types.def
@@ -531,6 +531,8 @@ DEF_FUNCTION_TYPE_3 (BT_FN_ULONG_ULONG_ULONG_ULONG,
BT_ULONG, BT_ULONG, BT_ULONG, BT_ULONG)
DEF_FUNCTION_TYPE_3 (BT_FN_LONG_LONG_UINT_UINT,
BT_LONG, BT_LONG, BT_UINT, BT_UINT)
+DEF_FUNCTION_TYPE_3 (BT_FN_LONG_LONG_LONG_DOUBLE,
+ BT_LONG, BT_LONG, BT_LONG, BT_DOUBLE)
DEF_FUNCTION_TYPE_3 (BT_FN_ULONG_ULONG_UINT_UINT,
BT_ULONG, BT_ULONG, BT_UINT, BT_UINT)
DEF_FUNCTION_TYPE_3 (BT_FN_STRING_CONST_STRING_CONST_STRING_INT,
@@ -763,6 +765,12 @@ DEF_FUNCTION_TYPE_VAR_1 (BT_FN_VOID_LONG_VAR,
BT_VOID, BT_LONG)
DEF_FUNCTION_TYPE_VAR_1 (BT_FN_VOID_ULL_VAR,
BT_VOID, BT_ULONGLONG)
+DEF_FUNCTION_TYPE_VAR_1 (BT_FN_PTR_PTR_VAR, BT_PTR, BT_PTR)
+DEF_FUNCTION_TYPE_VAR_1 (BT_FN_I1_I1_VAR, BT_I1, BT_I1)
+DEF_FUNCTION_TYPE_VAR_1 (BT_FN_I2_I2_VAR, BT_I2, BT_I2)
+DEF_FUNCTION_TYPE_VAR_1 (BT_FN_I4_I4_VAR, BT_I4, BT_I4)
+DEF_FUNCTION_TYPE_VAR_1 (BT_FN_I8_I8_VAR, BT_I8, BT_I8)
+DEF_FUNCTION_TYPE_VAR_1 (BT_FN_I16_I16_VAR, BT_I16, BT_I16)
DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_FILEPTR_CONST_STRING_VAR,
BT_INT, BT_FILEPTR, BT_CONST_STRING)
diff --git a/gcc/builtins.c b/gcc/builtins.c
index c659611..1d4de09 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -132,7 +132,7 @@ static rtx expand_builtin_mempcpy (tree, rtx);
static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx, tree, int);
static rtx expand_builtin_strcat (tree, rtx);
static rtx expand_builtin_strcpy (tree, rtx);
-static rtx expand_builtin_strcpy_args (tree, tree, rtx);
+static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx);
static rtx expand_builtin_stpcpy (tree, rtx, machine_mode);
static rtx expand_builtin_stpncpy (tree, rtx);
static rtx expand_builtin_strncat (tree, rtx);
@@ -148,6 +148,7 @@ static rtx expand_builtin_unop (machine_mode, tree, rtx, rtx, optab);
static rtx expand_builtin_frame_address (tree, tree);
static tree stabilize_va_list_loc (location_t, tree, int);
static rtx expand_builtin_expect (tree, rtx);
+static rtx expand_builtin_expect_with_probability (tree, rtx);
static tree fold_builtin_constant_p (tree);
static tree fold_builtin_classify_type (tree);
static tree fold_builtin_strlen (location_t, tree, tree);
@@ -207,15 +208,6 @@ is_builtin_name (const char *name)
return false;
}
-
-/* Return true if DECL is a function symbol representing a built-in. */
-
-bool
-is_builtin_fn (tree decl)
-{
- return TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl);
-}
-
/* Return true if NODE should be considered for inline expansion regardless
of the optimization level. This means whenever a function is invoked with
its "internal" name, which normally contains the prefix "__builtin". */
@@ -550,6 +542,58 @@ string_length (const void *ptr, unsigned eltsize, unsigned maxelts)
return n;
}
+/* For a call at LOC to a function FN that expects a string in the argument
+ ARG, issue a diagnostic due to it being a called with an argument
+ declared at NONSTR that is a character array with no terminating NUL. */
+
+void
+warn_string_no_nul (location_t loc, const char *fn, tree arg, tree decl)
+{
+ if (TREE_NO_WARNING (arg))
+ return;
+
+ loc = expansion_point_location_if_in_system_header (loc);
+
+ if (warning_at (loc, OPT_Wstringop_overflow_,
+ "%qs argument missing terminating nul", fn))
+ {
+ inform (DECL_SOURCE_LOCATION (decl),
+ "referenced argument declared here");
+ TREE_NO_WARNING (arg) = 1;
+ }
+}
+
+/* If EXP refers to an unterminated constant character array return
+ the declaration of the object of which the array is a member or
+ element. Otherwise return null. */
+
+tree
+unterminated_array (tree exp)
+{
+ if (TREE_CODE (exp) == SSA_NAME)
+ {
+ gimple *stmt = SSA_NAME_DEF_STMT (exp);
+ if (!is_gimple_assign (stmt))
+ return NULL_TREE;
+
+ tree rhs1 = gimple_assign_rhs1 (stmt);
+ tree_code code = gimple_assign_rhs_code (stmt);
+ if (code == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (rhs1, 0)) == ARRAY_REF)
+ rhs1 = rhs1;
+ else if (code != POINTER_PLUS_EXPR)
+ return NULL_TREE;
+
+ exp = rhs1;
+ }
+
+ tree nonstr = NULL;
+ if (c_strlen (exp, 1, &nonstr, 1) == NULL && nonstr)
+ return nonstr;
+
+ return NULL_TREE;
+}
+
/* Compute the length of a null-terminated character string or wide
character string handling character sizes of 1, 2, and 4 bytes.
TREE_STRING_LENGTH is not the right way because it evaluates to
@@ -567,41 +611,49 @@ string_length (const void *ptr, unsigned eltsize, unsigned maxelts)
accesses. Note that this implies the result is not going to be emitted
into the instruction stream.
- The value returned is of type `ssizetype'.
+ If a not zero-terminated string value is encountered and NONSTR is
+ non-zero, the declaration of the string value is assigned to *NONSTR.
+ *NONSTR is accumulating, thus not cleared on success, therefore it has
+ to be initialized to NULL_TREE by the caller.
- Unfortunately, string_constant can't access the values of const char
- arrays with initializers, so neither can we do so here. */
+ ELTSIZE is 1 for normal single byte character strings, and 2 or
+ 4 for wide characer strings. ELTSIZE is by default 1.
+
+ The value returned is of type `ssizetype'. */
tree
-c_strlen (tree src, int only_value)
+c_strlen (tree src, int only_value, tree *nonstr, unsigned eltsize)
{
+ gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
STRIP_NOPS (src);
if (TREE_CODE (src) == COND_EXPR
&& (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
{
tree len1, len2;
- len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
- len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
+ len1 = c_strlen (TREE_OPERAND (src, 1), only_value, nonstr, eltsize);
+ len2 = c_strlen (TREE_OPERAND (src, 2), only_value, nonstr, eltsize);
if (tree_int_cst_equal (len1, len2))
return len1;
}
if (TREE_CODE (src) == COMPOUND_EXPR
&& (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
- return c_strlen (TREE_OPERAND (src, 1), only_value);
+ return c_strlen (TREE_OPERAND (src, 1), only_value, nonstr, eltsize);
location_t loc = EXPR_LOC_OR_LOC (src, input_location);
/* Offset from the beginning of the string in bytes. */
tree byteoff;
- src = string_constant (src, &byteoff);
+ tree memsize;
+ tree decl;
+ src = string_constant (src, &byteoff, &memsize, &decl);
if (src == 0)
return NULL_TREE;
/* Determine the size of the string element. */
- unsigned eltsize
- = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (src))));
+ if (eltsize != tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (src)))))
+ return NULL_TREE;
/* Set MAXELTS to sizeof (SRC) / sizeof (*SRC) - 1, the maximum possible
length of SRC. Prefer TYPE_SIZE() to TREE_STRING_LENGTH() if possible
@@ -610,16 +662,12 @@ c_strlen (tree src, int only_value)
In that case, the elements of the array after the terminating NUL are
all NUL. */
HOST_WIDE_INT strelts = TREE_STRING_LENGTH (src);
- strelts = strelts / eltsize - 1;
+ strelts = strelts / eltsize;
- HOST_WIDE_INT maxelts = strelts;
- tree type = TREE_TYPE (src);
- if (tree size = TYPE_SIZE_UNIT (type))
- if (tree_fits_shwi_p (size))
- {
- maxelts = tree_to_uhwi (size);
- maxelts = maxelts / eltsize - 1;
- }
+ if (!tree_fits_uhwi_p (memsize))
+ return NULL_TREE;
+
+ HOST_WIDE_INT maxelts = tree_to_uhwi (memsize) / eltsize;
/* PTR can point to the byte representation of any string type, including
char* and wchar_t*. */
@@ -627,18 +675,28 @@ c_strlen (tree src, int only_value)
if (byteoff && TREE_CODE (byteoff) != INTEGER_CST)
{
+ /* The code below works only for single byte character types. */
+ if (eltsize != 1)
+ return NULL_TREE;
+
/* If the string has an internal NUL character followed by any
non-NUL characters (e.g., "foo\0bar"), we can't compute
the offset to the following NUL if we don't know where to
start searching for it. */
unsigned len = string_length (ptr, eltsize, strelts);
- if (len < strelts)
+
+ /* Return when an embedded null character is found or none at all. */
+ if (len + 1 < strelts)
+ return NULL_TREE;
+ else if (len >= maxelts)
{
- /* Return when an embedded null character is found. */
+ if (nonstr && decl)
+ *nonstr = decl;
return NULL_TREE;
}
- if (!maxelts)
+ /* For empty strings the result should be zero. */
+ if (len == 0)
return ssize_int (0);
/* We don't know the starting offset, but we do know that the string
@@ -649,8 +707,8 @@ c_strlen (tree src, int only_value)
tree offsave = TREE_SIDE_EFFECTS (byteoff) ? save_expr (byteoff) : byteoff;
offsave = fold_convert (ssizetype, offsave);
tree condexp = fold_build2_loc (loc, LE_EXPR, boolean_type_node, offsave,
- build_int_cst (ssizetype, len * eltsize));
- tree lenexp = size_diffop_loc (loc, ssize_int (strelts * eltsize), offsave);
+ build_int_cst (ssizetype, len));
+ tree lenexp = size_diffop_loc (loc, ssize_int (len), offsave);
return fold_build3_loc (loc, COND_EXPR, ssizetype, condexp, lenexp,
build_zero_cst (ssizetype));
}
@@ -662,14 +720,14 @@ c_strlen (tree src, int only_value)
a null character if we can represent it as a single HOST_WIDE_INT. */
if (byteoff == 0)
eltoff = 0;
- else if (! tree_fits_shwi_p (byteoff))
+ else if (! tree_fits_uhwi_p (byteoff) || tree_to_uhwi (byteoff) % eltsize)
eltoff = -1;
else
- eltoff = tree_to_shwi (byteoff) / eltsize;
+ eltoff = tree_to_uhwi (byteoff) / eltsize;
/* If the offset is known to be out of bounds, warn, and call strlen at
runtime. */
- if (eltoff < 0 || eltoff > maxelts)
+ if (eltoff < 0 || eltoff >= maxelts)
{
/* Suppress multiple warnings for propagated constant strings. */
if (only_value != 2
@@ -683,6 +741,11 @@ c_strlen (tree src, int only_value)
return NULL_TREE;
}
+ /* If eltoff is larger than strelts but less than maxelts the
+ string length is zero, since the excess memory will be zero. */
+ if (eltoff > strelts)
+ return ssize_int (0);
+
/* Use strlen to search for the first zero byte. Since any strings
constructed with build_string will have nulls appended, we win even
if we get handed something like (char[4])"abcd".
@@ -690,7 +753,16 @@ c_strlen (tree src, int only_value)
Since ELTOFF is our starting index into the string, no further
calculation is needed. */
unsigned len = string_length (ptr + eltoff * eltsize, eltsize,
- maxelts - eltoff);
+ strelts - eltoff);
+
+ /* Don't know what to return if there was no zero termination.
+ Ideally this would turn into a gcc_checking_assert over time. */
+ if (len >= maxelts - eltoff)
+ {
+ if (nonstr && decl)
+ *nonstr = decl;
+ return NULL_TREE;
+ }
return ssize_int (len);
}
@@ -2971,6 +3043,10 @@ expand_builtin_strnlen (tree exp, rtx target, machine_mode target_mode)
tree func = get_callee_fndecl (exp);
tree len = c_strlen (src, 0);
+ /* FIXME: Change c_strlen() to return sizetype instead of ssizetype
+ so these conversions aren't necessary. */
+ if (len)
+ len = fold_convert_loc (loc, TREE_TYPE (bound), len);
if (TREE_CODE (bound) == INTEGER_CST)
{
@@ -2985,7 +3061,6 @@ expand_builtin_strnlen (tree exp, rtx target, machine_mode target_mode)
if (!len || TREE_CODE (len) != INTEGER_CST)
return NULL_RTX;
- len = fold_convert_loc (loc, size_type_node, len);
len = fold_build2_loc (loc, MIN_EXPR, size_type_node, len, bound);
return expand_expr (len, target, target_mode, EXPAND_NORMAL);
}
@@ -3835,7 +3910,7 @@ expand_builtin_strcpy (tree exp, rtx target)
src, destsize);
}
- if (rtx ret = expand_builtin_strcpy_args (dest, src, target))
+ if (rtx ret = expand_builtin_strcpy_args (exp, dest, src, target))
{
/* Check to see if the argument was declared attribute nonstring
and if so, issue a warning since at this point it's not known
@@ -3855,8 +3930,17 @@ expand_builtin_strcpy (tree exp, rtx target)
expand_builtin_strcpy. */
static rtx
-expand_builtin_strcpy_args (tree dest, tree src, rtx target)
+expand_builtin_strcpy_args (tree exp, tree dest, tree src, rtx target)
{
+ /* Detect strcpy calls with unterminated arrays.. */
+ if (tree nonstr = unterminated_array (src))
+ {
+ /* NONSTR refers to the non-nul terminated constant array. */
+ if (!TREE_NO_WARNING (exp))
+ warn_string_no_nul (EXPR_LOCATION (exp), "strcpy", src, nonstr);
+ return NULL_RTX;
+ }
+
return expand_movstr (dest, src, target, /*endp=*/0);
}
@@ -3900,9 +3984,14 @@ expand_builtin_stpcpy_1 (tree exp, rtx target, machine_mode mode)
compile-time, not an expression containing a string. This is
because the latter will potentially produce pessimized code
when used to produce the return value. */
- if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
+ tree nonstr = NULL_TREE;
+ if (!c_getstr (src, NULL)
+ || !(len = c_strlen (src, 0, &nonstr, 1)))
return expand_movstr (dst, src, target, /*endp=*/2);
+ if (nonstr && !TREE_NO_WARNING (exp))
+ warn_string_no_nul (EXPR_LOCATION (exp), "stpcpy", src, nonstr);
+
lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
ret = expand_builtin_mempcpy_args (dst, src, lenp1,
target, exp, /*endp=*/2);
@@ -3916,7 +4005,7 @@ expand_builtin_stpcpy_1 (tree exp, rtx target, machine_mode mode)
if (CONST_INT_P (len_rtx))
{
- ret = expand_builtin_strcpy_args (dst, src, target);
+ ret = expand_builtin_strcpy_args (exp, dst, src, target);
if (ret)
{
@@ -4480,11 +4569,16 @@ expand_builtin_memcmp (tree exp, rtx target, bool result_eq)
/*objsize=*/NULL_TREE);
}
+ /* If the specified length exceeds the size of either object,
+ call the function. */
+ if (!no_overflow)
+ return NULL_RTX;
+
/* Due to the performance benefit, always inline the calls first
when result_eq is false. */
rtx result = NULL_RTX;
- if (!result_eq && fcode != BUILT_IN_BCMP && no_overflow)
+ if (!result_eq && fcode != BUILT_IN_BCMP)
{
result = inline_expand_builtin_string_cmp (exp, target);
if (result)
@@ -4746,7 +4840,10 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
/* If we are not using the given length, we must incorporate it here.
The actual new length parameter will be MIN(len,arg3) in this case. */
if (len != len3)
- len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, len3);
+ {
+ len = fold_convert_loc (loc, sizetype, len);
+ len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, len3);
+ }
rtx arg1_rtx = get_memory_rtx (arg1, len);
rtx arg2_rtx = get_memory_rtx (arg2, len);
rtx arg3_rtx = expand_normal (len);
@@ -5251,6 +5348,27 @@ expand_builtin_expect (tree exp, rtx target)
return target;
}
+/* Expand a call to __builtin_expect_with_probability. We just return our
+ argument as the builtin_expect semantic should've been already executed by
+ tree branch prediction pass. */
+
+static rtx
+expand_builtin_expect_with_probability (tree exp, rtx target)
+{
+ tree arg;
+
+ if (call_expr_nargs (exp) < 3)
+ return const0_rtx;
+ arg = CALL_EXPR_ARG (exp, 0);
+
+ target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
+ /* When guessing was done, the hints should be already stripped away. */
+ gcc_assert (!flag_guess_branch_prob
+ || optimize == 0 || seen_error ());
+ return target;
+}
+
+
/* Expand a call to __builtin_assume_aligned. We just return our first
argument as the builtin_assume_aligned semantic should've been already
executed by CCP. */
@@ -5745,14 +5863,21 @@ static rtx
get_builtin_sync_mem (tree loc, machine_mode mode)
{
rtx addr, mem;
+ int addr_space = TYPE_ADDR_SPACE (POINTER_TYPE_P (TREE_TYPE (loc))
+ ? TREE_TYPE (TREE_TYPE (loc))
+ : TREE_TYPE (loc));
+ scalar_int_mode addr_mode = targetm.addr_space.address_mode (addr_space);
- addr = expand_expr (loc, NULL_RTX, ptr_mode, EXPAND_SUM);
- addr = convert_memory_address (Pmode, addr);
+ addr = expand_expr (loc, NULL_RTX, addr_mode, EXPAND_SUM);
/* Note that we explicitly do not want any alias information for this
memory, so that we kill all other live memories. Otherwise we don't
satisfy the full barrier semantics of the intrinsic. */
- mem = validize_mem (gen_rtx_MEM (mode, addr));
+ mem = gen_rtx_MEM (mode, addr);
+
+ set_mem_addr_space (mem, addr_space);
+
+ mem = validize_mem (mem);
/* The alignment needs to be at least according to that of the mode. */
set_mem_align (mem, MAX (GET_MODE_ALIGNMENT (mode),
@@ -6918,6 +7043,55 @@ inline_expand_builtin_string_cmp (tree exp, rtx target)
const_str_n, mode);
}
+/* Expand a call to __builtin_speculation_safe_value_<N>. MODE
+ represents the size of the first argument to that call, or VOIDmode
+ if the argument is a pointer. IGNORE will be true if the result
+ isn't used. */
+static rtx
+expand_speculation_safe_value (machine_mode mode, tree exp, rtx target,
+ bool ignore)
+{
+ rtx val, failsafe;
+ unsigned nargs = call_expr_nargs (exp);
+
+ tree arg0 = CALL_EXPR_ARG (exp, 0);
+
+ if (mode == VOIDmode)
+ {
+ mode = TYPE_MODE (TREE_TYPE (arg0));
+ gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
+ }
+
+ val = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL);
+
+ /* An optional second argument can be used as a failsafe value on
+ some machines. If it isn't present, then the failsafe value is
+ assumed to be 0. */
+ if (nargs > 1)
+ {
+ tree arg1 = CALL_EXPR_ARG (exp, 1);
+ failsafe = expand_expr (arg1, NULL_RTX, mode, EXPAND_NORMAL);
+ }
+ else
+ failsafe = const0_rtx;
+
+ /* If the result isn't used, the behavior is undefined. It would be
+ nice to emit a warning here, but path splitting means this might
+ happen with legitimate code. So simply drop the builtin
+ expansion in that case; we've handled any side-effects above. */
+ if (ignore)
+ return const0_rtx;
+
+ /* If we don't have a suitable target, create one to hold the result. */
+ if (target == NULL || GET_MODE (target) != mode)
+ target = gen_reg_rtx (mode);
+
+ if (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode)
+ val = convert_modes (mode, VOIDmode, val, false);
+
+ return targetm.speculation_safe_value (mode, target, val, failsafe);
+}
+
/* Expand an expression EXP that calls a built-in function,
with result going to TARGET if that's convenient
(and in mode MODE if that's convenient).
@@ -7513,6 +7687,8 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
return expand_builtin_va_copy (exp);
case BUILT_IN_EXPECT:
return expand_builtin_expect (exp, target);
+ case BUILT_IN_EXPECT_WITH_PROBABILITY:
+ return expand_builtin_expect_with_probability (exp, target);
case BUILT_IN_ASSUME_ALIGNED:
return expand_builtin_assume_aligned (exp, target);
case BUILT_IN_PREFETCH:
@@ -8029,6 +8205,17 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
case BUILT_IN_GOACC_PARLEVEL_SIZE:
return expand_builtin_goacc_parlevel_id_size (exp, target, ignore);
+ case BUILT_IN_SPECULATION_SAFE_VALUE_PTR:
+ return expand_speculation_safe_value (VOIDmode, exp, target, ignore);
+
+ case BUILT_IN_SPECULATION_SAFE_VALUE_1:
+ case BUILT_IN_SPECULATION_SAFE_VALUE_2:
+ case BUILT_IN_SPECULATION_SAFE_VALUE_4:
+ case BUILT_IN_SPECULATION_SAFE_VALUE_8:
+ case BUILT_IN_SPECULATION_SAFE_VALUE_16:
+ mode = get_builtin_sync_mode (fcode - BUILT_IN_SPECULATION_SAFE_VALUE_1);
+ return expand_speculation_safe_value (mode, exp, target, ignore);
+
default: /* just do library call, if unknown builtin */
break;
}
@@ -8055,11 +8242,8 @@ builtin_mathfn_code (const_tree t)
return END_BUILTINS;
fndecl = get_callee_fndecl (t);
- if (fndecl == NULL_TREE
- || TREE_CODE (fndecl) != FUNCTION_DECL
- || ! DECL_BUILT_IN (fndecl)
- || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
- return END_BUILTINS;
+ if (fndecl == NULL_TREE || !fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
+ return END_BUILTINS;
parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
init_const_call_expr_arg_iterator (t, &iter);
@@ -8153,16 +8337,20 @@ fold_builtin_constant_p (tree arg)
return NULL_TREE;
}
-/* Create builtin_expect with PRED and EXPECTED as its arguments and
- return it as a truthvalue. */
+/* Create builtin_expect or builtin_expect_with_probability
+ with PRED and EXPECTED as its arguments and return it as a truthvalue.
+ Fortran FE can also produce builtin_expect with PREDICTOR as third argument.
+ builtin_expect_with_probability instead uses third argument as PROBABILITY
+ value. */
static tree
build_builtin_expect_predicate (location_t loc, tree pred, tree expected,
- tree predictor)
+ tree predictor, tree probability)
{
tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
- fn = builtin_decl_explicit (BUILT_IN_EXPECT);
+ fn = builtin_decl_explicit (probability == NULL_TREE ? BUILT_IN_EXPECT
+ : BUILT_IN_EXPECT_WITH_PROBABILITY);
arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
ret_type = TREE_TYPE (TREE_TYPE (fn));
pred_type = TREE_VALUE (arg_types);
@@ -8170,18 +8358,23 @@ build_builtin_expect_predicate (location_t loc, tree pred, tree expected,
pred = fold_convert_loc (loc, pred_type, pred);
expected = fold_convert_loc (loc, expected_type, expected);
- call_expr = build_call_expr_loc (loc, fn, predictor ? 3 : 2, pred, expected,
- predictor);
+
+ if (probability)
+ call_expr = build_call_expr_loc (loc, fn, 3, pred, expected, probability);
+ else
+ call_expr = build_call_expr_loc (loc, fn, predictor ? 3 : 2, pred, expected,
+ predictor);
return build2 (NE_EXPR, TREE_TYPE (pred), call_expr,
build_int_cst (ret_type, 0));
}
-/* Fold a call to builtin_expect with arguments ARG0 and ARG1. Return
+/* Fold a call to builtin_expect with arguments ARG0, ARG1, ARG2, ARG3. Return
NULL_TREE if no simplification is possible. */
tree
-fold_builtin_expect (location_t loc, tree arg0, tree arg1, tree arg2)
+fold_builtin_expect (location_t loc, tree arg0, tree arg1, tree arg2,
+ tree arg3)
{
tree inner, fndecl, inner_arg0;
enum tree_code code;
@@ -8205,8 +8398,8 @@ fold_builtin_expect (location_t loc, tree arg0, tree arg1, tree arg2)
if (TREE_CODE (inner) == CALL_EXPR
&& (fndecl = get_callee_fndecl (inner))
- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT)
+ && (fndecl_built_in_p (fndecl, BUILT_IN_EXPECT)
+ || fndecl_built_in_p (fndecl, BUILT_IN_EXPECT_WITH_PROBABILITY)))
return arg0;
inner = inner_arg0;
@@ -8217,8 +8410,8 @@ fold_builtin_expect (location_t loc, tree arg0, tree arg1, tree arg2)
tree op1 = TREE_OPERAND (inner, 1);
arg1 = save_expr (arg1);
- op0 = build_builtin_expect_predicate (loc, op0, arg1, arg2);
- op1 = build_builtin_expect_predicate (loc, op1, arg1, arg2);
+ op0 = build_builtin_expect_predicate (loc, op0, arg1, arg2, arg3);
+ op1 = build_builtin_expect_predicate (loc, op1, arg1, arg2, arg3);
inner = build2 (code, TREE_TYPE (inner), op0, op1);
return fold_convert_loc (loc, TREE_TYPE (arg0), inner);
@@ -8269,11 +8462,24 @@ fold_builtin_strlen (location_t loc, tree type, tree arg)
return NULL_TREE;
else
{
- tree len = c_strlen (arg, 0);
+ tree nonstr = NULL_TREE;
+ tree len = c_strlen (arg, 0, &nonstr);
if (len)
return fold_convert_loc (loc, type, len);
+ if (!nonstr)
+ c_strlen (arg, 1, &nonstr);
+
+ if (nonstr)
+ {
+ if (EXPR_HAS_LOCATION (arg))
+ loc = EXPR_LOCATION (arg);
+ else if (loc == UNKNOWN_LOCATION)
+ loc = input_location;
+ warn_string_no_nul (loc, "strlen", arg, nonstr);
+ }
+
return NULL_TREE;
}
}
@@ -9314,7 +9520,7 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1)
return fold_builtin_strpbrk (loc, arg0, arg1, type);
case BUILT_IN_EXPECT:
- return fold_builtin_expect (loc, arg0, arg1, NULL_TREE);
+ return fold_builtin_expect (loc, arg0, arg1, NULL_TREE, NULL_TREE);
case BUILT_IN_ISGREATER:
return fold_builtin_unordered_cmp (loc, fndecl,
@@ -9392,7 +9598,10 @@ fold_builtin_3 (location_t loc, tree fndecl,
return fold_builtin_memcmp (loc, arg0, arg1, arg2);
case BUILT_IN_EXPECT:
- return fold_builtin_expect (loc, arg0, arg1, arg2);
+ return fold_builtin_expect (loc, arg0, arg1, arg2, NULL_TREE);
+
+ case BUILT_IN_EXPECT_WITH_PROBABILITY:
+ return fold_builtin_expect (loc, arg0, arg1, NULL_TREE, arg2);
case BUILT_IN_ADD_OVERFLOW:
case BUILT_IN_SUB_OVERFLOW:
@@ -9516,9 +9725,7 @@ fold_call_expr (location_t loc, tree exp, bool ignore)
{
tree ret = NULL_TREE;
tree fndecl = get_callee_fndecl (exp);
- if (fndecl
- && TREE_CODE (fndecl) == FUNCTION_DECL
- && DECL_BUILT_IN (fndecl)
+ if (fndecl && fndecl_built_in_p (fndecl)
/* If CALL_EXPR_VA_ARG_PACK is set, the arguments aren't finalized
yet. Defer folding until we see all the arguments
(after inlining). */
@@ -9532,10 +9739,7 @@ fold_call_expr (location_t loc, tree exp, bool ignore)
if (nargs && TREE_CODE (CALL_EXPR_ARG (exp, nargs - 1)) == CALL_EXPR)
{
tree fndecl2 = get_callee_fndecl (CALL_EXPR_ARG (exp, nargs - 1));
- if (fndecl2
- && TREE_CODE (fndecl2) == FUNCTION_DECL
- && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
+ if (fndecl2 && fndecl_built_in_p (fndecl2, BUILT_IN_VA_ARG_PACK))
return NULL_TREE;
}
@@ -9571,17 +9775,14 @@ fold_builtin_call_array (location_t loc, tree,
tree fndecl = TREE_OPERAND (fn, 0);
if (TREE_CODE (fndecl) == FUNCTION_DECL
- && DECL_BUILT_IN (fndecl))
+ && fndecl_built_in_p (fndecl))
{
/* If last argument is __builtin_va_arg_pack (), arguments to this
function are not finalized yet. Defer folding until they are. */
if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
{
tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
- if (fndecl2
- && TREE_CODE (fndecl2) == FUNCTION_DECL
- && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
+ if (fndecl2 && fndecl_built_in_p (fndecl2, BUILT_IN_VA_ARG_PACK))
return NULL_TREE;
}
if (avoid_folding_inline_builtin (fndecl))
@@ -10700,9 +10901,7 @@ fold_call_stmt (gcall *stmt, bool ignore)
tree ret = NULL_TREE;
tree fndecl = gimple_call_fndecl (stmt);
location_t loc = gimple_location (stmt);
- if (fndecl
- && TREE_CODE (fndecl) == FUNCTION_DECL
- && DECL_BUILT_IN (fndecl)
+ if (fndecl && fndecl_built_in_p (fndecl)
&& !gimple_call_va_arg_pack_p (stmt))
{
int nargs = gimple_call_num_args (stmt);
@@ -10749,8 +10948,7 @@ fold_call_stmt (gcall *stmt, bool ignore)
void
set_builtin_user_assembler_name (tree decl, const char *asmspec)
{
- gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
+ gcc_assert (fndecl_built_in_p (decl, BUILT_IN_NORMAL)
&& asmspec != 0);
tree builtin = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
@@ -10770,7 +10968,7 @@ set_builtin_user_assembler_name (tree decl, const char *asmspec)
bool
is_simple_builtin (tree decl)
{
- if (decl && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
+ if (decl && fndecl_built_in_p (decl, BUILT_IN_NORMAL))
switch (DECL_FUNCTION_CODE (decl))
{
/* Builtins that expand to constants. */
diff --git a/gcc/builtins.def b/gcc/builtins.def
index aacbd51..ef89729 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -848,6 +848,7 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECVP, "execvp", BT_FN_INT_CONST_STRING_PT
DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECVE, "execve", BT_FN_INT_CONST_STRING_PTR_CONST_STRING_PTR_CONST_STRING, ATTR_NOTHROW_LIST)
DEF_LIB_BUILTIN (BUILT_IN_EXIT, "exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST)
DEF_GCC_BUILTIN (BUILT_IN_EXPECT, "expect", BT_FN_LONG_LONG_LONG, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_EXPECT_WITH_PROBABILITY, "expect_with_probability", BT_FN_LONG_LONG_LONG_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_ASSUME_ALIGNED, "assume_aligned", BT_FN_PTR_CONST_PTR_SIZE_VAR, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_EXTEND_POINTER, "extend_pointer", BT_FN_UNWINDWORD_PTR, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_EXTRACT_RETURN_ADDR, "extract_return_addr", BT_FN_PTR_PTR, ATTR_LEAF_LIST)
@@ -1003,6 +1004,28 @@ DEF_BUILTIN (BUILT_IN_EMUTLS_REGISTER_COMMON,
true, true, true, ATTR_NOTHROW_LEAF_LIST, false,
!targetm.have_tls)
+/* Suppressing speculation. Users are expected to use the first (N)
+ variant, which will be translated internally into one of the other
+ types. */
+
+DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_N, "speculation_safe_value",
+ BT_FN_VOID_VAR, ATTR_NOVOPS_NOTHROW_LEAF_LIST)
+
+DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_PTR,
+ "speculation_safe_value_ptr", BT_FN_PTR_PTR_VAR,
+ ATTR_NOVOPS_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_1, "speculation_safe_value_1",
+ BT_FN_I1_I1_VAR, ATTR_NOVOPS_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_2, "speculation_safe_value_2",
+ BT_FN_I2_I2_VAR, ATTR_NOVOPS_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_4, "speculation_safe_value_4",
+ BT_FN_I4_I4_VAR, ATTR_NOVOPS_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_8, "speculation_safe_value_8",
+ BT_FN_I8_I8_VAR, ATTR_NOVOPS_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_16,
+ "speculation_safe_value_16", BT_FN_I16_I16_VAR,
+ ATTR_NOVOPS_NOTHROW_LEAF_LIST)
+
/* Exception support. */
DEF_BUILTIN_STUB (BUILT_IN_UNWIND_RESUME, "__builtin_unwind_resume")
DEF_BUILTIN_STUB (BUILT_IN_CXA_END_CLEANUP, "__builtin_cxa_end_cleanup")
diff --git a/gcc/builtins.h b/gcc/builtins.h
index 2e0a2f9..45ad684 100644
--- a/gcc/builtins.h
+++ b/gcc/builtins.h
@@ -49,7 +49,6 @@ extern struct target_builtins *this_target_builtins;
/* Non-zero if __builtin_constant_p should be folded right away. */
extern bool force_folding_builtin_constant_p;
-extern bool is_builtin_fn (tree);
extern bool called_as_built_in (tree);
extern bool get_object_alignment_1 (tree, unsigned int *,
unsigned HOST_WIDE_INT *);
@@ -58,7 +57,7 @@ extern bool get_pointer_alignment_1 (tree, unsigned int *,
unsigned HOST_WIDE_INT *);
extern unsigned int get_pointer_alignment (tree);
extern unsigned string_length (const void*, unsigned, unsigned);
-extern tree c_strlen (tree, int);
+extern tree c_strlen (tree, int, tree * = NULL, unsigned = 1);
extern void expand_builtin_setjmp_setup (rtx, rtx);
extern void expand_builtin_setjmp_receiver (rtx);
extern void expand_builtin_update_setjmp_buf (rtx);
@@ -77,7 +76,7 @@ extern void expand_ifn_atomic_compare_exchange (gcall *);
extern rtx expand_builtin (tree, rtx, rtx, machine_mode, int);
extern rtx expand_builtin_with_bounds (tree, rtx, rtx, machine_mode, int);
extern enum built_in_function builtin_mathfn_code (const_tree);
-extern tree fold_builtin_expect (location_t, tree, tree, tree);
+extern tree fold_builtin_expect (location_t, tree, tree, tree, tree);
extern bool avoid_folding_inline_builtin (tree);
extern tree fold_call_expr (location_t, tree, bool);
extern tree fold_builtin_call_array (location_t, tree, tree, int, tree *);
@@ -104,6 +103,8 @@ extern bool target_char_cst_p (tree t, char *p);
extern internal_fn associated_internal_fn (tree);
extern internal_fn replacement_internal_fn (gcall *);
+extern void warn_string_no_nul (location_t, const char *, tree, tree);
+extern tree unterminated_array (tree);
extern tree max_object_size ();
#endif /* GCC_BUILTINS_H */
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 0ae008b..4080bee 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,220 @@
+2018-09-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * c-ada-spec.c: Include diagnostic.h.
+ (dump_ada_declaration) <RECORD_TYPE>: Issue a warning on packed layout.
+
+2018-09-19 Marek Polacek <polacek@redhat.com>
+
+ * c.opt (Wclass-conversion): New.
+
+2018-09-17 David Malcolm <dmalcolm@redhat.com>
+
+ * c-format.c (range_label_for_format_type_mismatch::get_text):
+ Update for new param.
+
+2018-09-17 David Malcolm <dmalcolm@redhat.com>
+
+ * c-format.c (format_warning_at_char): Update for introduction of
+ format_string_diagnostic_t.
+ (format_type_warning): Likewise.
+
+2018-09-17 Martin Jambor <mjambor@suse.cz>
+
+ PR c/63886
+ * c.opt (Wabsolute-value): New.
+
+2018-09-06 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * c-common.c (complete_flexible_array_elts): New helper function.
+ * c-common.h (complete_flexible_array_elts): Declare.
+
+2018-09-02 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * c-common.c (braced_list_to_string): Remove eval parameter.
+ Add some more checks. Always create zero-terminated STRING_CST.
+ * c-common.h (braced_list_to_string): Adjust prototype.
+
+2018-08-27 David Malcolm <dmalcolm@redhat.com>
+
+ PR 87091
+ * c-common.c (c_cpp_error): Update for conversion of show_caret_p
+ to a tri-state.
+ (maybe_suggest_missing_token_insertion): Likewise.
+ (maybe_add_include_fixit): Add param "override_location". If set,
+ and source-printing is enabled, then override the rich_location's
+ primary location with that of the insertion point for the fix-it
+ hint, marking it with SHOW_LINES_WITHOUT_RANGE.
+ * c-common.h (extern void maybe_add_include_fixit): Add bool
+ param.
+ * c-format.c (selftest::test_type_mismatch_range_labels): Update
+ for conversion of show_caret_p to a tri-state.
+ * c-warn.c (warn_for_restrict): Likewise.
+ * known-headers.cc
+ (suggest_missing_header::~suggest_missing_header): Update call to
+ maybe_add_include_fixit to suggest overriding the location, as it
+ is for a note.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ * c-common.c (check_function_restrict): Use new function
+ fndecl_built_in_p and remove check for FUNCTION_DECL if
+ possible.
+ (check_builtin_function_arguments): Likewise.
+ (reject_gcc_builtin): Likewise.
+ * c-warn.c (sizeof_pointer_memaccess_warning): Likewise.
+
+2018-08-26 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87029, Implement -Wredundant-move.
+ * c.opt (Wredundant-move): New option.
+
+2018-08-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/86981, Implement -Wpessimizing-move.
+ * c.opt (Wpessimizing-move): New option.
+
+2018-08-20 David Malcolm <dmalcolm@redhat.com>
+
+ PR other/84889
+ * c-attribs.c (common_handle_aligned_attribute): Add
+ auto_diagnostic_group instance.
+ * c-indentation.c (warn_for_misleading_indentation): Likewise.
+ * c-opts.c (c_common_post_options): Likewise.
+ * c-warn.c (warn_logical_not_parentheses): Likewise.
+ (warn_duplicated_cond_add_or_warn): Likewise.
+ (warn_for_multistatement_macros): Likewise.
+
+2018-08-20 Nathan Sidwell <nathan@acm.org>
+
+ * c-ada-spec.c (macro_length, dump_ada_macros): Adjust macro parm
+ access.
+
+2018-08-17 Nathan Sidwell <nathan@acm.org>
+
+ * c-cppbuiltin.c (struct lazy_hex_fp_value_struct): Remove macro
+ field.
+ (laxy_hex_fp_value_count): Make unsigned.
+ (lazy_hex_fp_value): Provided with macro & lazy number. Directly
+ manipulate the macro.
+ (builtin_defin_with_hex_fp_value): Adjust callback name, use
+ cpp_define_lazily.
+
+2018-08-17 David Malcolm <dmalcolm@redhat.com>
+
+ * c-format.c (enum format_type): Add gcc_dump_printf_format_type.
+ (gcc_dump_printf_length_specs): New.
+ (gcc_dump_printf_flag_pairs): New.
+ (gcc_dump_printf_flag_specs): New.
+ (gcc_dump_printf_char_table): New.
+ (format_types_orig): Add entry for "gcc_dump_printf".
+ (init_dynamic_diag_info): Set up length_char_specs and
+ conversion_specs for gcc_dump_printf_format_type.
+ (handle_format_attribute): Handle gcc_dump_printf_format_type.
+
+2018-08-17 Nathan Sidwell <nathan@acm.org>
+
+ * c-ada-spec.c (macro_length, dump_ada_macros): Constify.
+
+ * c-ada-spec.c: Don't #include "cpp-id-data.h"
+ * c-cppbuiltin.c: Likewise.
+
+2018-08-17 Martin Liska <mliska@suse.cz>
+
+ * c.opt: Remove Warn, Init and Report for options with
+ Ignore/Deprecated flag. Warning is done automatically for
+ Deprecated flags.
+
+2018-08-16 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/70693
+ * c-common.c (selftest::c_family_tests): Call
+ selftest::c_indentation_c_tests.
+ * c-common.h (selftest::c_indentation_c_tests): New decl.
+ * c-indentation.c: Include "selftest.h".
+ (next_tab_stop): Add "tab_width" param, rather than accessing
+ cpp_opts.
+ (get_visual_column): Likewise. Clarify comment. Bulletproof
+ against reading past the end of the line.
+ (get_first_nws_vis_column): Add "tab_width" param.
+ (detect_intervening_unindent): Likewise.
+ (should_warn_for_misleading_indentation): Read tab width from
+ cpp_opts and pass around.
+ (selftest::test_next_tab_stop): New test.
+ (selftest::assert_get_visual_column_succeeds): New function.
+ (ASSERT_GET_VISUAL_COLUMN_SUCCEEDS): New macro.
+ (selftest::assert_get_visual_column_fails): New function.
+ (ASSERT_GET_VISUAL_COLUMN_FAILS): New macro.
+ (selftest::test_get_visual_column): New test.
+ (selftest::c_indentation_c_tests): New function.
+
+2018-08-16 Nathan Sidwell <nathan@acm.org>
+
+ * c-ada-spec.c (count_ada_macro): Use cpp_user_macro_p.
+ (store_ada_macro): Likewise.
+ * c-ppoutput.c (cb_used_define, dump_macro): Likewise.
+ * c-spellcheck.cc (should-suggest_as_macro_p): Likewise,
+
+2018-08-15 David Malcolm <dmalcolm@redhat.com>
+
+ * c-format.c: Include "selftest-diagnostic.h" and
+ "gcc-rich-location.h".
+ (format_warning_at_char): Pass NULL for new label params of
+ format_warning_va.
+ (class indirection_suffix): New class.
+ (class range_label_for_format_type_mismatch): New class.
+ (format_type_warning): Move logic for generating "*" suffix to
+ class indirection_suffix. Create "fmt_label" and "param_label"
+ to show their types, and pass them to the
+ format_warning_at_substring calls.
+ (selftest::test_type_mismatch_range_labels): New test.
+ (selftest::c_format_c_tests): Call it.
+
+2018-08-13 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/71625
+ * c-common.c (braced_list_to_string): New function.
+ * c-common.h (braced_list_to_string): Declare it.
+
+2018-08-08 Nathan Sidwell <nathan@acm.org>
+
+ * c-common.c (try_to_locate_new_include_inertion_point): Use
+ linemap_included_from_linemap.
+ * c-lex.c (fe_file_change): Use linemap_included_from.
+ * c-ppoutput.c (pp_file_change): Likewise.
+
+2018-08-01 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/86650
+ * c-family/c-format.c (gcc_tdiag_char_table): Update comment for "%G".
+ (gcc_cdiag_char_table, gcc_cxxdiag_char_table): Same.
+ (init_dynamic_diag_info): Update from "gcall *" to "gimple *".
+ * c-format.h (T89_G): Update to be "gimple *" rather than
+ "gcall *".
+ (local_gcall_ptr_node): Rename...
+ (local_gimple_ptr_node): ...to this.
+
+2018-07-31 David Malcolm <dmalcolm@redhat.com>
+
+ * c-format.c (PP_FORMAT_CHAR_TABLE): New macro, based on existing
+ table entries for gcc_diag_char_table, and the 'Z' entry from
+ gcc_tdiag_char_table, changing the "chain" entry for 'Z' from
+ &gcc_tdiag_char_table[0] to &gcc_diag_char_table[0].
+ (gcc_diag_char_table): Use PP_FORMAT_CHAR_TABLE, implicitly
+ adding missing "Z" for this table. Remove erroneous "G" and "K"
+ entries.
+ (gcc_tdiag_char_table): Use PP_FORMAT_CHAR_TABLE. Remove "v".
+ (gcc_cdiag_char_table): Use PP_FORMAT_CHAR_TABLE.
+ (gcc_cxxdiag_char_table): Use PP_FORMAT_CHAR_TABLE. Remove "v".
+
+2018-07-31 Richard Earnshaw <rearnsha@arm.com>
+
+ * c-common.c (speculation_safe_resolve_call): New function.
+ (speculation_safe_resolve_params): New function.
+ (speculation_safe_resolve_return): New function.
+ (resolve_overloaded_builtin): Handle __builtin_speculation_safe_value.
+ * c-cppbuiltin.c (c_cpp_builtins): Add pre-define for
+ __HAVE_SPECULATION_SAFE_VALUE.
+
2018-07-20 David Malcolm <dmalcolm@redhat.com>
* c-common.c (c_cpp_error): Remove redundant "line_table"
@@ -218,7 +435,7 @@
2018-05-11 Martin Liska <mliska@suse.cz>
- PR sanitizer/85556
+ PR sanitizer/85556
* c-attribs.c (handle_no_sanitize_attribute): Iterate all
TREE_LIST values.
@@ -457,11 +674,11 @@
2018-01-18 Boris Kolpackov <boris@codesynthesis.com>
- PR other/70268
- * c.opt (-fmacro-prefix-map): New option.
- * c-opts.c (c_common_handle_option): Handle it.
- * c-lex.c (init_c_lex): Set remap_filename cpp callback.
- * c-ppoutput.c (init_pp_output): Likewise.
+ PR other/70268
+ * c.opt (-fmacro-prefix-map): New option.
+ * c-opts.c (c_common_handle_option): Handle it.
+ * c-lex.c (init_c_lex): Set remap_filename cpp callback.
+ * c-ppoutput.c (init_pp_output): Likewise.
2018-01-17 David Malcolm <dmalcolm@redhat.com>
@@ -530,7 +747,7 @@
Update copyright years.
2017-12-22 Mike Stump <mikestump@comcast.net>
- Eric Botcazou <ebotcazou@adacore.com>
+ Eric Botcazou <ebotcazou@adacore.com>
* c-pragma.c (init_pragma): Register pragma GCC unroll.
* c-pragma.h (enum pragma_kind): Add PRAGMA_UNROLL.
@@ -652,7 +869,7 @@
* c-common.h (c_switch_covers_all_cases_p): Declare.
2017-11-28 Julia Koval <julia.koval@intel.com>
- Sebastian Peryt <sebastian.peryt@intel.com>
+ Sebastian Peryt <sebastian.peryt@intel.com>
* array-notation-common.c: Delete.
* c-cilkplus.c: Ditto.
@@ -1010,8 +1227,8 @@
* c-cppbuiltin.c (c_cpp_builtins): Use opt_scalar_float_mode.
2017-08-30 Richard Sandiford <richard.sandiford@linaro.org>
- Alan Hayward <alan.hayward@arm.com>
- David Sherwood <david.sherwood@arm.com>
+ Alan Hayward <alan.hayward@arm.com>
+ David Sherwood <david.sherwood@arm.com>
* c-common.c (c_common_fixed_point_type_for_size): Use new mode
iterators.
@@ -1473,7 +1690,7 @@
2017-05-01 Xi Ruoyao <ryxi@stu.xidian.edu.cn>
- PR c++/80038
+ PR c++/80038
* c-common.h (cilk_gimplify_call_params_in_spawned_fn): Remove
prototype.
(cilk_install_body_pedigree_operations): Likewise.
@@ -1797,8 +2014,8 @@
2016-12-08 Martin Sebor <msebor@redhat.com>
PR c/78165
- * c-pretty-print (pp_c_integer_constant): Avoid formatting type
- suffix.
+ * c-pretty-print (pp_c_integer_constant): Avoid formatting type
+ suffix.
2016-12-07 Martin Sebor <msebor@redhat.com>
diff --git a/gcc/c-family/c-ada-spec.c b/gcc/c-family/c-ada-spec.c
index 9c7de23..eae741e 100644
--- a/gcc/c-family/c-ada-spec.c
+++ b/gcc/c-family/c-ada-spec.c
@@ -27,7 +27,7 @@ along with GCC; see the file COPYING3. If not see
#include "c-ada-spec.h"
#include "fold-const.h"
#include "c-pragma.h"
-#include "cpp-id-data.h"
+#include "diagnostic.h"
#include "stringpool.h"
#include "attribs.h"
@@ -70,7 +70,7 @@ macro_length (const cpp_macro *macro, int *supported, int *buffer_len,
(*param_len)++;
for (i = 0; i < macro->paramc; i++)
{
- cpp_hashnode *param = macro->params[i];
+ cpp_hashnode *param = macro->parm.params[i];
*param_len += NODE_LEN (param);
@@ -89,7 +89,7 @@ macro_length (const cpp_macro *macro, int *supported, int *buffer_len,
for (j = 0; j < macro->count; j++)
{
- cpp_token *token = &macro->exp.tokens[j];
+ const cpp_token *token = &macro->exp.tokens[j];
if (token->flags & PREV_WHITE)
(*buffer_len)++;
@@ -102,7 +102,7 @@ macro_length (const cpp_macro *macro, int *supported, int *buffer_len,
if (token->type == CPP_MACRO_ARG)
*buffer_len +=
- NODE_LEN (macro->params[token->val.macro_arg.arg_no - 1]);
+ NODE_LEN (macro->parm.params[token->val.macro_arg.arg_no - 1]);
else
/* Include enough extra space to handle e.g. special characters. */
*buffer_len += (cpp_token_len (token) + 1) * 8;
@@ -171,13 +171,12 @@ static int
count_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *node,
void *v ATTRIBUTE_UNUSED)
{
- const cpp_macro *macro = node->value.macro;
-
- if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)
- && macro->count
- && *NODE_NAME (node) != '_'
- && LOCATION_FILE (macro->line) == macro_source_file)
- max_ada_macros++;
+ if (cpp_user_macro_p (node) && *NODE_NAME (node) != '_')
+ {
+ const cpp_macro *macro = node->value.macro;
+ if (macro->count && LOCATION_FILE (macro->line) == macro_source_file)
+ max_ada_macros++;
+ }
return 1;
}
@@ -190,15 +189,13 @@ static int
store_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED,
cpp_hashnode *node, void *macros)
{
- const cpp_macro *macro = node->value.macro;
-
- if (node->type == NT_MACRO
- && !(node->flags & NODE_BUILTIN)
- && macro->count
- && *NODE_NAME (node) != '_'
- && LOCATION_FILE (macro->line) == macro_source_file)
- ((cpp_hashnode **) macros)[store_ada_macro_index++] = node;
-
+ if (cpp_user_macro_p (node) && *NODE_NAME (node) != '_')
+ {
+ const cpp_macro *macro = node->value.macro;
+ if (macro->count
+ && LOCATION_FILE (macro->line) == macro_source_file)
+ ((cpp_hashnode **) macros)[store_ada_macro_index++] = node;
+ }
return 1;
}
@@ -256,7 +253,7 @@ dump_ada_macros (pretty_printer *pp, const char* file)
*buf_param++ = '(';
for (i = 0; i < macro->paramc; i++)
{
- cpp_hashnode *param = macro->params[i];
+ cpp_hashnode *param = macro->parm.params[i];
memcpy (buf_param, NODE_NAME (param), NODE_LEN (param));
buf_param += NODE_LEN (param);
@@ -278,7 +275,7 @@ dump_ada_macros (pretty_printer *pp, const char* file)
for (i = 0; supported && i < macro->count; i++)
{
- cpp_token *token = &macro->exp.tokens[i];
+ const cpp_token *token = &macro->exp.tokens[i];
int is_one = 0;
if (token->flags & PREV_WHITE)
@@ -295,7 +292,7 @@ dump_ada_macros (pretty_printer *pp, const char* file)
case CPP_MACRO_ARG:
{
cpp_hashnode *param =
- macro->params[token->val.macro_arg.arg_no - 1];
+ macro->parm.params[token->val.macro_arg.arg_no - 1];
memcpy (buffer, NODE_NAME (param), NODE_LEN (param));
buffer += NODE_LEN (param);
}
@@ -2704,6 +2701,16 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
return 1;
}
+ /* ??? Packed record layout is not supported. */
+ if (TYPE_PACKED (TREE_TYPE (t)))
+ {
+ warning_at (DECL_SOURCE_LOCATION (t), 0,
+ "unsupported record layout");
+ pp_string (buffer, "pragma Compile_Time_Warning (True, ");
+ pp_string (buffer, "\"probably incorrect record layout\");");
+ newline_and_indent (buffer, spc);
+ }
+
if (orig && TYPE_NAME (orig))
pp_string (buffer, "subtype ");
else
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 9da9c27..5454e09 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -1881,6 +1881,7 @@ common_handle_aligned_attribute (tree *node, tree name, tree args, int flags,
bitalign /= BITS_PER_UNIT;
bool diagd = true;
+ auto_diagnostic_group d;
if (DECL_USER_ALIGN (decl) || DECL_USER_ALIGN (last_decl))
diagd = warning (OPT_Wattributes,
"ignoring attribute %<%E (%u)%> because it conflicts "
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 422d668..4bfb145 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -5326,8 +5326,7 @@ check_function_restrict (const_tree fndecl, const_tree fntype,
{
/* Avoid diagnosing calls built-ins with a zero size/bound
here. They are checked in more detail elsewhere. */
- if (DECL_BUILT_IN (fndecl)
- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
+ if (fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
&& nargs == 3
&& TREE_CODE (argarray[2]) == INTEGER_CST
&& integer_zerop (argarray[2]))
@@ -5755,8 +5754,7 @@ bool
check_builtin_function_arguments (location_t loc, vec<location_t> arg_loc,
tree fndecl, int nargs, tree *args)
{
- if (!DECL_BUILT_IN (fndecl)
- || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL)
+ if (!fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
return true;
switch (DECL_FUNCTION_CODE (fndecl))
@@ -6133,7 +6131,7 @@ c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason,
gcc_unreachable ();
}
if (done_lexing)
- richloc->set_range (0, input_location, true);
+ richloc->set_range (0, input_location, SHOW_RANGE_WITH_CARET);
diagnostic_set_info_translated (&diagnostic, msg, ap,
richloc, dlevel);
diagnostic_override_option_index (&diagnostic,
@@ -6427,6 +6425,28 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
return failure;
}
+/* INIT is an constructor of a structure with a flexible array member.
+ Complete the flexible array member with a domain based on it's value. */
+void
+complete_flexible_array_elts (tree init)
+{
+ tree elt, type;
+
+ if (init == NULL_TREE || TREE_CODE (init) != CONSTRUCTOR)
+ return;
+
+ if (vec_safe_is_empty (CONSTRUCTOR_ELTS (init)))
+ return;
+
+ elt = CONSTRUCTOR_ELTS (init)->last ().value;
+ type = TREE_TYPE (elt);
+ if (TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_SIZE (type) == NULL_TREE)
+ complete_array_type (&TREE_TYPE (elt), elt, false);
+ else
+ complete_flexible_array_elts (elt);
+}
+
/* Like c_mark_addressable but don't check register qualifier. */
void
c_common_mark_addressable_vec (tree t)
@@ -6457,6 +6477,122 @@ builtin_type_for_size (int size, bool unsignedp)
return type ? type : error_mark_node;
}
+/* Work out the size of the first argument of a call to
+ __builtin_speculation_safe_value. Only pointers and integral types
+ are permitted. Return -1 if the argument type is not supported or
+ the size is too large; 0 if the argument type is a pointer or the
+ size if it is integral. */
+static enum built_in_function
+speculation_safe_value_resolve_call (tree function, vec<tree, va_gc> *params)
+{
+ /* Type of the argument. */
+ tree type;
+ int size;
+
+ if (vec_safe_is_empty (params))
+ {
+ error ("too few arguments to function %qE", function);
+ return BUILT_IN_NONE;
+ }
+
+ type = TREE_TYPE ((*params)[0]);
+ if (TREE_CODE (type) == ARRAY_TYPE && c_dialect_cxx ())
+ {
+ /* Force array-to-pointer decay for C++. */
+ (*params)[0] = default_conversion ((*params)[0]);
+ type = TREE_TYPE ((*params)[0]);
+ }
+
+ if (POINTER_TYPE_P (type))
+ return BUILT_IN_SPECULATION_SAFE_VALUE_PTR;
+
+ if (!INTEGRAL_TYPE_P (type))
+ goto incompatible;
+
+ if (!COMPLETE_TYPE_P (type))
+ goto incompatible;
+
+ size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
+ if (size == 1 || size == 2 || size == 4 || size == 8 || size == 16)
+ return ((enum built_in_function)
+ ((int) BUILT_IN_SPECULATION_SAFE_VALUE_1 + exact_log2 (size)));
+
+ incompatible:
+ /* Issue the diagnostic only if the argument is valid, otherwise
+ it would be redundant at best and could be misleading. */
+ if (type != error_mark_node)
+ error ("operand type %qT is incompatible with argument %d of %qE",
+ type, 1, function);
+
+ return BUILT_IN_NONE;
+}
+
+/* Validate and coerce PARAMS, the arguments to ORIG_FUNCTION to fit
+ the prototype for FUNCTION. The first argument is mandatory, a second
+ argument, if present, must be type compatible with the first. */
+static bool
+speculation_safe_value_resolve_params (location_t loc, tree orig_function,
+ vec<tree, va_gc> *params)
+{
+ tree val;
+
+ if (params->length () == 0)
+ {
+ error_at (loc, "too few arguments to function %qE", orig_function);
+ return false;
+ }
+
+ else if (params->length () > 2)
+ {
+ error_at (loc, "too many arguments to function %qE", orig_function);
+ return false;
+ }
+
+ val = (*params)[0];
+ if (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE)
+ val = default_conversion (val);
+ if (!(TREE_CODE (TREE_TYPE (val)) == POINTER_TYPE
+ || TREE_CODE (TREE_TYPE (val)) == INTEGER_TYPE))
+ {
+ error_at (loc,
+ "expecting argument of type pointer or of type integer "
+ "for argument 1");
+ return false;
+ }
+ (*params)[0] = val;
+
+ if (params->length () == 2)
+ {
+ tree val2 = (*params)[1];
+ if (TREE_CODE (TREE_TYPE (val2)) == ARRAY_TYPE)
+ val2 = default_conversion (val2);
+ if (!(TREE_TYPE (val) == TREE_TYPE (val2)
+ || useless_type_conversion_p (TREE_TYPE (val), TREE_TYPE (val2))))
+ {
+ error_at (loc, "both arguments must be compatible");
+ return false;
+ }
+ (*params)[1] = val2;
+ }
+
+ return true;
+}
+
+/* Cast the result of the builtin back to the type of the first argument,
+ preserving any qualifiers that it might have. */
+static tree
+speculation_safe_value_resolve_return (tree first_param, tree result)
+{
+ tree ptype = TREE_TYPE (first_param);
+ tree rtype = TREE_TYPE (result);
+ ptype = TYPE_MAIN_VARIANT (ptype);
+
+ if (tree_int_cst_equal (TYPE_SIZE (ptype), TYPE_SIZE (rtype)))
+ return convert (ptype, result);
+
+ return result;
+}
+
/* A helper function for resolve_overloaded_builtin in resolving the
overloaded __sync_ builtins. Returns a positive power of 2 if the
first operand of PARAMS is a pointer to a supported data type.
@@ -7111,6 +7247,54 @@ resolve_overloaded_builtin (location_t loc, tree function,
/* Handle BUILT_IN_NORMAL here. */
switch (orig_code)
{
+ case BUILT_IN_SPECULATION_SAFE_VALUE_N:
+ {
+ tree new_function, first_param, result;
+ enum built_in_function fncode
+ = speculation_safe_value_resolve_call (function, params);;
+
+ first_param = (*params)[0];
+ if (fncode == BUILT_IN_NONE
+ || !speculation_safe_value_resolve_params (loc, function, params))
+ return error_mark_node;
+
+ if (targetm.have_speculation_safe_value (true))
+ {
+ new_function = builtin_decl_explicit (fncode);
+ result = build_function_call_vec (loc, vNULL, new_function, params,
+ NULL);
+
+ if (result == error_mark_node)
+ return result;
+
+ return speculation_safe_value_resolve_return (first_param, result);
+ }
+ else
+ {
+ /* This target doesn't have, or doesn't need, active mitigation
+ against incorrect speculative execution. Simply return the
+ first parameter to the builtin. */
+ if (!targetm.have_speculation_safe_value (false))
+ /* The user has invoked __builtin_speculation_safe_value
+ even though __HAVE_SPECULATION_SAFE_VALUE is not
+ defined: emit a warning. */
+ warning_at (input_location, 0,
+ "this target does not define a speculation barrier; "
+ "your program will still execute correctly, "
+ "but incorrect speculation may not be be "
+ "restricted");
+
+ /* If the optional second argument is present, handle any side
+ effects now. */
+ if (params->length () == 2
+ && TREE_SIDE_EFFECTS ((*params)[1]))
+ return build2 (COMPOUND_EXPR, TREE_TYPE (first_param),
+ (*params)[1], first_param);
+
+ return first_param;
+ }
+ }
+
case BUILT_IN_ATOMIC_EXCHANGE:
case BUILT_IN_ATOMIC_COMPARE_EXCHANGE:
case BUILT_IN_ATOMIC_LOAD:
@@ -7847,7 +8031,7 @@ reject_gcc_builtin (const_tree expr, location_t loc /* = UNKNOWN_LOCATION */)
strlen, and for C++ operators new and delete.
The c_decl_implicit() test avoids false positives for implicitly
declared built-ins with library fallbacks (such as abs). */
- && DECL_BUILT_IN (expr)
+ && fndecl_built_in_p (expr)
&& DECL_IS_BUILTIN (expr)
&& !c_decl_implicit (expr)
&& !DECL_ASSEMBLER_NAME_SET_P (expr))
@@ -8174,8 +8358,8 @@ maybe_suggest_missing_token_insertion (rich_location *richloc,
location_t hint_loc = hint->get_start_loc ();
location_t old_loc = richloc->get_loc ();
- richloc->set_range (0, hint_loc, true);
- richloc->add_range (old_loc, false);
+ richloc->set_range (0, hint_loc, SHOW_RANGE_WITH_CARET);
+ richloc->add_range (old_loc);
}
}
@@ -8206,6 +8390,7 @@ c_family_tests (void)
{
c_common_c_tests ();
c_format_c_tests ();
+ c_indentation_c_tests ();
c_pretty_print_c_tests ();
c_spellcheck_cc_tests ();
}
@@ -8249,8 +8434,8 @@ try_to_locate_new_include_insertion_point (const char *file, location_t loc)
const line_map_ordinary *ord_map
= LINEMAPS_ORDINARY_MAP_AT (line_table, i);
- const line_map_ordinary *from = INCLUDED_FROM (line_table, ord_map);
- if (from)
+ if (const line_map_ordinary *from
+ = linemap_included_from_linemap (line_table, ord_map))
if (from->to_file == file)
{
last_include_ord_map = from;
@@ -8312,10 +8497,16 @@ static added_includes_t *added_includes;
location.
This function is idempotent: a header will be added at most once to
- any given file. */
+ any given file.
+
+ If OVERRIDE_LOCATION is true, then if a fix-it is added and will be
+ printed, then RICHLOC's primary location will be replaced by that of
+ the fix-it hint (for use by "inform" notes where the location of the
+ issue has already been reported). */
void
-maybe_add_include_fixit (rich_location *richloc, const char *header)
+maybe_add_include_fixit (rich_location *richloc, const char *header,
+ bool override_location)
{
location_t loc = richloc->get_loc ();
const char *file = LOCATION_FILE (loc);
@@ -8343,6 +8534,118 @@ maybe_add_include_fixit (rich_location *richloc, const char *header)
char *text = xasprintf ("#include %s\n", header);
richloc->add_fixit_insert_before (include_insert_loc, text);
free (text);
+
+ if (override_location && global_dc->show_caret)
+ {
+ /* Replace the primary location with that of the insertion point for the
+ fix-it hint.
+
+ We use SHOW_LINES_WITHOUT_RANGE so that we don't meaningless print a
+ caret for the insertion point (or colorize it).
+
+ Hence we print e.g.:
+
+ ../x86_64-pc-linux-gnu/libstdc++-v3/include/vector:74:1: note: msg 2
+ 73 | # include <debug/vector>
+ +++ |+#include <vector>
+ 74 | #endif
+
+ rather than:
+
+ ../x86_64-pc-linux-gnu/libstdc++-v3/include/vector:74:1: note: msg 2
+ 73 | # include <debug/vector>
+ +++ |+#include <vector>
+ 74 | #endif
+ | ^
+
+ avoiding the caret on the first column of line 74. */
+ richloc->set_range (0, include_insert_loc, SHOW_LINES_WITHOUT_RANGE);
+ }
+}
+
+/* Attempt to convert a braced array initializer list CTOR for array
+ TYPE into a STRING_CST for convenience and efficiency. Return
+ the converted string on success or the original ctor on failure. */
+
+tree
+braced_list_to_string (tree type, tree ctor)
+{
+ if (!tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
+ return ctor;
+
+ /* If the array has an explicit bound, use it to constrain the size
+ of the string. If it doesn't, be sure to create a string that's
+ as long as implied by the index of the last zero specified via
+ a designator, as in:
+ const char a[] = { [7] = 0 }; */
+ unsigned HOST_WIDE_INT maxelts = tree_to_uhwi (TYPE_SIZE_UNIT (type));
+ maxelts /= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
+
+ /* Avoid converting initializers for zero-length arrays. */
+ if (!maxelts)
+ return ctor;
+
+ unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (ctor);
+
+ auto_vec<char> str;
+ str.reserve (nelts + 1);
+
+ unsigned HOST_WIDE_INT i;
+ tree index, value;
+
+ FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), i, index, value)
+ {
+ unsigned HOST_WIDE_INT idx = i;
+ if (index)
+ {
+ if (!tree_fits_uhwi_p (index))
+ return ctor;
+ idx = tree_to_uhwi (index);
+ }
+
+ /* auto_vec is limited to UINT_MAX elements. */
+ if (idx > UINT_MAX)
+ return ctor;
+
+ /* Avoid non-constant initializers. */
+ if (!tree_fits_shwi_p (value))
+ return ctor;
+
+ /* Skip over embedded nuls except the last one (initializer
+ elements are in ascending order of indices). */
+ HOST_WIDE_INT val = tree_to_shwi (value);
+ if (!val && i + 1 < nelts)
+ continue;
+
+ if (idx < str.length())
+ return ctor;
+
+ /* Bail if the CTOR has a block of more than 256 embedded nuls
+ due to implicitly initialized elements. */
+ unsigned nchars = (idx - str.length ()) + 1;
+ if (nchars > 256)
+ return ctor;
+
+ if (nchars > 1)
+ {
+ str.reserve (idx);
+ str.quick_grow_cleared (idx);
+ }
+
+ if (idx >= maxelts)
+ return ctor;
+
+ str.safe_insert (idx, val);
+ }
+
+ /* Append a nul string termination. */
+ if (str.length () < maxelts)
+ str.safe_push (0);
+
+ /* Build a STRING_CST with the same type as the array. */
+ tree res = build_string (str.length (), str.begin ());
+ TREE_TYPE (res) = type;
+ return res;
}
#include "gt-c-family-c-common.h"
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index fcec95b..9e86876 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1038,6 +1038,7 @@ extern tree fold_offsetof (tree, tree = size_type_node,
tree_code ctx = ERROR_MARK);
extern int complete_array_type (tree *, tree, bool);
+extern void complete_flexible_array_elts (tree);
extern tree builtin_type_for_size (int, bool);
@@ -1327,16 +1328,18 @@ excess_precision_mode_join (enum flt_eval_method, enum flt_eval_method);
extern int c_flt_eval_method (bool ts18661_p);
extern void add_no_sanitize_value (tree node, unsigned int flags);
-extern void maybe_add_include_fixit (rich_location *, const char *);
+extern void maybe_add_include_fixit (rich_location *, const char *, bool);
extern void maybe_suggest_missing_token_insertion (rich_location *richloc,
enum cpp_ttype token_type,
location_t prev_token_loc);
+extern tree braced_list_to_string (tree, tree);
#if CHECKING_P
namespace selftest {
/* Declarations for specific families of tests within c-family,
by source file, in alphabetical order. */
extern void c_format_c_tests (void);
+ extern void c_indentation_c_tests (void);
extern void c_pretty_print_c_tests (void);
extern void c_spellcheck_cc_tests (void);
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index bdb5691..96a6b4d 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -31,7 +31,6 @@ along with GCC; see the file COPYING3. If not see
#include "output.h" /* For user_label_prefix. */
#include "debug.h" /* For dwarf2out_do_cfi_asm. */
#include "common/common-target.h"
-#include "cpp-id-data.h"
#include "cppbuiltin.h"
#ifndef TARGET_OS_CPP_BUILTINS
@@ -1361,7 +1360,12 @@ c_cpp_builtins (cpp_reader *pfile)
cpp_define (pfile, "__WCHAR_UNSIGNED__");
cpp_atomic_builtins (pfile);
-
+
+ /* Show support for __builtin_speculation_safe_value () if the target
+ has been updated to fully support it. */
+ if (targetm.have_speculation_safe_value (false))
+ cpp_define (pfile, "__HAVE_SPECULATION_SAFE_VALUE");
+
#ifdef DWARF2_UNWIND_INFO
if (dwarf2out_do_cfi_asm ())
cpp_define (pfile, "__GCC_HAVE_DWARF2_CFI_ASM");
@@ -1566,7 +1570,6 @@ builtin_define_with_int_value (const char *macro, HOST_WIDE_INT value)
struct GTY(()) lazy_hex_fp_value_struct
{
const char *hex_str;
- cpp_macro *macro;
machine_mode mode;
int digits;
const char *fp_suffix;
@@ -1579,36 +1582,35 @@ struct GTY(()) lazy_hex_fp_value_struct
#define LAZY_HEX_FP_VALUES_CNT (4 * (3 + NUM_FLOATN_NX_TYPES))
static GTY(()) struct lazy_hex_fp_value_struct
lazy_hex_fp_values[LAZY_HEX_FP_VALUES_CNT];
-static GTY(()) int lazy_hex_fp_value_count;
+static GTY(()) unsigned lazy_hex_fp_value_count;
-static bool
-lazy_hex_fp_value (cpp_reader *pfile ATTRIBUTE_UNUSED,
- cpp_hashnode *node)
+static void
+lazy_hex_fp_value (cpp_reader *, cpp_macro *macro, unsigned num)
{
REAL_VALUE_TYPE real;
char dec_str[64], buf1[256];
- unsigned int idx;
- if (node->value.builtin < BT_FIRST_USER
- || (int) node->value.builtin >= BT_FIRST_USER + lazy_hex_fp_value_count)
- return false;
- idx = node->value.builtin - BT_FIRST_USER;
- real_from_string (&real, lazy_hex_fp_values[idx].hex_str);
+ gcc_checking_assert (num < lazy_hex_fp_value_count);
+
+ real_from_string (&real, lazy_hex_fp_values[num].hex_str);
real_to_decimal_for_mode (dec_str, &real, sizeof (dec_str),
- lazy_hex_fp_values[idx].digits, 0,
- lazy_hex_fp_values[idx].mode);
-
- sprintf (buf1, "%s%s", dec_str, lazy_hex_fp_values[idx].fp_suffix);
- node->flags &= ~(NODE_BUILTIN | NODE_USED);
- node->value.macro = lazy_hex_fp_values[idx].macro;
- for (idx = 0; idx < node->value.macro->count; idx++)
- if (node->value.macro->exp.tokens[idx].type == CPP_NUMBER)
- break;
- gcc_assert (idx < node->value.macro->count);
- node->value.macro->exp.tokens[idx].val.str.len = strlen (buf1);
- node->value.macro->exp.tokens[idx].val.str.text
- = (const unsigned char *) ggc_strdup (buf1);
- return true;
+ lazy_hex_fp_values[num].digits, 0,
+ lazy_hex_fp_values[num].mode);
+
+ size_t len
+ = sprintf (buf1, "%s%s", dec_str, lazy_hex_fp_values[num].fp_suffix);
+ gcc_assert (len < sizeof (buf1));
+ for (unsigned idx = 0; idx < macro->count; idx++)
+ if (macro->exp.tokens[idx].type == CPP_NUMBER)
+ {
+ macro->exp.tokens[idx].val.str.len = len;
+ macro->exp.tokens[idx].val.str.text
+ = (const unsigned char *) ggc_strdup (buf1);
+ return;
+ }
+
+ /* We must have replaced a token. */
+ gcc_unreachable ();
}
/* Pass an object-like macro a hexadecimal floating-point value. */
@@ -1627,23 +1629,18 @@ builtin_define_with_hex_fp_value (const char *macro,
&& flag_dump_macros == 0
&& !cpp_get_options (parse_in)->traditional)
{
- struct cpp_hashnode *node;
if (lazy_hex_fp_value_count == 0)
- cpp_get_callbacks (parse_in)->user_builtin_macro = lazy_hex_fp_value;
+ cpp_get_callbacks (parse_in)->user_lazy_macro = lazy_hex_fp_value;
sprintf (buf2, fp_cast, "1.1");
sprintf (buf1, "%s=%s", macro, buf2);
cpp_define (parse_in, buf1);
- node = C_CPP_HASHNODE (get_identifier (macro));
+ struct cpp_hashnode *node = C_CPP_HASHNODE (get_identifier (macro));
lazy_hex_fp_values[lazy_hex_fp_value_count].hex_str
= ggc_strdup (hex_str);
lazy_hex_fp_values[lazy_hex_fp_value_count].mode = TYPE_MODE (type);
lazy_hex_fp_values[lazy_hex_fp_value_count].digits = digits;
lazy_hex_fp_values[lazy_hex_fp_value_count].fp_suffix = fp_suffix;
- lazy_hex_fp_values[lazy_hex_fp_value_count].macro = node->value.macro;
- node->flags |= NODE_BUILTIN;
- node->value.builtin
- = (enum cpp_builtin_type) (BT_FIRST_USER + lazy_hex_fp_value_count);
- lazy_hex_fp_value_count++;
+ cpp_define_lazily (parse_in, node, lazy_hex_fp_value_count++);
return;
}
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index a0192dd..a1133c7 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -32,8 +32,10 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic.h"
#include "substring-locations.h"
#include "selftest.h"
+#include "selftest-diagnostic.h"
#include "builtins.h"
#include "attribs.h"
+#include "gcc-rich-location.h"
/* Handle attributes associated with format checking. */
@@ -44,6 +46,7 @@ enum format_type { printf_format_type, asm_fprintf_format_type,
gcc_diag_format_type, gcc_tdiag_format_type,
gcc_cdiag_format_type,
gcc_cxxdiag_format_type, gcc_gfc_format_type,
+ gcc_dump_printf_format_type,
gcc_objc_string_format_type,
format_type_error = -1};
@@ -56,7 +59,7 @@ struct function_format_info
/* Initialized in init_dynamic_diag_info. */
static GTY(()) tree local_tree_type_node;
-static GTY(()) tree local_gcall_ptr_node;
+static GTY(()) tree local_gimple_ptr_node;
static GTY(()) tree locus;
static bool decode_format_attr (tree, function_format_info *, int);
@@ -97,8 +100,9 @@ format_warning_at_char (location_t fmt_string_loc, tree format_string_cst,
substring_loc fmt_loc (fmt_string_loc, string_type, char_idx, char_idx,
char_idx);
- bool warned = format_warning_va (fmt_loc, UNKNOWN_LOCATION, NULL, opt,
- gmsgid, &ap);
+ format_string_diagnostic_t diag (fmt_loc, NULL, UNKNOWN_LOCATION, NULL,
+ NULL);
+ bool warned = diag.emit_warning_va (opt, gmsgid, &ap);
va_end (ap);
return warned;
@@ -461,6 +465,7 @@ static const format_length_info gcc_diag_length_specs[] =
#define gcc_tdiag_length_specs gcc_diag_length_specs
#define gcc_cdiag_length_specs gcc_diag_length_specs
#define gcc_cxxdiag_length_specs gcc_diag_length_specs
+#define gcc_dump_printf_length_specs gcc_diag_length_specs
/* This differs from printf_length_specs only in that "Z" is not accepted. */
static const format_length_info scanf_length_specs[] =
@@ -550,6 +555,7 @@ static const format_flag_pair gcc_diag_flag_pairs[] =
#define gcc_cdiag_flag_pairs gcc_diag_flag_pairs
#define gcc_cxxdiag_flag_pairs gcc_diag_flag_pairs
#define gcc_gfc_flag_pairs gcc_diag_flag_pairs
+#define gcc_dump_printf_flag_pairs gcc_diag_flag_pairs
static const format_flag_spec gcc_diag_flag_specs[] =
{
@@ -565,6 +571,7 @@ static const format_flag_spec gcc_diag_flag_specs[] =
#define gcc_cdiag_flag_specs gcc_diag_flag_specs
#define gcc_cxxdiag_flag_specs gcc_diag_flag_specs
#define gcc_gfc_flag_specs gcc_diag_flag_specs
+#define gcc_dump_printf_flag_specs gcc_diag_flag_specs
static const format_flag_spec scanf_flag_specs[] =
{
@@ -679,127 +686,90 @@ static const format_char_info asm_fprintf_char_table[] =
{ NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
};
+/* GCC-specific format_char_info arrays. */
+
+/* The conversion specifiers implemented within pp_format, and thus supported
+ by all pretty_printer instances within GCC. */
+
+#define PP_FORMAT_CHAR_TABLE \
+ { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \
+ { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \
+ { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \
+ { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \
+ { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL }, \
+ { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, \
+ { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "//cR", NULL }, \
+ { "<", 0, STD_C89, NOARGUMENTS, "", "<", NULL }, \
+ { ">", 0, STD_C89, NOARGUMENTS, "", ">", NULL }, \
+ { "'" , 0, STD_C89, NOARGUMENTS, "", "", NULL }, \
+ { "R", 0, STD_C89, NOARGUMENTS, "", "\\", NULL }, \
+ { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, \
+ { "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_diag_char_table[0] }
+
static const format_char_info gcc_diag_char_table[] =
{
- /* C89 conversion specifiers. */
- { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL },
- { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL },
-
- /* Custom conversion specifiers. */
-
- /* G requires a "gcall*" argument at runtime. */
- { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
- /* K requires a "tree" argument at runtime. */
- { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
-
- { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "//cR", NULL },
- { "<", 0, STD_C89, NOARGUMENTS, "", "<", NULL },
- { ">", 0, STD_C89, NOARGUMENTS, "", ">", NULL },
- { "'" , 0, STD_C89, NOARGUMENTS, "", "", NULL },
- { "R", 0, STD_C89, NOARGUMENTS, "", "\\", NULL },
- { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL },
+ /* The conversion specifiers implemented within pp_format. */
+ PP_FORMAT_CHAR_TABLE,
+
{ NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
};
static const format_char_info gcc_tdiag_char_table[] =
{
- /* C89 conversion specifiers. */
- { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL },
- { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL },
+ /* The conversion specifiers implemented within pp_format. */
+ PP_FORMAT_CHAR_TABLE,
- /* Custom conversion specifiers. */
+ /* Custom conversion specifiers implemented by default_tree_printer. */
/* These will require a "tree" at runtime. */
{ "DFTV", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "'", NULL },
{ "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL },
{ "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
- /* G requires a "gcall*" argument at runtime. */
+ /* G requires a "gimple*" argument at runtime. */
{ "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
- { "v", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL },
-
- { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "/cR", NULL },
- { "<", 0, STD_C89, NOARGUMENTS, "", "<", NULL },
- { ">", 0, STD_C89, NOARGUMENTS, "", ">", NULL },
- { "'", 0, STD_C89, NOARGUMENTS, "", "", NULL },
- { "R", 0, STD_C89, NOARGUMENTS, "", "\\", NULL },
- { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL },
- { "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_tdiag_char_table[0] },
{ NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
};
static const format_char_info gcc_cdiag_char_table[] =
{
- /* C89 conversion specifiers. */
- { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL },
- { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL },
+ /* The conversion specifiers implemented within pp_format. */
+ PP_FORMAT_CHAR_TABLE,
- /* Custom conversion specifiers. */
+ /* Custom conversion specifiers implemented by c_tree_printer. */
/* These will require a "tree" at runtime. */
{ "DFTV", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "'", NULL },
{ "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL },
{ "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
- /* G requires a "gcall*" argument at runtime. */
+ /* G requires a "gimple*" argument at runtime. */
{ "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
{ "v", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL },
- { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "/cR", NULL },
- { "<", 0, STD_C89, NOARGUMENTS, "", "<", NULL },
- { ">", 0, STD_C89, NOARGUMENTS, "", ">", NULL },
- { "'", 0, STD_C89, NOARGUMENTS, "", "", NULL },
- { "R", 0, STD_C89, NOARGUMENTS, "", "\\", NULL },
- { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL },
- { "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_tdiag_char_table[0] },
{ NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
};
static const format_char_info gcc_cxxdiag_char_table[] =
{
- /* C89 conversion specifiers. */
- { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL },
- { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL },
+ /* The conversion specifiers implemented within pp_format. */
+ PP_FORMAT_CHAR_TABLE,
- /* Custom conversion specifiers. */
+ /* Custom conversion specifiers implemented by cp_printer. */
/* These will require a "tree" at runtime. */
{ "ADFHISTVX",1,STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "'", NULL },
{ "E", 1,STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "", NULL },
{ "K", 1, STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
- { "v", 0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL },
- /* G requires a "gcall*" argument at runtime. */
+ /* G requires a "gimple*" argument at runtime. */
{ "G", 1, STD_C89,{ T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
/* These accept either an 'int' or an 'enum tree_code' (which is handled as an 'int'.) */
{ "CLOPQ",0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "/cR", NULL },
- { "<", 0, STD_C89, NOARGUMENTS, "", "<", NULL },
- { ">", 0, STD_C89, NOARGUMENTS, "", ">", NULL },
- { "'", 0, STD_C89, NOARGUMENTS, "", "", NULL },
- { "R", 0, STD_C89, NOARGUMENTS, "", "\\", NULL },
- { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL },
- { "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_tdiag_char_table[0] },
{ NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
};
@@ -823,6 +793,22 @@ static const format_char_info gcc_gfc_char_table[] =
{ NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
};
+static const format_char_info gcc_dump_printf_char_table[] =
+{
+ /* The conversion specifiers implemented within pp_format. */
+ PP_FORMAT_CHAR_TABLE,
+
+ /* Custom conversion specifiers implemented by dump_pretty_printer. */
+
+ /* E and G require a "gimple *" argument at runtime. */
+ { "EG", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
+
+ /* T requires a "tree" at runtime. */
+ { "T", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
+
+ { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
+};
+
static const format_char_info scan_char_table[] =
{
/* C89 conversion specifiers. */
@@ -922,6 +908,13 @@ static const format_kind_info format_types_orig[] =
0, 0, 0, 0, 0, 0,
NULL, NULL
},
+ { "gcc_dump_printf", gcc_dump_printf_length_specs,
+ gcc_dump_printf_char_table, "q+#", NULL,
+ gcc_dump_printf_flag_specs, gcc_dump_printf_flag_pairs,
+ FMT_FLAG_ARG_CONVERT,
+ 0, 0, 'p', 0, 'L', 0,
+ NULL, &integer_type_node
+ },
{ "NSString", NULL, NULL, NULL, NULL,
NULL, NULL,
FMT_FLAG_ARG_CONVERT|FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL, 0, 0, 0, 0, 0, 0,
@@ -3547,6 +3540,82 @@ get_corrected_substring (const substring_loc &fmt_loc,
return result;
}
+/* Helper class for adding zero or more trailing '*' to types.
+
+ The format type and name exclude any '*' for pointers, so those
+ must be formatted manually. For all the types we currently have,
+ this is adequate, but formats taking pointers to functions or
+ arrays would require the full type to be built up in order to
+ print it with %T. */
+
+class indirection_suffix
+{
+ public:
+ indirection_suffix (int pointer_count) : m_pointer_count (pointer_count) {}
+
+ /* Determine the size of the buffer (including NUL-terminator). */
+
+ size_t get_buffer_size () const
+ {
+ return m_pointer_count + 2;
+ }
+
+ /* Write the '*' to DST and add a NUL-terminator. */
+
+ void fill_buffer (char *dst) const
+ {
+ if (m_pointer_count == 0)
+ dst[0] = 0;
+ else if (c_dialect_cxx ())
+ {
+ memset (dst, '*', m_pointer_count);
+ dst[m_pointer_count] = 0;
+ }
+ else
+ {
+ dst[0] = ' ';
+ memset (dst + 1, '*', m_pointer_count);
+ dst[m_pointer_count + 1] = 0;
+ }
+ }
+
+ private:
+ int m_pointer_count;
+};
+
+/* Subclass of range_label for labelling the range in the format string
+ with the type in question, adding trailing '*' for pointer_count. */
+
+class range_label_for_format_type_mismatch
+ : public range_label_for_type_mismatch
+{
+ public:
+ range_label_for_format_type_mismatch (tree labelled_type, tree other_type,
+ int pointer_count)
+ : range_label_for_type_mismatch (labelled_type, other_type),
+ m_pointer_count (pointer_count)
+ {
+ }
+
+ label_text get_text (unsigned range_idx) const FINAL OVERRIDE
+ {
+ label_text text = range_label_for_type_mismatch::get_text (range_idx);
+ if (text.m_buffer == NULL)
+ return text;
+
+ indirection_suffix suffix (m_pointer_count);
+ char *p = (char *) alloca (suffix.get_buffer_size ());
+ suffix.fill_buffer (p);
+
+ char *result = concat (text.m_buffer, p, NULL);
+ text.maybe_free ();
+ return label_text (result, true);
+ }
+
+ private:
+ int m_pointer_count;
+};
+
/* Give a warning about a format argument of different type from that expected.
The range of the diagnostic is taken from WHOLE_FMT_LOC; the caret location
is based on the location of the char at TYPE->offset_loc.
@@ -3595,7 +3664,6 @@ format_type_warning (const substring_loc &whole_fmt_loc,
int pointer_count = type->pointer_count;
int arg_num = type->arg_num;
- char *p;
/* If ARG_TYPE is a typedef with a misleading name (for example,
size_t but not the standard size_t expected by printf %zu), avoid
printing the typedef name. */
@@ -3607,25 +3675,10 @@ format_type_warning (const substring_loc &whole_fmt_loc,
&& !strcmp (wanted_type_name,
lang_hooks.decl_printable_name (TYPE_NAME (arg_type), 2)))
arg_type = TYPE_MAIN_VARIANT (arg_type);
- /* The format type and name exclude any '*' for pointers, so those
- must be formatted manually. For all the types we currently have,
- this is adequate, but formats taking pointers to functions or
- arrays would require the full type to be built up in order to
- print it with %T. */
- p = (char *) alloca (pointer_count + 2);
- if (pointer_count == 0)
- p[0] = 0;
- else if (c_dialect_cxx ())
- {
- memset (p, '*', pointer_count);
- p[pointer_count] = 0;
- }
- else
- {
- p[0] = ' ';
- memset (p + 1, '*', pointer_count);
- p[pointer_count + 1] = 0;
- }
+
+ indirection_suffix suffix (pointer_count);
+ char *p = (char *) alloca (suffix.get_buffer_size ());
+ suffix.fill_buffer (p);
/* WHOLE_FMT_LOC has the caret at the end of the range.
Set the caret to be at the offset from TYPE. Subtract one
@@ -3633,18 +3686,22 @@ format_type_warning (const substring_loc &whole_fmt_loc,
substring_loc fmt_loc (whole_fmt_loc);
fmt_loc.set_caret_index (type->offset_loc - 1);
+ range_label_for_format_type_mismatch fmt_label (wanted_type, arg_type,
+ pointer_count);
+ range_label_for_type_mismatch param_label (arg_type, wanted_type);
+
/* Get a string for use as a replacement fix-it hint for the range in
fmt_loc, or NULL. */
char *corrected_substring
= get_corrected_substring (fmt_loc, type, arg_type, fki,
offset_to_type_start, conversion_char);
-
+ format_string_diagnostic_t diag (fmt_loc, &fmt_label, param_loc, &param_label,
+ corrected_substring);
if (wanted_type_name)
{
if (arg_type)
- format_warning_at_substring
- (fmt_loc, param_loc,
- corrected_substring, OPT_Wformat_,
+ diag.emit_warning
+ (OPT_Wformat_,
"%s %<%s%.*s%> expects argument of type %<%s%s%>, "
"but argument %d has type %qT",
gettext (kind_descriptions[kind]),
@@ -3652,9 +3709,8 @@ format_type_warning (const substring_loc &whole_fmt_loc,
format_length, format_start,
wanted_type_name, p, arg_num, arg_type);
else
- format_warning_at_substring
- (fmt_loc, param_loc,
- corrected_substring, OPT_Wformat_,
+ diag.emit_warning
+ (OPT_Wformat_,
"%s %<%s%.*s%> expects a matching %<%s%s%> argument",
gettext (kind_descriptions[kind]),
(kind == CF_KIND_FORMAT ? "%" : ""),
@@ -3663,9 +3719,8 @@ format_type_warning (const substring_loc &whole_fmt_loc,
else
{
if (arg_type)
- format_warning_at_substring
- (fmt_loc, param_loc,
- corrected_substring, OPT_Wformat_,
+ diag.emit_warning
+ (OPT_Wformat_,
"%s %<%s%.*s%> expects argument of type %<%T%s%>, "
"but argument %d has type %qT",
gettext (kind_descriptions[kind]),
@@ -3673,9 +3728,8 @@ format_type_warning (const substring_loc &whole_fmt_loc,
format_length, format_start,
wanted_type, p, arg_num, arg_type);
else
- format_warning_at_substring
- (fmt_loc, param_loc,
- corrected_substring, OPT_Wformat_,
+ diag.emit_warning
+ (OPT_Wformat_,
"%s %<%s%.*s%> expects a matching %<%T%s%> argument",
gettext (kind_descriptions[kind]),
(kind == CF_KIND_FORMAT ? "%" : ""),
@@ -3875,27 +3929,27 @@ init_dynamic_diag_info (void)
local_tree_type_node = void_type_node;
}
- /* Similar to the above but for gcall*. */
- if (!local_gcall_ptr_node
- || local_gcall_ptr_node == void_type_node)
+ /* Similar to the above but for gimple*. */
+ if (!local_gimple_ptr_node
+ || local_gimple_ptr_node == void_type_node)
{
- if ((local_gcall_ptr_node = maybe_get_identifier ("gcall")))
+ if ((local_gimple_ptr_node = maybe_get_identifier ("gimple")))
{
- local_gcall_ptr_node
- = identifier_global_value (local_gcall_ptr_node);
- if (local_gcall_ptr_node)
+ local_gimple_ptr_node
+ = identifier_global_value (local_gimple_ptr_node);
+ if (local_gimple_ptr_node)
{
- if (TREE_CODE (local_gcall_ptr_node) != TYPE_DECL)
+ if (TREE_CODE (local_gimple_ptr_node) != TYPE_DECL)
{
- error ("%<gcall%> is not defined as a type");
- local_gcall_ptr_node = 0;
+ error ("%<gimple%> is not defined as a type");
+ local_gimple_ptr_node = 0;
}
else
- local_gcall_ptr_node = TREE_TYPE (local_gcall_ptr_node);
+ local_gimple_ptr_node = TREE_TYPE (local_gimple_ptr_node);
}
}
else
- local_gcall_ptr_node = void_type_node;
+ local_gimple_ptr_node = void_type_node;
}
static tree hwi;
@@ -3942,6 +3996,7 @@ init_dynamic_diag_info (void)
dynamic_format_types[gcc_tdiag_format_type].length_char_specs =
dynamic_format_types[gcc_cdiag_format_type].length_char_specs =
dynamic_format_types[gcc_cxxdiag_format_type].length_char_specs =
+ dynamic_format_types[gcc_dump_printf_format_type].length_char_specs =
diag_ls = (format_length_info *)
xmemdup (gcc_diag_length_specs,
sizeof (gcc_diag_length_specs),
@@ -3968,6 +4023,8 @@ init_dynamic_diag_info (void)
gcc_cdiag_char_table;
dynamic_format_types[gcc_cxxdiag_format_type].conversion_specs =
gcc_cxxdiag_char_table;
+ dynamic_format_types[gcc_dump_printf_format_type].conversion_specs =
+ gcc_dump_printf_char_table;
}
#ifdef TARGET_FORMAT_TYPES
@@ -4122,7 +4179,8 @@ handle_format_attribute (tree *node, tree ARG_UNUSED (name), tree args,
|| info.format_type == gcc_diag_format_type
|| info.format_type == gcc_tdiag_format_type
|| info.format_type == gcc_cdiag_format_type
- || info.format_type == gcc_cxxdiag_format_type)
+ || info.format_type == gcc_cxxdiag_format_type
+ || info.format_type == gcc_dump_printf_format_type)
{
/* Our first time through, we have to make sure that our
format_type data is allocated dynamically and is modifiable. */
@@ -4144,7 +4202,8 @@ handle_format_attribute (tree *node, tree ARG_UNUSED (name), tree args,
else if (info.format_type == gcc_diag_format_type
|| info.format_type == gcc_tdiag_format_type
|| info.format_type == gcc_cdiag_format_type
- || info.format_type == gcc_cxxdiag_format_type)
+ || info.format_type == gcc_cxxdiag_format_type
+ || info.format_type == gcc_dump_printf_format_type)
init_dynamic_diag_info ();
else
gcc_unreachable ();
@@ -4254,6 +4313,66 @@ test_get_format_for_type_scanf ()
#undef ASSERT_FORMAT_FOR_TYPE_STREQ
+/* Exercise the type-printing label code, to give some coverage
+ under "make selftest-valgrind" (in particular, to ensure that
+ the label-printing machinery doesn't leak). */
+
+static void
+test_type_mismatch_range_labels ()
+{
+ /* Create a tempfile and write some text to it.
+ ....................0000000001 11111111 12 22222222
+ ....................1234567890 12345678 90 12345678. */
+ const char *content = " printf (\"msg: %i\\n\", msg);\n";
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+ line_table_test ltt;
+
+ linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
+
+ location_t c17 = linemap_position_for_column (line_table, 17);
+ ASSERT_EQ (LOCATION_COLUMN (c17), 17);
+ location_t c18 = linemap_position_for_column (line_table, 18);
+ location_t c24 = linemap_position_for_column (line_table, 24);
+ location_t c26 = linemap_position_for_column (line_table, 26);
+
+ /* Don't attempt to run the tests if column data might be unavailable. */
+ if (c26 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ location_t fmt = make_location (c18, c17, c18);
+ ASSERT_EQ (LOCATION_COLUMN (fmt), 18);
+
+ location_t param = make_location (c24, c24, c26);
+ ASSERT_EQ (LOCATION_COLUMN (param), 24);
+
+ range_label_for_format_type_mismatch fmt_label (char_type_node,
+ integer_type_node, 1);
+ range_label_for_type_mismatch param_label (integer_type_node,
+ char_type_node);
+ gcc_rich_location richloc (fmt, &fmt_label);
+ richloc.add_range (param, SHOW_RANGE_WITHOUT_CARET, &param_label);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ if (c_dialect_cxx ())
+ /* "char*", without a space. */
+ ASSERT_STREQ ("\n"
+ " printf (\"msg: %i\\n\", msg);\n"
+ " ~^ ~~~\n"
+ " | |\n"
+ " char* int\n",
+ pp_formatted_text (dc.printer));
+ else
+ /* "char *", with a space. */
+ ASSERT_STREQ ("\n"
+ " printf (\"msg: %i\\n\", msg);\n"
+ " ~^ ~~~\n"
+ " | |\n"
+ " | int\n"
+ " char *\n",
+ pp_formatted_text (dc.printer));
+}
+
/* Run all of the selftests within this file. */
void
@@ -4262,6 +4381,7 @@ c_format_c_tests ()
test_get_modifier_for_format_len ();
test_get_format_for_type_printf ();
test_get_format_for_type_scanf ();
+ test_type_mismatch_range_labels ();
}
} // namespace selftest
diff --git a/gcc/c-family/c-format.h b/gcc/c-family/c-format.h
index f828e77..d984d10 100644
--- a/gcc/c-family/c-format.h
+++ b/gcc/c-family/c-format.h
@@ -298,7 +298,7 @@ struct format_kind_info
#define T_UC &unsigned_char_type_node
#define T99_UC { STD_C99, NULL, T_UC }
#define T_V &void_type_node
-#define T89_G { STD_C89, NULL, &local_gcall_ptr_node }
+#define T89_G { STD_C89, NULL, &local_gimple_ptr_node }
#define T89_T { STD_C89, NULL, &local_tree_type_node }
#define T89_V { STD_C89, NULL, T_V }
#define T_W &wchar_type_node
diff --git a/gcc/c-family/c-indentation.c b/gcc/c-family/c-indentation.c
index 44b1e1e..cff5aec 100644
--- a/gcc/c-family/c-indentation.c
+++ b/gcc/c-family/c-indentation.c
@@ -23,15 +23,15 @@ along with GCC; see the file COPYING3. If not see
#include "tm.h"
#include "c-common.h"
#include "c-indentation.h"
+#include "selftest.h"
extern cpp_options *cpp_opts;
/* Round up VIS_COLUMN to nearest tab stop. */
static unsigned int
-next_tab_stop (unsigned int vis_column)
+next_tab_stop (unsigned int vis_column, unsigned int tab_width)
{
- const unsigned int tab_width = cpp_opts->tabstop;
vis_column = ((vis_column + tab_width) / tab_width) * tab_width;
return vis_column;
}
@@ -43,12 +43,13 @@ next_tab_stop (unsigned int vis_column)
Returns true if a conversion was possible, writing the result to OUT,
otherwise returns false. If FIRST_NWS is not NULL, then write to it
the visual column corresponding to the first non-whitespace character
- on the line. */
+ on the line (up to or before EXPLOC). */
static bool
get_visual_column (expanded_location exploc, location_t loc,
unsigned int *out,
- unsigned int *first_nws)
+ unsigned int *first_nws,
+ unsigned int tab_width)
{
/* PR c++/68819: if the column number is zero, we presumably
had a location_t > LINE_MAP_MAX_LOCATION_WITH_COLS, and so
@@ -73,6 +74,8 @@ get_visual_column (expanded_location exploc, location_t loc,
char_span line = location_get_source_line (exploc.file, exploc.line);
if (!line)
return false;
+ if ((size_t)exploc.column > line.length ())
+ return false;
unsigned int vis_column = 0;
for (int i = 1; i < exploc.column; i++)
{
@@ -85,7 +88,7 @@ get_visual_column (expanded_location exploc, location_t loc,
}
if (ch == '\t')
- vis_column = next_tab_stop (vis_column);
+ vis_column = next_tab_stop (vis_column, tab_width);
else
vis_column++;
}
@@ -106,7 +109,8 @@ get_visual_column (expanded_location exploc, location_t loc,
static bool
get_first_nws_vis_column (const char *file, int line_num,
- unsigned int *first_nws)
+ unsigned int *first_nws,
+ unsigned int tab_width)
{
gcc_assert (first_nws);
@@ -125,7 +129,7 @@ get_first_nws_vis_column (const char *file, int line_num,
}
if (ch == '\t')
- vis_column = next_tab_stop (vis_column);
+ vis_column = next_tab_stop (vis_column, tab_width);
else
vis_column++;
}
@@ -178,7 +182,8 @@ static bool
detect_intervening_unindent (const char *file,
int body_line,
int next_stmt_line,
- unsigned int vis_column)
+ unsigned int vis_column,
+ unsigned int tab_width)
{
gcc_assert (file);
gcc_assert (next_stmt_line > body_line);
@@ -186,7 +191,7 @@ detect_intervening_unindent (const char *file,
for (int line = body_line + 1; line < next_stmt_line; line++)
{
unsigned int line_vis_column;
- if (get_first_nws_vis_column (file, line, &line_vis_column))
+ if (get_first_nws_vis_column (file, line, &line_vis_column, tab_width))
if (line_vis_column < vis_column)
return true;
}
@@ -289,6 +294,8 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
expanded_location next_stmt_exploc = expand_location (next_stmt_loc);
expanded_location guard_exploc = expand_location (guard_loc);
+ const unsigned int tab_width = cpp_opts->tabstop;
+
/* They must be in the same file. */
if (next_stmt_exploc.file != body_exploc.file)
return false;
@@ -334,7 +341,7 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
unsigned int guard_line_first_nws;
if (!get_visual_column (guard_exploc, guard_loc,
&guard_vis_column,
- &guard_line_first_nws))
+ &guard_line_first_nws, tab_width))
return false;
/* Heuristic: only warn if the guard is the first thing
on its line. */
@@ -394,15 +401,15 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
it's not clear that it's meaningful to look at indentation. */
if (!get_visual_column (next_stmt_exploc, next_stmt_loc,
&next_stmt_vis_column,
- &next_stmt_line_first_nws))
+ &next_stmt_line_first_nws, tab_width))
return false;
if (!get_visual_column (body_exploc, body_loc,
&body_vis_column,
- &body_line_first_nws))
+ &body_line_first_nws, tab_width))
return false;
if (!get_visual_column (guard_exploc, guard_loc,
&guard_vis_column,
- &guard_line_first_nws))
+ &guard_line_first_nws, tab_width))
return false;
/* If the line where the next stmt starts has non-whitespace
@@ -486,7 +493,7 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
int vis_column = MIN (next_stmt_vis_column, body_vis_column);
if (detect_intervening_unindent (body_exploc.file, body_exploc.line,
next_stmt_exploc.line,
- vis_column))
+ vis_column, tab_width))
return false;
/* Otherwise, they are visually aligned: issue a warning. */
@@ -602,6 +609,7 @@ warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
body_tinfo,
next_tinfo))
{
+ auto_diagnostic_group d;
if (warning_at (guard_tinfo.location, OPT_Wmisleading_indentation,
"this %qs clause does not guard...",
guard_tinfo_to_string (guard_tinfo.keyword)))
@@ -611,3 +619,160 @@ warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
guard_tinfo_to_string (guard_tinfo.keyword));
}
}
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Verify that next_tab_stop works as expected. */
+
+static void
+test_next_tab_stop ()
+{
+ const unsigned int tab_width = 8;
+
+ ASSERT_EQ (next_tab_stop (0, tab_width), 8);
+ ASSERT_EQ (next_tab_stop (1, tab_width), 8);
+ ASSERT_EQ (next_tab_stop (7, tab_width), 8);
+
+ ASSERT_EQ (next_tab_stop (8, tab_width), 16);
+ ASSERT_EQ (next_tab_stop (9, tab_width), 16);
+ ASSERT_EQ (next_tab_stop (15, tab_width), 16);
+
+ ASSERT_EQ (next_tab_stop (16, tab_width), 24);
+ ASSERT_EQ (next_tab_stop (17, tab_width), 24);
+ ASSERT_EQ (next_tab_stop (23, tab_width), 24);
+}
+
+/* Verify that the given call to get_visual_column succeeds, with
+ the given results. */
+
+static void
+assert_get_visual_column_succeeds (const location &loc,
+ const char *file, int line, int column,
+ const unsigned int tab_width,
+ unsigned int expected_visual_column,
+ unsigned int expected_first_nws)
+{
+ expanded_location exploc;
+ exploc.file = file;
+ exploc.line = line;
+ exploc.column = column;
+ exploc.data = NULL;
+ exploc.sysp = false;
+ unsigned int actual_visual_column;
+ unsigned int actual_first_nws;
+ bool result = get_visual_column (exploc, UNKNOWN_LOCATION,
+ &actual_visual_column,
+ &actual_first_nws, tab_width);
+ ASSERT_TRUE_AT (loc, result);
+ ASSERT_EQ_AT (loc, actual_visual_column, expected_visual_column);
+ ASSERT_EQ_AT (loc, actual_first_nws, expected_first_nws);
+}
+
+/* Verify that the given call to get_visual_column succeeds, with
+ the given results. */
+
+#define ASSERT_GET_VISUAL_COLUMN_SUCCEEDS(FILENAME, LINE, COLUMN, \
+ TAB_WIDTH, \
+ EXPECTED_VISUAL_COLUMN, \
+ EXPECTED_FIRST_NWS) \
+ SELFTEST_BEGIN_STMT \
+ assert_get_visual_column_succeeds (SELFTEST_LOCATION, \
+ FILENAME, LINE, COLUMN, \
+ TAB_WIDTH, \
+ EXPECTED_VISUAL_COLUMN, \
+ EXPECTED_FIRST_NWS); \
+ SELFTEST_END_STMT
+
+/* Verify that the given call to get_visual_column fails gracefully. */
+
+static void
+assert_get_visual_column_fails (const location &loc,
+ const char *file, int line, int column,
+ const unsigned int tab_width)
+{
+ expanded_location exploc;
+ exploc.file = file;
+ exploc.line = line;
+ exploc.column = column;
+ exploc.data = NULL;
+ exploc.sysp = false;
+ unsigned int actual_visual_column;
+ unsigned int actual_first_nws;
+ bool result = get_visual_column (exploc, UNKNOWN_LOCATION,
+ &actual_visual_column,
+ &actual_first_nws, tab_width);
+ ASSERT_FALSE_AT (loc, result);
+}
+
+/* Verify that the given call to get_visual_column fails gracefully. */
+
+#define ASSERT_GET_VISUAL_COLUMN_FAILS(FILENAME, LINE, COLUMN, \
+ TAB_WIDTH) \
+ SELFTEST_BEGIN_STMT \
+ assert_get_visual_column_fails (SELFTEST_LOCATION, \
+ FILENAME, LINE, COLUMN, \
+ TAB_WIDTH); \
+ SELFTEST_END_STMT
+
+/* Verify that get_visual_column works as expected. */
+
+static void
+test_get_visual_column ()
+{
+ /* Create a tempfile with a mixture of tabs and spaces.
+
+ Both lines have either a space or a tab, then " line N",
+ for 8 characters in total.
+
+ 1-based "columns" (w.r.t. to line 1):
+ .....................0000000001111.
+ .....................1234567890123. */
+ const char *content = (" line 1\n"
+ "\t line 2\n");
+ line_table_test ltt;
+ temp_source_file tmp (SELFTEST_LOCATION, ".txt", content);
+
+ const unsigned int tab_width = 8;
+ const char *file = tmp.get_filename ();
+
+ /* Line 1 (space-based indentation). */
+ {
+ const int line = 1;
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 1, tab_width, 0, 0);
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 2, tab_width, 1, 1);
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 3, tab_width, 2, 2);
+ /* first_nws should have stopped increasing. */
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 4, tab_width, 3, 2);
+ /* Verify the end-of-line boundary. */
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 8, tab_width, 7, 2);
+ ASSERT_GET_VISUAL_COLUMN_FAILS (file, line, 9, tab_width);
+ }
+
+ /* Line 2 (tab-based indentation). */
+ {
+ const int line = 2;
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 1, tab_width, 0, 0);
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 2, tab_width, 8, 8);
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 3, tab_width, 9, 9);
+ /* first_nws should have stopped increasing. */
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 4, tab_width, 10, 9);
+ /* Verify the end-of-line boundary. */
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 8, tab_width, 14, 9);
+ ASSERT_GET_VISUAL_COLUMN_FAILS (file, line, 9, tab_width);
+ }
+}
+
+/* Run all of the selftests within this file. */
+
+void
+c_indentation_c_tests ()
+{
+ test_next_tab_stop ();
+ test_get_visual_column ();
+}
+
+} // namespace selftest
+
+#endif /* CHECKING_P */
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index 074c2d2..ac58335c 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -199,7 +199,7 @@ fe_file_change (const line_map_ordinary *new_map)
we already did in compile_file. */
if (!MAIN_FILE_P (new_map))
{
- unsigned int included_at = LAST_SOURCE_LINE_LOCATION (new_map - 1);
+ location_t included_at = linemap_included_from (new_map);
int line = 0;
if (included_at > BUILTINS_LOCATION)
line = SOURCE_LINE (new_map - 1, included_at);
diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index cb69fb3..ec05771 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -931,6 +931,7 @@ c_common_post_options (const char **pfilename)
warn_abi_version = latest_abi_version;
if (flag_abi_version == latest_abi_version)
{
+ auto_diagnostic_group d;
if (warning (OPT_Wabi, "-Wabi won't warn about anything"))
{
inform (input_location, "-Wabi warns about differences "
diff --git a/gcc/c-family/c-ppoutput.c b/gcc/c-family/c-ppoutput.c
index 8c525caf..2e5a44e 100644
--- a/gcc/c-family/c-ppoutput.c
+++ b/gcc/c-family/c-ppoutput.c
@@ -532,13 +532,14 @@ static void
cb_used_define (cpp_reader *pfile, source_location line ATTRIBUTE_UNUSED,
cpp_hashnode *node)
{
- macro_queue *q;
- if (node->flags & NODE_BUILTIN)
- return;
- q = XNEW (macro_queue);
- q->macro = xstrdup ((const char *) cpp_macro_definition (pfile, node));
- q->next = define_queue;
- define_queue = q;
+ if (cpp_user_macro_p (node))
+ {
+ macro_queue *q;
+ q = XNEW (macro_queue);
+ q->macro = xstrdup ((const char *) cpp_macro_definition (pfile, node));
+ q->next = define_queue;
+ define_queue = q;
+ }
}
static void
@@ -663,11 +664,9 @@ pp_file_change (const line_map_ordinary *map)
/* Bring current file to correct line when entering a new file. */
if (map->reason == LC_ENTER)
{
- const line_map_ordinary *from = INCLUDED_FROM (line_table, map);
- maybe_print_line (LAST_SOURCE_LINE_LOCATION (from));
+ maybe_print_line (linemap_included_from (map));
+ flags = " 1";
}
- if (map->reason == LC_ENTER)
- flags = " 1";
else if (map->reason == LC_LEAVE)
flags = " 2";
print_line (map->start_location, flags);
@@ -690,7 +689,7 @@ cb_def_pragma (cpp_reader *pfile, source_location line)
static int
dump_macro (cpp_reader *pfile, cpp_hashnode *node, void *v ATTRIBUTE_UNUSED)
{
- if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
+ if (cpp_user_macro_p (node))
{
fputs ("#define ", print.outf);
fputs ((const char *) cpp_macro_definition (pfile, node),
diff --git a/gcc/c-family/c-spellcheck.cc b/gcc/c-family/c-spellcheck.cc
index c0975d3..85fd278 100644
--- a/gcc/c-family/c-spellcheck.cc
+++ b/gcc/c-family/c-spellcheck.cc
@@ -45,13 +45,13 @@ name_reserved_for_implementation_p (const char *str)
static bool
should_suggest_as_macro_p (cpp_hashnode *hashnode)
{
- if (hashnode->type != NT_MACRO)
+ if (!cpp_macro_p (hashnode))
return false;
- /* Don't suggest names reserved for the implementation, but do suggest the builtin
- macros such as __FILE__, __LINE__ etc. */
- if (name_reserved_for_implementation_p ((const char *)hashnode->ident.str)
- && !(hashnode->flags & NODE_BUILTIN))
+ /* Don't suggest names reserved for the implementation, but do
+ suggest the builtin macros such as __FILE__, __LINE__ etc. */
+ if (cpp_user_macro_p (hashnode)
+ && name_reserved_for_implementation_p ((const char *)hashnode->ident.str))
return false;
return true;
diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
index d34d667..a1a7f93 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -491,6 +491,7 @@ warn_logical_not_parentheses (location_t location, enum tree_code code,
&& integer_zerop (rhs))
return;
+ auto_diagnostic_group d;
if (warning_at (location, OPT_Wlogical_not_parentheses,
"logical not is only applied to the left hand side of "
"comparison")
@@ -701,7 +702,7 @@ sizeof_pointer_memaccess_warning (location_t *sizeof_arg_loc, tree callee,
location_t loc;
if (TREE_CODE (callee) != FUNCTION_DECL
- || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
+ || !fndecl_built_in_p (callee, BUILT_IN_NORMAL)
|| vec_safe_length (params) <= 1)
return;
@@ -2232,6 +2233,7 @@ warn_duplicated_cond_add_or_warn (location_t loc, tree cond, vec<tree> **chain)
FOR_EACH_VEC_ELT (**chain, ix, t)
if (operand_equal_p (cond, t, 0))
{
+ auto_diagnostic_group d;
if (warning_at (loc, OPT_Wduplicated_cond,
"duplicated %<if%> condition"))
inform (EXPR_LOCATION (t), "previously used here");
@@ -2427,7 +2429,7 @@ warn_for_restrict (unsigned param_pos, tree *argarray, unsigned nargs)
{
arg = argarray[pos - 1];
if (EXPR_HAS_LOCATION (arg))
- richloc.add_range (EXPR_LOCATION (arg), false);
+ richloc.add_range (EXPR_LOCATION (arg));
}
return warning_n (&richloc, OPT_Wrestrict, arg_positions.length (),
@@ -2601,6 +2603,7 @@ warn_for_multistatement_macros (location_t body_loc, location_t next_loc,
return;
}
+ auto_diagnostic_group d;
if (warning_at (body_loc, OPT_Wmultistatement_macros,
"macro expands to multiple statements"))
inform (guard_loc, "some parts of macro expansion are not guarded by "
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index d614838..43d1d27 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -271,6 +271,10 @@ Warn if a subobject has an abi_tag attribute that the complete object type does
Wpsabi
C ObjC C++ ObjC++ LTO Var(warn_psabi) Init(1) Warning Undocumented LangEnabledBy(C ObjC C++ ObjC++,Wabi)
+Wabsolute-value
+C ObjC Var(warn_absolute_value) Warning EnabledBy(Wextra)
+Warn on suspicious calls of standard functions computing absolute values.
+
Waddress
C ObjC C++ ObjC++ Var(warn_address) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
Warn about suspicious uses of memory addresses.
@@ -413,7 +417,7 @@ C ObjC C++ ObjC++ Var(warn_char_subscripts) Warning LangEnabledBy(C ObjC C++ Obj
Warn about subscripts whose type is \"char\".
Wchkp
-C ObjC C++ ObjC++ Var(warn_chkp) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) Deprecated
+C ObjC C++ ObjC++ Warning Deprecated
Deprecated in GCC 9. This switch has no effect.
Wclobbered
@@ -820,7 +824,7 @@ C ObjC Var(warn_missing_prototypes) Warning
Warn about global functions without prototypes.
Wmudflap
-C ObjC C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C ObjC C++ ObjC++ Deprecated
Wmultichar
C ObjC C++ ObjC++ CPP(warn_multichar) CppReason(CPP_W_MULTICHAR) Var(cpp_warn_multichar) Init(0) Warning
@@ -846,6 +850,10 @@ Wnon-template-friend
C++ ObjC++ Var(warn_nontemplate_friend) Init(1) Warning
Warn when non-templatized friend functions are declared within a template.
+Wclass-conversion
+C++ ObjC++ Var(warn_class_conversion) Init(1) Warning
+Warn when a conversion function will never be called due to the type it converts to.
+
Wclass-memaccess
C++ ObjC++ Var(warn_class_memaccess) Warning LangEnabledBy(C++ ObjC++, Wall)
Warn for unsafe raw memory writes to objects of class types.
@@ -937,6 +945,10 @@ Wpedantic
C ObjC C++ ObjC++ CPP(cpp_pedantic) CppReason(CPP_W_PEDANTIC) Warning
; Documented in common.opt
+Wpessimizing-move
+C++ ObjC++ Var(warn_pessimizing_move) Warning LangEnabledBy(C++ ObjC++, Wall)
+Warn about calling std::move on a local object in a return statement preventing copy elision.
+
Wpmf-conversions
C++ ObjC++ Var(warn_pmf2ptr) Init(1) Warning
Warn when converting the type of pointers to member functions.
@@ -981,6 +993,10 @@ Wredundant-decls
C ObjC C++ ObjC++ Var(warn_redundant_decls) Warning
Warn about multiple declarations of the same object.
+Wredundant-move
+C++ ObjC++ Var(warn_redundant_move) Warning LangEnabledBy(C++ ObjC++,Wextra)
+Warn about redundant calls to std::move.
+
Wregister
C++ ObjC++ Var(warn_register) Warning
Warn about uses of register storage specifier.
@@ -1238,14 +1254,14 @@ C++ ObjC++ Joined RejectNegative Var(aligned_new_threshold) UInteger Init(-1)
-faligned-new=<N> Use C++17 over-aligned type allocation for alignments greater than N.
fall-virtual
-C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C++ ObjC++ Deprecated
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)
+C++ ObjC++ Deprecated
No longer supported.
fasm
@@ -1268,78 +1284,78 @@ C ObjC C++ ObjC++
Where shorter, use canonicalized paths to systems headers.
fcheck-pointer-bounds
-C ObjC C++ ObjC++ LTO Report Var(flag_check_pointer_bounds) Deprecated
+C ObjC C++ ObjC++ LTO Deprecated
Deprecated in GCC 9. This switch has no effect.
fchkp-check-incomplete-type
-C ObjC C++ ObjC++ LTO Report Var(flag_chkp_incomplete_type) Init(1) Deprecated
+C ObjC C++ ObjC++ LTO Deprecated
Deprecated in GCC 9. This switch has no effect.
fchkp-zero-input-bounds-for-main
-C ObjC C++ ObjC++ LTO Report Var(flag_chkp_zero_input_bounds_for_main) Init(0) Deprecated
+C ObjC C++ ObjC++ LTO Deprecated
Deprecated in GCC 9. This switch has no effect.
fchkp-first-field-has-own-bounds
-C ObjC C++ ObjC++ LTO RejectNegative Report Var(flag_chkp_first_field_has_own_bounds) Deprecated
+C ObjC C++ ObjC++ LTO Deprecated RejectNegative
Deprecated in GCC 9. This switch has no effect.
fchkp-narrow-bounds
-C ObjC C++ ObjC++ LTO Report Var(flag_chkp_narrow_bounds) Init(1) Deprecated
+C ObjC C++ ObjC++ LTO Deprecated
Deprecated in GCC 9. This switch has no effect.
fchkp-narrow-to-innermost-array
-C ObjC C++ ObjC++ LTO RejectNegative Report Var(flag_chkp_narrow_to_innermost_arrray) Deprecated
+C ObjC C++ ObjC++ LTO Deprecated RejectNegative
Deprecated in GCC 9. This switch has no effect.
fchkp-flexible-struct-trailing-arrays
-C ObjC C++ ObjC++ LTO Report Var(flag_chkp_flexible_struct_trailing_arrays) Deprecated
+C ObjC C++ ObjC++ LTO Deprecated
Deprecated in GCC 9. This switch has no effect.
fchkp-optimize
-C ObjC C++ ObjC++ LTO Report Var(flag_chkp_optimize) Init(-1)
+C ObjC C++ ObjC++ LTO Deprecated
fchkp-use-fast-string-functions
-C ObjC C++ ObjC++ LTO Report Var(flag_chkp_use_fast_string_functions) Init(0) Deprecated
+C ObjC C++ ObjC++ LTO Deprecated
Deprecated in GCC 9. This switch has no effect.
fchkp-use-nochk-string-functions
-C ObjC C++ ObjC++ LTO Report Var(flag_chkp_use_nochk_string_functions) Init(0) Deprecated
+C ObjC C++ ObjC++ LTO Deprecated
Deprecated in GCC 9. This switch has no effect.
fchkp-use-static-bounds
-C ObjC C++ ObjC++ LTO Report Var(flag_chkp_use_static_bounds) Init(1) Deprecated
+C ObjC C++ ObjC++ LTO Deprecated
Deprecated in GCC 9. This switch has no effect.
fchkp-use-static-const-bounds
-C ObjC C++ ObjC++ LTO Report Var(flag_chkp_use_static_const_bounds) Init(-1) Deprecated
+C ObjC C++ ObjC++ LTO Deprecated
Deprecated in GCC 9. This switch has no effect.
fchkp-treat-zero-dynamic-size-as-infinite
-C ObjC C++ ObjC++ LTO Report Var(flag_chkp_zero_dynamic_size_as_infinite) Init(0) Deprecated
+C ObjC C++ ObjC++ LTO Deprecated
Deprecated in GCC 9. This switch has no effect.
fchkp-check-read
-C ObjC C++ ObjC++ LTO Report Var(flag_chkp_check_read) Init(1) Deprecated
+C ObjC C++ ObjC++ LTO Deprecated
Deprecated in GCC 9. This switch has no effect.
fchkp-check-write
-C ObjC C++ ObjC++ LTO Report Var(flag_chkp_check_write) Init(1) Deprecated
+C ObjC C++ ObjC++ LTO Deprecated
Deprecated in GCC 9. This switch has no effect.
fchkp-store-bounds
-C ObjC C++ ObjC++ LTO Report Var(flag_chkp_store_bounds) Init(1) Deprecated
+C ObjC C++ ObjC++ LTO Deprecated
Deprecated in GCC 9. This switch has no effect.
fchkp-instrument-calls
-C ObjC C++ ObjC++ LTO Report Var(flag_chkp_instrument_calls) Init(1) Deprecated
+C ObjC C++ ObjC++ LTO Deprecated
Deprecated in GCC 9. This switch has no effect.
fchkp-instrument-marked-only
-C ObjC C++ ObjC++ LTO Report Var(flag_chkp_instrument_marked_only) Init(0) Deprecated
+C ObjC C++ ObjC++ LTO Deprecated
Deprecated in GCC 9. This switch has no effect.
fchkp-use-wrappers
-C ObjC C++ ObjC++ LTO Report Var(flag_chkp_use_wrappers) Init(1) Deprecated
+C ObjC C++ ObjC++ LTO Deprecated
Deprecated in GCC 9. This switch has no effect.
static-libmpx
@@ -1350,8 +1366,8 @@ static-libmpxwrappers
Driver Deprecated
Deprecated in GCC 9. This switch has no effect.
-fcilkplus Undocumented
-C ObjC C++ ObjC++ LTO Report Var(flag_cilkplus) Init(0)
+fcilkplus
+C ObjC C++ ObjC++ LTO Undocumented Ignore
Deprecated in GCC 8. This switch has no effect.
fconcepts
@@ -1363,7 +1379,7 @@ C ObjC C++ ObjC++
Allow the arguments of the '?' operator to have different types.
fconserve-space
-C++ ObjC++ Var(flag_conserve_space)
+C++ ObjC++ Ignore
Does nothing. Preserved for backward compatibility.
fconstant-string-class=
@@ -1430,7 +1446,7 @@ C++ ObjC++ Var(flag_enforce_eh_specs) Init(1)
Generate code to check exception specifications.
fenum-int-equiv
-C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C++ ObjC++ Deprecated
fexec-charset=
C ObjC C++ ObjC++ Joined RejectNegative
@@ -1449,10 +1465,10 @@ C++ ObjC++ Var(flag_extern_tls_init) Init(-1)
Support dynamic initialization of thread-local variables in a different translation unit.
fexternal-templates
-C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C++ ObjC++ Deprecated
ffor-scope
-C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C++ ObjC++ Deprecated
ffreestanding
C ObjC C++ ObjC++
@@ -1471,20 +1487,20 @@ C ObjC Var(flag_gnu89_inline) Init(-1)
Use traditional GNU semantics for inline functions.
fguiding-decls
-C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C++ ObjC++ Deprecated
fhandle-exceptions
C++ ObjC++ Optimization Alias(fexceptions) Warn({-fhandle-exceptions has been renamed -fexceptions (and is now on by default)})
fhonor-std
-C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C++ ObjC++ Deprecated
fhosted
C ObjC
Assume normal C execution environment.
fhuge-objects
-C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C++ ObjC++ Deprecated
No longer supported.
fimplement-inlines
@@ -1504,14 +1520,14 @@ C++ ObjC++ Var(flag_new_inheriting_ctors) Init(1)
Implement C++17 inheriting constructor semantics.
ffriend-injection
-C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C++ ObjC++ Deprecated
fkeep-inline-dllexport
C C++ ObjC ObjC++ Var(flag_keep_inline_dllexport) Init(1) Report Condition(TARGET_DLLIMPORT_DECL_ATTRIBUTES)
Don't emit dllexported inline functions unless needed.
flabels-ok
-C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C++ ObjC++ Deprecated
flax-vector-conversions
C ObjC C++ ObjC++ Var(flag_lax_vector_conversions)
@@ -1522,19 +1538,19 @@ C ObjC C++ ObjC++ Var(flag_ms_extensions)
Don't warn about uses of Microsoft extensions.
fmudflap
-C ObjC C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C ObjC C++ ObjC++ Deprecated
fmudflapth
-C ObjC C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C ObjC C++ ObjC++ Deprecated
fmudflapir
-C ObjC C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C ObjC C++ ObjC++ Deprecated
fname-mangling-version-
-C++ ObjC++ Joined Ignore Warn(switch %qs is no longer supported)
+C++ ObjC++ Joined Deprecated
fnew-abi
-C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C++ ObjC++ Deprecated
fnew-ttp-matching
C++ ObjC++ Var(flag_new_ttp)
@@ -1575,7 +1591,7 @@ fnonansi-builtins
C++ ObjC++ Var(flag_no_nonansi_builtin, 0)
fnonnull-objects
-C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C++ ObjC++ Deprecated
fnothrow-opt
C++ ObjC++ Optimization Var(flag_nothrow_opt)
@@ -1710,7 +1726,7 @@ C++ ObjC++ Var(flag_sized_deallocation) Init(-1)
Enable C++14 sized deallocation support.
fsquangle
-C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C++ ObjC++ Deprecated
fsso-struct=
C ObjC Joined RejectNegative Enum(sso_struct) Var(default_sso) Init(SSO_NATIVE)
@@ -1737,7 +1753,7 @@ C++ ObjC++ Optimization Var(flag_strict_enums)
Assume that values of enumeration type are always within the minimum range of that type.
fstrict-prototype
-C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C++ ObjC++ Deprecated
fstrong-eval-order
C++ ObjC++ Common Alias(fstrong-eval-order=, all, none)
@@ -1777,7 +1793,7 @@ C++ ObjC++ Joined RejectNegative UInteger
-ftemplate-depth=<number> Specify maximum template instantiation depth.
fthis-is-variable
-C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C++ ObjC++ Deprecated
fthreadsafe-statics
C++ ObjC++ Optimization Var(flag_threadsafe_statics) Init(1)
@@ -1808,11 +1824,11 @@ C++ ObjC++ Var(flag_visibility_ms_compat)
Changes visibility to match Microsoft Visual Studio by default.
fvtable-gc
-C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C++ ObjC++ Deprecated
No longer supported.
fvtable-thunks
-C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C++ ObjC++ Deprecated
No longer supported.
fweak
@@ -1828,7 +1844,7 @@ C ObjC C++ ObjC++ Var(flag_working_directory) Init(-1)
Generate a #line directive pointing at the current working directory.
fxref
-C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+C++ ObjC++ Deprecated
No longer supported.
fzero-link
diff --git a/gcc/c-family/known-headers.cc b/gcc/c-family/known-headers.cc
index 5524d21..b0763cf 100644
--- a/gcc/c-family/known-headers.cc
+++ b/gcc/c-family/known-headers.cc
@@ -192,7 +192,7 @@ suggest_missing_header::~suggest_missing_header ()
return;
gcc_rich_location richloc (get_location ());
- maybe_add_include_fixit (&richloc, m_header_hint);
+ maybe_add_include_fixit (&richloc, m_header_hint, true);
inform (&richloc,
"%qs is defined in header %qs;"
" did you forget to %<#include %s%>?",
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 424b6a1..6fd76cf 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,128 @@
+2018-09-17 David Malcolm <dmalcolm@redhat.com>
+
+ * c-objc-common.c (range_label_for_type_mismatch::get_text):
+ Update for new param.
+ * c-typeck.c (maybe_range_label_for_tree_type_mismatch::get_text):
+ Likewise.
+
+2018-09-17 Martin Jambor <mjambor@suse.cz>
+
+ PR c/63886
+ * c-parser.c: (warn_for_abs): New function.
+ (c_parser_postfix_expression_after_primary): Call it.
+
+2018-09-13 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * c-typeck.c (digest_init): Shorten overlength strings.
+
+2018-09-06 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * c-decl.c (finish_decl): Call complete_flexible_array_elts.
+
+2018-09-02 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * c-decl.c (finish_decl): Call braced_list_to_string here ...
+ * c-parser.c (c_parser_declaration_or_fndef): ... instead of here.
+
+2018-08-30 Alexander Monakov <amonakov@ispras.ru>
+
+ * gimple-parser.c (c_parser_gimple_binary_expression): Accept infix
+ "__MULT_HIGHPART" for MULT_HIGHPART_EXPR.
+
+2018-08-27 David Malcolm <dmalcolm@redhat.com>
+
+ PR 87091
+ * c-decl.c (implicitly_declare): Update call to
+ maybe_add_include_fixit to suggest overriding the location, as it
+ is for a note.
+ * c-objc-common.c (c_tree_printer): Update for conversion of
+ show_caret_p to a tri-state.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ * c-decl.c (locate_old_decl): Use new function
+ fndecl_built_in_p and remove check for FUNCTION_DECL if
+ possible.
+ (diagnose_mismatched_decls): Likewise.
+ (merge_decls): Likewise.
+ (warn_if_shadowing): Likewise.
+ (pushdecl): Likewise.
+ (implicitly_declare): Likewise.
+ * c-parser.c (c_parser_postfix_expression_after_primary): Likewise.
+ * c-tree.h (C_DECL_ISNT_PROTOTYPE): Likewise.
+ * c-typeck.c (build_function_call_vec): Likewise.
+ (convert_arguments): Likewise.
+
+2018-08-20 David Malcolm <dmalcolm@redhat.com>
+
+ PR other/84889
+ * c-decl.c (pushtag): Add auto_diagnostic_group instance.
+ (diagnose_mismatched_decls): Likewise, in various places.
+ (warn_if_shadowing): Likewise.
+ (implicit_decl_warning): Likewise.
+ (implicitly_declare): Likewise.
+ (undeclared_variable): Likewise.
+ (declare_label): Likewise.
+ (grokdeclarator): Likewise.
+ (start_function): Likewise.
+ * c-parser.c (c_parser_declaration_or_fndef): Likewise.
+ (c_parser_parameter_declaration): Likewise.
+ (c_parser_binary_expression): Likewise.
+ * c-typeck.c (c_expr_sizeof_expr): Likewise.
+ (parser_build_binary_op): Likewise.
+ (build_unary_op): Likewise.
+ (error_init): Likewise.
+ (pedwarn_init): Likewise.
+ (warning_init): Likewise.
+ (convert_for_assignment): Likewise.
+
+2018-08-15 David Malcolm <dmalcolm@redhat.com>
+
+ * c-objc-common.c: Include "gcc-rich-location.h".
+ (c_tree_printer): Move implemenation of '%T' to...
+ (print_type): ...this new function.
+ (range_label_for_type_mismatch::get_text): New function.
+ * c-typeck.c (convert_for_assignment): Add type labels to the rhs
+ range for the various ic_argpass cases.
+ (class maybe_range_label_for_tree_type_mismatch): New class.
+ (build_binary_op): Use it when calling binary_op_error.
+
+2018-08-15 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ * c-decl.c (start_decl): Do not warn if variables is named as main
+ and is a local variable.
+
+2018-08-15 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c/19315
+ * c-decl.c (finish_decl): Don't add the 'extern' storage class to
+ objects of unknown size.
+
+2018-08-13 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/71625
+ * c-parser.c (c_parser_declaration_or_fndef): Call
+ braced_list_to_string.
+
+2018-08-03 Bogdan Harjoc <harjoc@gmail.com>
+
+ PR c/86690
+ * c-typeck.c (lookup_field): Do not use TYPE_LANG_SPECIFIC after
+ errors.
+
+2018-08-01 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/86650
+ * c-objc-common.c (c_tree_printer): Move usage of EXPR_LOCATION (t)
+ and TREE_BLOCK (t) from within percent_K_format to this callsite.
+
+2018-08-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/85704
+ * c-typeck.c (init_field_decl_cmp): New function.
+ (output_pending_init_elements): Use it for field comparisons
+ instead of pure bit_position comparisons.
+
2018-07-12 Jakub Jelinek <jakub@redhat.com>
* c-decl.c (c_decl_attributes): Don't diagnose vars without mappable
@@ -211,7 +336,7 @@
DEBUG_BEGIN_STMTs.
2017-12-22 Mike Stump <mikestump@comcast.net>
- Eric Botcazou <ebotcazou@adacore.com>
+ Eric Botcazou <ebotcazou@adacore.com>
* c-parser.c (c_parser_while_statement): Add unroll parameter and
build ANNOTATE_EXPR if present. Add 3rd operand to ANNOTATE_EXPR.
@@ -328,7 +453,7 @@
c_switch_covers_all_cases_p returns true.
2017-11-28 Julia Koval <julia.koval@intel.com>
- Sebastian Peryt <sebastian.peryt@intel.com>
+ Sebastian Peryt <sebastian.peryt@intel.com>
* Make-lang.in (c/c-array-notation.o): Remove.
* c-array-notation.c: Delete.
@@ -1045,7 +1170,7 @@
2017-05-01 Xi Ruoyao <ryxi@stu.xidian.edu.cn>
- PR c++/80038
+ PR c++/80038
* c-gimplify.c (c_gimplify_expr): Remove calls to
cilk_gimplifY_call_params_in_spawned_fn.
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index ed1dd28..fdcfbde 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -1571,6 +1571,7 @@ pushtag (location_t loc, tree name, tree type)
&& (TYPE_MAIN_VARIANT (TREE_TYPE (b->decl))
!= TYPE_MAIN_VARIANT (type)))
{
+ auto_diagnostic_group d;
if (warning_at (loc, OPT_Wc___compat,
("using %qD as both a typedef and a tag is "
"invalid in C++"), b->decl)
@@ -1799,7 +1800,7 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype)
static void
locate_old_decl (tree decl)
{
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl)
+ if (TREE_CODE (decl) == FUNCTION_DECL && fndecl_built_in_p (decl)
&& !C_DECL_DECLARED_BUILTIN (decl))
;
else if (DECL_INITIAL (decl))
@@ -1823,8 +1824,6 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
tree *newtypep, tree *oldtypep)
{
tree newtype, oldtype;
- bool pedwarned = false;
- bool warned = false;
bool retval = true;
#define DECL_EXTERN_INLINE(DECL) (DECL_DECLARED_INLINE_P (DECL) \
@@ -1844,9 +1843,10 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{
if (!(TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_BUILT_IN (olddecl)
+ && fndecl_built_in_p (olddecl)
&& !C_DECL_DECLARED_BUILTIN (olddecl)))
{
+ auto_diagnostic_group d;
error ("%q+D redeclared as different kind of symbol", newdecl);
locate_old_decl (olddecl);
}
@@ -1864,15 +1864,20 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
given scope. */
if (TREE_CODE (olddecl) == CONST_DECL)
{
+ auto_diagnostic_group d;
error ("redeclaration of enumerator %q+D", newdecl);
locate_old_decl (olddecl);
return false;
}
+ bool pedwarned = false;
+ bool warned = false;
+ auto_diagnostic_group d;
+
if (!comptypes (oldtype, newtype))
{
if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_BUILT_IN (olddecl) && !C_DECL_DECLARED_BUILTIN (olddecl))
+ && fndecl_built_in_p (olddecl) && !C_DECL_DECLARED_BUILTIN (olddecl))
{
/* Accept harmless mismatch in function types.
This is for the ffs and fprintf builtins. */
@@ -2020,7 +2025,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
define the built-in with an old-style definition (so we
can't validate the argument list) the built-in definition is
overridden, but optionally warn this was a bad choice of name. */
- if (DECL_BUILT_IN (olddecl)
+ if (fndecl_built_in_p (olddecl)
&& !C_DECL_DECLARED_BUILTIN (olddecl)
&& (!TREE_PUBLIC (newdecl)
|| (DECL_INITIAL (newdecl)
@@ -2052,6 +2057,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
)
&& same_translation_unit_p (newdecl, olddecl))
{
+ auto_diagnostic_group d;
error ("redefinition of %q+D", newdecl);
locate_old_decl (olddecl);
return false;
@@ -2062,11 +2068,14 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
the argument types must be checked specially. */
else if (DECL_INITIAL (olddecl)
&& !prototype_p (oldtype) && prototype_p (newtype)
- && TYPE_ACTUAL_ARG_TYPES (oldtype)
- && !validate_proto_after_old_defn (newdecl, newtype, oldtype))
+ && TYPE_ACTUAL_ARG_TYPES (oldtype))
{
- locate_old_decl (olddecl);
- return false;
+ auto_diagnostic_group d;
+ if (!validate_proto_after_old_defn (newdecl, newtype, oldtype))
+ {
+ locate_old_decl (olddecl);
+ return false;
+ }
}
/* A non-static declaration (even an "extern") followed by a
static declaration is undefined behavior per C99 6.2.2p3-5,7.
@@ -2087,6 +2096,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
if (!DECL_IS_BUILTIN (olddecl)
&& !DECL_EXTERN_INLINE (olddecl))
{
+ auto_diagnostic_group d;
error ("static declaration of %q+D follows "
"non-static declaration", newdecl);
locate_old_decl (olddecl);
@@ -2097,6 +2107,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
{
if (DECL_CONTEXT (olddecl))
{
+ auto_diagnostic_group d;
error ("non-static declaration of %q+D follows "
"static declaration", newdecl);
locate_old_decl (olddecl);
@@ -2121,6 +2132,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
DECL_ATTRIBUTES (olddecl)) != NULL;
if (newa != olda)
{
+ auto_diagnostic_group d;
error_at (input_location, "%<gnu_inline%> attribute present on %q+D",
newa ? newdecl : olddecl);
error_at (DECL_SOURCE_LOCATION (newa ? olddecl : newdecl),
@@ -2141,6 +2153,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
}
else if (DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl))
{
+ auto_diagnostic_group d;
if (DECL_THREAD_LOCAL_P (newdecl))
error ("thread-local declaration of %q+D follows "
"non-thread-local declaration", newdecl);
@@ -2155,6 +2168,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
/* Multiple initialized definitions are not allowed (6.9p3,5). */
if (DECL_INITIAL (newdecl) && DECL_INITIAL (olddecl))
{
+ auto_diagnostic_group d;
error ("redefinition of %q+D", newdecl);
locate_old_decl (olddecl);
return false;
@@ -2175,6 +2189,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
{
if (!DECL_FILE_SCOPE_P (olddecl))
{
+ auto_diagnostic_group d;
error ("extern declaration of %q+D follows "
"declaration with no linkage", newdecl);
locate_old_decl (olddecl);
@@ -2189,6 +2204,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
}
else
{
+ auto_diagnostic_group d;
if (TREE_PUBLIC (newdecl))
error ("non-static declaration of %q+D follows "
"static declaration", newdecl);
@@ -2211,12 +2227,14 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
}
else if (DECL_EXTERNAL (olddecl))
{
+ auto_diagnostic_group d;
error ("declaration of %q+D with no linkage follows "
"extern declaration", newdecl);
locate_old_decl (olddecl);
}
else
{
+ auto_diagnostic_group d;
error ("redeclaration of %q+D with no linkage", newdecl);
locate_old_decl (olddecl);
}
@@ -2263,6 +2281,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
if (TREE_CODE (newdecl) == PARM_DECL
&& (!TREE_ASM_WRITTEN (olddecl) || TREE_ASM_WRITTEN (newdecl)))
{
+ auto_diagnostic_group d;
error ("redefinition of parameter %q+D", newdecl);
locate_old_decl (olddecl);
return false;
@@ -2278,8 +2297,8 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
&& DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl))
/* Don't warn about redundant redeclarations of builtins. */
&& !(TREE_CODE (newdecl) == FUNCTION_DECL
- && !DECL_BUILT_IN (newdecl)
- && DECL_BUILT_IN (olddecl)
+ && !fndecl_built_in_p (newdecl)
+ && fndecl_built_in_p (olddecl)
&& !C_DECL_DECLARED_BUILTIN (olddecl))
/* Don't warn about an extern followed by a definition. */
&& !(DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl))
@@ -2557,7 +2576,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
|| DECL_DISREGARD_INLINE_LIMITS (olddecl));
}
- if (DECL_BUILT_IN (olddecl))
+ if (fndecl_built_in_p (olddecl))
{
/* If redeclaring a builtin function, it stays built in.
But it gets tagged as having been declared. */
@@ -2778,7 +2797,6 @@ warn_if_shadowing (tree new_decl)
DECL_SOURCE_LOCATION (b->decl))))
{
tree old_decl = b->decl;
- bool warned = false;
if (old_decl == error_mark_node)
{
@@ -2786,7 +2804,10 @@ warn_if_shadowing (tree new_decl)
"non-variable", new_decl);
break;
}
- else if (TREE_CODE (old_decl) == PARM_DECL)
+
+ bool warned = false;
+ auto_diagnostic_group d;
+ if (TREE_CODE (old_decl) == PARM_DECL)
{
enum opt_code warning_code;
@@ -2819,7 +2840,7 @@ warn_if_shadowing (tree new_decl)
new_decl);
}
else if (TREE_CODE (old_decl) == FUNCTION_DECL
- && DECL_BUILT_IN (old_decl))
+ && fndecl_built_in_p (old_decl))
{
warning (OPT_Wshadow, "declaration of %q+D shadows "
"a built-in function", new_decl);
@@ -2932,7 +2953,7 @@ pushdecl (tree x)
thistype = TREE_TYPE (b_use->decl);
b_use->u.type = TREE_TYPE (b_use->decl);
if (TREE_CODE (b_use->decl) == FUNCTION_DECL
- && DECL_BUILT_IN (b_use->decl))
+ && fndecl_built_in_p (b_use->decl))
thistype
= build_type_attribute_variant (thistype,
TYPE_ATTRIBUTES
@@ -3036,7 +3057,8 @@ pushdecl (tree x)
else
thistype = type;
b->u.type = TREE_TYPE (b->decl);
- if (TREE_CODE (b->decl) == FUNCTION_DECL && DECL_BUILT_IN (b->decl))
+ if (TREE_CODE (b->decl) == FUNCTION_DECL
+ && fndecl_built_in_p (b->decl))
thistype
= build_type_attribute_variant (thistype,
TYPE_ATTRIBUTES (b->u.type));
@@ -3123,6 +3145,7 @@ implicit_decl_warning (location_t loc, tree id, tree olddecl)
return;
bool warned;
+ auto_diagnostic_group d;
name_hint hint;
if (!olddecl)
hint = lookup_name_fuzzy (id, FUZZY_LOOKUP_FUNCTION_NAME, loc);
@@ -3386,7 +3409,7 @@ implicitly_declare (location_t loc, tree functionid)
in the external scope because they're pushed before the file
scope gets created. Catch this here and rebind them into the
file scope. */
- if (!DECL_BUILT_IN (decl) && DECL_IS_BUILTIN (decl))
+ if (!fndecl_built_in_p (decl) && DECL_IS_BUILTIN (decl))
{
bind (functionid, decl, file_scope,
/*invisible=*/false, /*nested=*/true,
@@ -3407,7 +3430,7 @@ implicitly_declare (location_t loc, tree functionid)
implicit_decl_warning (loc, functionid, decl);
C_DECL_IMPLICIT (decl) = 1;
}
- if (DECL_BUILT_IN (decl))
+ if (fndecl_built_in_p (decl))
{
newtype = build_type_attribute_variant (newtype,
TYPE_ATTRIBUTES
@@ -3423,7 +3446,7 @@ implicitly_declare (location_t loc, tree functionid)
if (header != NULL && warned)
{
rich_location richloc (line_table, loc);
- maybe_add_include_fixit (&richloc, header);
+ maybe_add_include_fixit (&richloc, header, true);
inform (&richloc,
"include %qs or provide a declaration of %qD",
header, decl);
@@ -3435,6 +3458,7 @@ implicitly_declare (location_t loc, tree functionid)
{
if (!comptypes (newtype, TREE_TYPE (decl)))
{
+ auto_diagnostic_group d;
error_at (loc, "incompatible implicit declaration of "
"function %qD", decl);
locate_old_decl (decl);
@@ -3487,6 +3511,7 @@ undeclared_variable (location_t loc, tree id)
static bool already = false;
struct c_scope *scope;
+ auto_diagnostic_group d;
if (current_function_decl == NULL_TREE)
{
name_hint guessed_id = lookup_name_fuzzy (id, FUZZY_LOOKUP_NAME, loc);
@@ -3686,6 +3711,7 @@ declare_label (tree name)
at this scope */
if (b && B_IN_CURRENT_SCOPE (b))
{
+ auto_diagnostic_group d;
error ("duplicate label declaration %qE", name);
locate_old_decl (b->decl);
@@ -3784,6 +3810,7 @@ define_label (location_t location, tree name)
|| (DECL_CONTEXT (label) != current_function_decl
&& C_DECLARED_LABEL_FLAG (label))))
{
+ auto_diagnostic_group d;
error_at (location, "duplicate label %qD", label);
locate_old_decl (label);
return NULL_TREE;
@@ -4700,7 +4727,8 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
if (expr)
add_stmt (fold_convert (void_type_node, expr));
- if (TREE_CODE (decl) != FUNCTION_DECL && MAIN_NAME_P (DECL_NAME (decl)))
+ if (TREE_CODE (decl) != FUNCTION_DECL && MAIN_NAME_P (DECL_NAME (decl))
+ && TREE_PUBLIC (decl))
warning (OPT_Wmain, "%q+D is usually a function", decl);
if (initialized)
@@ -4969,14 +4997,6 @@ finish_decl (tree decl, location_t init_loc, tree init,
case 2:
if (do_default)
error ("array size missing in %q+D", decl);
- /* If a `static' var's size isn't known,
- make it extern as well as static, so it does not get
- allocated.
- If it is not `static', then do not mark extern;
- finish_incomplete_decl will give it a default size
- and it will get allocated. */
- else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
- DECL_EXTERNAL (decl) = 1;
break;
case 3:
@@ -5011,11 +5031,19 @@ finish_decl (tree decl, location_t init_loc, tree init,
relayout_decl (decl);
}
+ if (TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_STRING_FLAG (TREE_TYPE (type))
+ && DECL_INITIAL (decl)
+ && TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR)
+ DECL_INITIAL (decl) = braced_list_to_string (type, DECL_INITIAL (decl));
+
if (VAR_P (decl))
{
if (init && TREE_CODE (init) == CONSTRUCTOR)
add_flexible_array_elts_to_size (decl, init);
+ complete_flexible_array_elts (DECL_INITIAL (decl));
+
if (DECL_SIZE (decl) == NULL_TREE && TREE_TYPE (decl) != error_mark_node
&& COMPLETE_TYPE_P (TREE_TYPE (decl)))
layout_decl (decl, 0);
@@ -6727,6 +6755,7 @@ grokdeclarator (const struct c_declarator *declarator,
|| (current_scope == file_scope && B_IN_EXTERNAL_SCOPE (b)))
&& TYPE_MAIN_VARIANT (b->decl) != TYPE_MAIN_VARIANT (type))
{
+ auto_diagnostic_group d;
if (warning_at (declarator->id_loc, OPT_Wc___compat,
("using %qD as both a typedef and a tag is "
"invalid in C++"), decl)
@@ -8801,6 +8830,7 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
{
if (stdarg_p (TREE_TYPE (old_decl)))
{
+ auto_diagnostic_group d;
warning_at (loc, 0, "%q+D defined as variadic function "
"without prototype", decl1);
locate_old_decl (old_decl);
diff --git a/gcc/c/c-objc-common.c b/gcc/c/c-objc-common.c
index a841bc1..fee5268 100644
--- a/gcc/c/c-objc-common.c
+++ b/gcc/c/c-objc-common.c
@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-pretty-print.h"
#include "langhooks.h"
#include "c-objc-common.h"
+#include "gcc-rich-location.h"
static bool c_tree_printer (pretty_printer *, text_info *, const char *,
int, bool, bool, bool, bool *, const char **);
@@ -61,13 +62,67 @@ c_objc_common_init (void)
return c_common_init ();
}
+/* Print T to CPP. */
+
+static void
+print_type (c_pretty_printer *cpp, tree t, bool *quoted)
+{
+ gcc_assert (TYPE_P (t));
+ struct obstack *ob = pp_buffer (cpp)->obstack;
+ char *p = (char *) obstack_base (ob);
+ /* Remember the end of the initial dump. */
+ int len = obstack_object_size (ob);
+
+ tree name = TYPE_NAME (t);
+ if (name && TREE_CODE (name) == TYPE_DECL && DECL_NAME (name))
+ pp_identifier (cpp, lang_hooks.decl_printable_name (name, 2));
+ else
+ cpp->type_id (t);
+
+ /* If we're printing a type that involves typedefs, also print the
+ stripped version. But sometimes the stripped version looks
+ exactly the same, so we don't want it after all. To avoid
+ printing it in that case, we play ugly obstack games. */
+ if (TYPE_CANONICAL (t) && t != TYPE_CANONICAL (t))
+ {
+ c_pretty_printer cpp2;
+ /* Print the stripped version into a temporary printer. */
+ cpp2.type_id (TYPE_CANONICAL (t));
+ struct obstack *ob2 = cpp2.buffer->obstack;
+ /* Get the stripped version from the temporary printer. */
+ const char *aka = (char *) obstack_base (ob2);
+ int aka_len = obstack_object_size (ob2);
+ int type1_len = obstack_object_size (ob) - len;
+
+ /* If they are identical, bail out. */
+ if (aka_len == type1_len && memcmp (p + len, aka, aka_len) == 0)
+ return;
+
+ /* They're not, print the stripped version now. */
+ if (*quoted)
+ pp_end_quote (cpp, pp_show_color (cpp));
+ pp_c_whitespace (cpp);
+ pp_left_brace (cpp);
+ pp_c_ws_string (cpp, _("aka"));
+ pp_c_whitespace (cpp);
+ if (*quoted)
+ pp_begin_quote (cpp, pp_show_color (cpp));
+ cpp->type_id (TYPE_CANONICAL (t));
+ if (*quoted)
+ pp_end_quote (cpp, pp_show_color (cpp));
+ pp_right_brace (cpp);
+ /* No further closing quotes are needed. */
+ *quoted = false;
+ }
+}
+
/* Called during diagnostic message formatting process to print a
source-level entity onto BUFFER. The meaning of the format specifiers
is as follows:
%D: a general decl,
%E: an identifier or expression,
%F: a function declaration,
- %G: a Gimple call statement,
+ %G: a Gimple statement,
%K: a CALL_EXPR,
%T: a type.
%V: a list of type qualifiers from a tree.
@@ -82,7 +137,6 @@ c_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
bool *quoted, const char **)
{
tree t = NULL_TREE;
- tree name;
// FIXME: the next cast should be a dynamic_cast, when it is permitted.
c_pretty_printer *cpp = (c_pretty_printer *) pp;
pp->padding = pp_none;
@@ -99,7 +153,7 @@ c_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
if (*spec == 'K')
{
t = va_arg (*text->args_ptr, tree);
- percent_K_format (text, t);
+ percent_K_format (text, EXPR_LOCATION (t), TREE_BLOCK (t));
return true;
}
@@ -107,7 +161,8 @@ c_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
{
t = va_arg (*text->args_ptr, tree);
if (set_locus)
- text->set_location (0, DECL_SOURCE_LOCATION (t), true);
+ text->set_location (0, DECL_SOURCE_LOCATION (t),
+ SHOW_RANGE_WITH_CARET);
}
switch (*spec)
@@ -133,56 +188,8 @@ c_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
break;
case 'T':
- {
- gcc_assert (TYPE_P (t));
- struct obstack *ob = pp_buffer (cpp)->obstack;
- char *p = (char *) obstack_base (ob);
- /* Remember the end of the initial dump. */
- int len = obstack_object_size (ob);
-
- name = TYPE_NAME (t);
- if (name && TREE_CODE (name) == TYPE_DECL && DECL_NAME (name))
- pp_identifier (cpp, lang_hooks.decl_printable_name (name, 2));
- else
- cpp->type_id (t);
-
- /* If we're printing a type that involves typedefs, also print the
- stripped version. But sometimes the stripped version looks
- exactly the same, so we don't want it after all. To avoid
- printing it in that case, we play ugly obstack games. */
- if (TYPE_CANONICAL (t) && t != TYPE_CANONICAL (t))
- {
- c_pretty_printer cpp2;
- /* Print the stripped version into a temporary printer. */
- cpp2.type_id (TYPE_CANONICAL (t));
- struct obstack *ob2 = cpp2.buffer->obstack;
- /* Get the stripped version from the temporary printer. */
- const char *aka = (char *) obstack_base (ob2);
- int aka_len = obstack_object_size (ob2);
- int type1_len = obstack_object_size (ob) - len;
-
- /* If they are identical, bail out. */
- if (aka_len == type1_len && memcmp (p + len, aka, aka_len) == 0)
- return true;
-
- /* They're not, print the stripped version now. */
- if (*quoted)
- pp_end_quote (pp, pp_show_color (pp));
- pp_c_whitespace (cpp);
- pp_left_brace (cpp);
- pp_c_ws_string (cpp, _("aka"));
- pp_c_whitespace (cpp);
- if (*quoted)
- pp_begin_quote (pp, pp_show_color (pp));
- cpp->type_id (TYPE_CANONICAL (t));
- if (*quoted)
- pp_end_quote (pp, pp_show_color (pp));
- pp_right_brace (cpp);
- /* No further closing quotes are needed. */
- *quoted = false;
- }
- return true;
- }
+ print_type (cpp, t, quoted);
+ return true;
case 'E':
if (TREE_CODE (t) == IDENTIFIER_NODE)
@@ -207,6 +214,22 @@ c_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
return true;
}
+/* C-specific implementation of range_label::get_text () vfunc for
+ range_label_for_type_mismatch. */
+
+label_text
+range_label_for_type_mismatch::get_text (unsigned /*range_idx*/) const
+{
+ if (m_labelled_type == NULL_TREE)
+ return label_text (NULL, false);
+
+ c_pretty_printer cpp;
+ bool quoted = false;
+ print_type (&cpp, m_labelled_type, &quoted);
+ return label_text (xstrdup (pp_formatted_text (&cpp)), true);
+}
+
+
/* In C and ObjC, all decls have "C" linkage. */
bool
has_c_linkage (const_tree decl ATTRIBUTE_UNUSED)
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 7a92628..1766a25 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1814,6 +1814,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
}
else
{
+ auto_diagnostic_group d;
name_hint hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_TYPENAME,
here);
if (hint)
@@ -4049,6 +4050,7 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
c_parser_set_source_position_from_token (token);
if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
{
+ auto_diagnostic_group d;
name_hint hint = lookup_name_fuzzy (token->value,
FUZZY_LOOKUP_TYPENAME,
token->location);
@@ -6864,14 +6866,18 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
&& !(TREE_CODE (first_arg) == PARM_DECL \
&& C_ARRAY_PARAMETER (first_arg) \
&& warn_sizeof_array_argument)) \
- if (warning_at (stack[sp].loc, OPT_Wsizeof_pointer_div, \
- "division %<sizeof (%T) / sizeof (%T)%> does " \
- "not compute the number of array elements", \
- type0, type1)) \
- if (DECL_P (first_arg)) \
- inform (DECL_SOURCE_LOCATION (first_arg), \
- "first %<sizeof%> operand was declared here"); \
- } \
+ { \
+ auto_diagnostic_group d; \
+ if (warning_at (stack[sp].loc, OPT_Wsizeof_pointer_div, \
+ "division %<sizeof (%T) / sizeof (%T)%> " \
+ "does not compute the number of array " \
+ "elements", \
+ type0, type1)) \
+ if (DECL_P (first_arg)) \
+ inform (DECL_SOURCE_LOCATION (first_arg), \
+ "first %<sizeof%> operand was declared here"); \
+ } \
+ } \
break; \
default: \
break; \
@@ -9095,6 +9101,144 @@ sizeof_ptr_memacc_comptypes (tree type1, tree type2)
return comptypes (type1, type2) == 1;
}
+/* Warn for patterns where abs-like function appears to be used incorrectly,
+ gracely ignore any non-abs-like function. The warning location should be
+ LOC. FNDECL is the declaration of called function, it must be a
+ BUILT_IN_NORMAL function. ARG is the first and only argument of the
+ call. */
+
+static void
+warn_for_abs (location_t loc, tree fndecl, tree arg)
+{
+ tree atype = TREE_TYPE (arg);
+
+ /* Casts from pointers (and thus arrays and fndecls) will generate
+ -Wint-conversion warnings. Most other wrong types hopefully lead to type
+ mismatch errors. TODO: Think about what to do with FIXED_POINT_TYPE_P
+ types and possibly other exotic types. */
+ if (!INTEGRAL_TYPE_P (atype)
+ && !SCALAR_FLOAT_TYPE_P (atype)
+ && TREE_CODE (atype) != COMPLEX_TYPE)
+ return;
+
+ enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
+
+ switch (fcode)
+ {
+ case BUILT_IN_ABS:
+ case BUILT_IN_LABS:
+ case BUILT_IN_LLABS:
+ case BUILT_IN_IMAXABS:
+ if (!INTEGRAL_TYPE_P (atype))
+ {
+ if (SCALAR_FLOAT_TYPE_P (atype))
+ warning_at (loc, OPT_Wabsolute_value,
+ "using integer absolute value function %qD when "
+ "argument is of floating point type %qT",
+ fndecl, atype);
+ else if (TREE_CODE (atype) == COMPLEX_TYPE)
+ warning_at (loc, OPT_Wabsolute_value,
+ "using integer absolute value function %qD when "
+ "argument is of complex type %qT", fndecl, atype);
+ else
+ gcc_unreachable ();
+ return;
+ }
+ if (TYPE_UNSIGNED (atype))
+ warning_at (loc, OPT_Wabsolute_value,
+ "taking the absolute value of unsigned type %qT "
+ "has no effect", atype);
+ break;
+
+ CASE_FLT_FN (BUILT_IN_FABS):
+ CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
+ if (!SCALAR_FLOAT_TYPE_P (atype)
+ || DECIMAL_FLOAT_MODE_P (TYPE_MODE (atype)))
+ {
+ if (INTEGRAL_TYPE_P (atype))
+ warning_at (loc, OPT_Wabsolute_value,
+ "using floating point absolute value function %qD "
+ "when argument is of integer type %qT", fndecl, atype);
+ else if (DECIMAL_FLOAT_TYPE_P (atype))
+ warning_at (loc, OPT_Wabsolute_value,
+ "using floating point absolute value function %qD "
+ "when argument is of decimal floating point type %qT",
+ fndecl, atype);
+ else if (TREE_CODE (atype) == COMPLEX_TYPE)
+ warning_at (loc, OPT_Wabsolute_value,
+ "using floating point absolute value function %qD when "
+ "argument is of complex type %qT", fndecl, atype);
+ else
+ gcc_unreachable ();
+ return;
+ }
+ break;
+
+ CASE_FLT_FN (BUILT_IN_CABS):
+ if (TREE_CODE (atype) != COMPLEX_TYPE)
+ {
+ if (INTEGRAL_TYPE_P (atype))
+ warning_at (loc, OPT_Wabsolute_value,
+ "using complex absolute value function %qD when "
+ "argument is of integer type %qT", fndecl, atype);
+ else if (SCALAR_FLOAT_TYPE_P (atype))
+ warning_at (loc, OPT_Wabsolute_value,
+ "using complex absolute value function %qD when "
+ "argument is of floating point type %qT",
+ fndecl, atype);
+ else
+ gcc_unreachable ();
+
+ return;
+ }
+ break;
+
+ case BUILT_IN_FABSD32:
+ case BUILT_IN_FABSD64:
+ case BUILT_IN_FABSD128:
+ if (!DECIMAL_FLOAT_TYPE_P (atype))
+ {
+ if (INTEGRAL_TYPE_P (atype))
+ warning_at (loc, OPT_Wabsolute_value,
+ "using decimal floating point absolute value "
+ "function %qD when argument is of integer type %qT",
+ fndecl, atype);
+ else if (SCALAR_FLOAT_TYPE_P (atype))
+ warning_at (loc, OPT_Wabsolute_value,
+ "using decimal floating point absolute value "
+ "function %qD when argument is of floating point "
+ "type %qT", fndecl, atype);
+ else if (TREE_CODE (atype) == COMPLEX_TYPE)
+ warning_at (loc, OPT_Wabsolute_value,
+ "using decimal floating point absolute value "
+ "function %qD when argument is of complex type %qT",
+ fndecl, atype);
+ else
+ gcc_unreachable ();
+ return;
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ tree ftype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
+ if (TREE_CODE (atype) == COMPLEX_TYPE)
+ {
+ gcc_assert (TREE_CODE (ftype) == COMPLEX_TYPE);
+ atype = TREE_TYPE (atype);
+ ftype = TREE_TYPE (ftype);
+ }
+
+ if (TYPE_PRECISION (ftype) < TYPE_PRECISION (atype))
+ warning_at (loc, OPT_Wabsolute_value,
+ "absolute value function %qD given an argument of type %qT "
+ "but has parameter of type %qT which may cause truncation "
+ "of value", fndecl, atype, ftype);
+}
+
+
/* Parse a postfix expression after the initial primary or compound
literal; that is, parse a series of postfix operators.
@@ -9159,14 +9303,19 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
expr.value, exprlist,
sizeof_arg,
sizeof_ptr_memacc_comptypes);
- if (TREE_CODE (expr.value) == FUNCTION_DECL
- && DECL_BUILT_IN_CLASS (expr.value) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (expr.value) == BUILT_IN_MEMSET
- && vec_safe_length (exprlist) == 3)
+ if (TREE_CODE (expr.value) == FUNCTION_DECL)
{
- tree arg0 = (*exprlist)[0];
- tree arg2 = (*exprlist)[2];
- warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask);
+ if (fndecl_built_in_p (expr.value, BUILT_IN_MEMSET)
+ && vec_safe_length (exprlist) == 3)
+ {
+ tree arg0 = (*exprlist)[0];
+ tree arg2 = (*exprlist)[2];
+ warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask);
+ }
+ if (warn_absolute_value
+ && fndecl_built_in_p (expr.value, BUILT_IN_NORMAL)
+ && vec_safe_length (exprlist) == 1)
+ warn_for_abs (expr_loc, expr.value, (*exprlist)[0]);
}
start = expr.get_start ();
@@ -9179,8 +9328,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
expr.original_code = ERROR_MARK;
if (TREE_CODE (expr.value) == INTEGER_CST
&& TREE_CODE (orig_expr.value) == FUNCTION_DECL
- && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
+ && fndecl_built_in_p (orig_expr.value, BUILT_IN_CONSTANT_P))
expr.original_code = C_MAYBE_CONST_EXPR;
expr.original_type = NULL;
if (exprlist)
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index ae1a1e6..017c01c 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -102,7 +102,7 @@ along with GCC; see the file COPYING3. If not see
#define C_DECL_ISNT_PROTOTYPE(EXP) \
(EXP == 0 \
|| (!prototype_p (TREE_TYPE (EXP)) \
- && !DECL_BUILT_IN (EXP)))
+ && !fndecl_built_in_p (EXP)))
/* For FUNCTION_TYPE, a hidden list of types of arguments. The same as
TYPE_ARG_TYPES for functions with prototypes, but created for functions
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 90ae306..a5a7da0 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -2207,9 +2207,14 @@ lookup_field (tree type, tree component)
/* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
to the field elements. Use a binary search on this array to quickly
find the element. Otherwise, do a linear search. TYPE_LANG_SPECIFIC
- will always be set for structures which have many elements. */
+ will always be set for structures which have many elements.
- if (TYPE_LANG_SPECIFIC (type) && TYPE_LANG_SPECIFIC (type)->s)
+ Duplicate field checking replaces duplicates with NULL_TREE so
+ TYPE_LANG_SPECIFIC arrays are potentially no longer sorted. In that
+ case just iterate using DECL_CHAIN. */
+
+ if (TYPE_LANG_SPECIFIC (type) && TYPE_LANG_SPECIFIC (type)->s
+ && !seen_error ())
{
int bot, top, half;
tree *field_array = &TYPE_LANG_SPECIFIC (type)->s->elts[0];
@@ -2901,6 +2906,7 @@ c_expr_sizeof_expr (location_t loc, struct c_expr expr)
if (TREE_CODE (expr.value) == PARM_DECL
&& C_ARRAY_PARAMETER (expr.value))
{
+ auto_diagnostic_group d;
if (warning_at (loc, OPT_Wsizeof_array_argument,
"%<sizeof%> on array function parameter %qE will "
"return size of %qT", expr.value,
@@ -3102,9 +3108,7 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
argarray = vec_safe_address (params);
/* Check that arguments to builtin functions match the expectations. */
- if (fundecl
- && DECL_BUILT_IN (fundecl)
- && DECL_BUILT_IN_CLASS (fundecl) == BUILT_IN_NORMAL
+ if (fundecl && fndecl_built_in_p (fundecl, BUILT_IN_NORMAL)
&& !check_builtin_function_arguments (loc, arg_loc, fundecl, nargs,
argarray))
return error_mark_node;
@@ -3227,8 +3231,7 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
precision should be removed (classification) or not
(comparison). */
if (type_generic
- && DECL_BUILT_IN (fundecl)
- && DECL_BUILT_IN_CLASS (fundecl) == BUILT_IN_NORMAL)
+ && fndecl_built_in_p (fundecl, BUILT_IN_NORMAL))
{
switch (DECL_FUNCTION_CODE (fundecl))
{
@@ -3730,19 +3733,27 @@ parser_build_binary_op (location_t location, enum tree_code code,
"comparison with string literal results in unspecified behavior");
/* Warn for ptr == '\0', it's likely that it should've been ptr[0]. */
if (POINTER_TYPE_P (type1)
- && null_pointer_constant_p (arg2.value)
- && char_type_p (type2)
- && warning_at (location, OPT_Wpointer_compare,
- "comparison between pointer and zero character "
- "constant"))
- inform (arg1.get_start (), "did you mean to dereference the pointer?");
+ && null_pointer_constant_p (arg2.value)
+ && char_type_p (type2))
+ {
+ auto_diagnostic_group d;
+ if (warning_at (location, OPT_Wpointer_compare,
+ "comparison between pointer and zero character "
+ "constant"))
+ inform (arg1.get_start (),
+ "did you mean to dereference the pointer?");
+ }
else if (POINTER_TYPE_P (type2)
&& null_pointer_constant_p (arg1.value)
- && char_type_p (type1)
- && warning_at (location, OPT_Wpointer_compare,
- "comparison between pointer and zero character "
- "constant"))
- inform (arg2.get_start (), "did you mean to dereference the pointer?");
+ && char_type_p (type1))
+ {
+ auto_diagnostic_group d;
+ if (warning_at (location, OPT_Wpointer_compare,
+ "comparison between pointer and zero character "
+ "constant"))
+ inform (arg2.get_start (),
+ "did you mean to dereference the pointer?");
+ }
}
else if (TREE_CODE_CLASS (code) == tcc_comparison
&& (code1 == STRING_CST || code2 == STRING_CST))
@@ -4283,13 +4294,16 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
e = TREE_OPERAND (e, 1);
if ((TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE
- || truth_value_p (TREE_CODE (e)))
- && warning_at (location, OPT_Wbool_operation,
- "%<~%> on a boolean expression"))
+ || truth_value_p (TREE_CODE (e))))
{
- gcc_rich_location richloc (location);
- richloc.add_fixit_insert_before (location, "!");
- inform (&richloc, "did you mean to use logical not?");
+ auto_diagnostic_group d;
+ if (warning_at (location, OPT_Wbool_operation,
+ "%<~%> on a boolean expression"))
+ {
+ gcc_rich_location richloc (location);
+ richloc.add_fixit_insert_before (location, "!");
+ inform (&richloc, "did you mean to use logical not?");
+ }
}
if (!noconvert)
arg = default_conversion (arg);
@@ -6192,6 +6206,8 @@ error_init (location_t loc, const char *gmsgid)
{
char *ofwhat;
+ auto_diagnostic_group d;
+
/* The gmsgid may be a format string with %< and %>. */
error_at (loc, gmsgid);
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
@@ -6211,7 +6227,7 @@ pedwarn_init (location_t loc, int opt, const char *gmsgid, ...)
it was defined to make sure macros defined in system headers
but used incorrectly elsewhere are diagnosed. */
source_location exploc = expansion_point_location_if_in_system_header (loc);
-
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
bool warned = emit_diagnostic_valist (DK_PEDWARN, exploc, opt, gmsgid, &ap);
@@ -6233,6 +6249,8 @@ warning_init (location_t loc, int opt, const char *gmsgid)
char *ofwhat;
bool warned;
+ auto_diagnostic_group d;
+
/* Use the location where a macro was expanded rather than where
it was defined to make sure macros defined in system headers
but used incorrectly elsewhere are diagnosed. */
@@ -6374,8 +6392,11 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
switch (errtype) \
{ \
case ic_argpass: \
- if (pedwarn (PLOC, OPT, AR, parmnum, rname)) \
- inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \
+ { \
+ auto_diagnostic_group d; \
+ if (pedwarn (PLOC, OPT, AR, parmnum, rname)) \
+ inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \
+ } \
break; \
case ic_assign: \
pedwarn (LOCATION, OPT, AS); \
@@ -6400,8 +6421,11 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
switch (errtype) \
{ \
case ic_argpass: \
- if (pedwarn (PLOC, OPT, AR, parmnum, rname, QUALS)) \
- inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \
+ { \
+ auto_diagnostic_group d; \
+ if (pedwarn (PLOC, OPT, AR, parmnum, rname, QUALS)) \
+ inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \
+ } \
break; \
case ic_assign: \
pedwarn (LOCATION, OPT, AS, QUALS); \
@@ -6426,8 +6450,11 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
switch (errtype) \
{ \
case ic_argpass: \
- if (warning_at (PLOC, OPT, AR, parmnum, rname, QUALS)) \
- inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \
+ { \
+ auto_diagnostic_group d; \
+ if (warning_at (PLOC, OPT, AR, parmnum, rname, QUALS)) \
+ inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \
+ } \
break; \
case ic_assign: \
warning_at (LOCATION, OPT, AS, QUALS); \
@@ -6919,13 +6946,16 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
switch (errtype)
{
case ic_argpass:
- if (pedwarn (expr_loc, OPT_Wpointer_sign,
- "pointer targets in passing argument %d of "
- "%qE differ in signedness", parmnum, rname))
- inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
- ? DECL_SOURCE_LOCATION (fundecl) : expr_loc,
- "expected %qT but argument is of type %qT",
- type, rhstype);
+ {
+ auto_diagnostic_group d;
+ range_label_for_type_mismatch rhs_label (rhstype, type);
+ gcc_rich_location richloc (expr_loc, &rhs_label);
+ if (pedwarn (&richloc, OPT_Wpointer_sign,
+ "pointer targets in passing argument %d of "
+ "%qE differ in signedness", parmnum, rname))
+ inform_for_arg (fundecl, expr_loc, parmnum, type,
+ rhstype);
+ }
break;
case ic_assign:
pedwarn (location, OPT_Wpointer_sign,
@@ -6976,10 +7006,15 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
switch (errtype)
{
case ic_argpass:
- if (pedwarn (expr_loc, OPT_Wincompatible_pointer_types,
- "passing argument %d of %qE from incompatible "
- "pointer type", parmnum, rname))
- inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
+ {
+ auto_diagnostic_group d;
+ range_label_for_type_mismatch rhs_label (rhstype, type);
+ gcc_rich_location richloc (expr_loc, &rhs_label);
+ if (pedwarn (&richloc, OPT_Wincompatible_pointer_types,
+ "passing argument %d of %qE from incompatible "
+ "pointer type", parmnum, rname))
+ inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
+ }
break;
case ic_assign:
pedwarn (location, OPT_Wincompatible_pointer_types,
@@ -7019,10 +7054,15 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
switch (errtype)
{
case ic_argpass:
- if (pedwarn (expr_loc, OPT_Wint_conversion,
- "passing argument %d of %qE makes pointer from "
- "integer without a cast", parmnum, rname))
- inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
+ {
+ auto_diagnostic_group d;
+ range_label_for_type_mismatch rhs_label (rhstype, type);
+ gcc_rich_location richloc (expr_loc, &rhs_label);
+ if (pedwarn (&richloc, OPT_Wint_conversion,
+ "passing argument %d of %qE makes pointer from "
+ "integer without a cast", parmnum, rname))
+ inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
+ }
break;
case ic_assign:
pedwarn (location, OPT_Wint_conversion,
@@ -7050,10 +7090,15 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
switch (errtype)
{
case ic_argpass:
- if (pedwarn (expr_loc, OPT_Wint_conversion,
- "passing argument %d of %qE makes integer from "
- "pointer without a cast", parmnum, rname))
- inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
+ {
+ auto_diagnostic_group d;
+ range_label_for_type_mismatch rhs_label (rhstype, type);
+ gcc_rich_location richloc (expr_loc, &rhs_label);
+ if (pedwarn (&richloc, OPT_Wint_conversion,
+ "passing argument %d of %qE makes integer from "
+ "pointer without a cast", parmnum, rname))
+ inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
+ }
break;
case ic_assign:
pedwarn (location, OPT_Wint_conversion,
@@ -7089,9 +7134,14 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
switch (errtype)
{
case ic_argpass:
- error_at (expr_loc, "incompatible type for argument %d of %qE", parmnum,
- rname);
- inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
+ {
+ auto_diagnostic_group d;
+ range_label_for_type_mismatch rhs_label (rhstype, type);
+ gcc_rich_location richloc (expr_loc, &rhs_label);
+ error_at (&richloc, "incompatible type for argument %d of %qE", parmnum,
+ rname);
+ inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
+ }
break;
case ic_assign:
error_at (location, "incompatible types when assigning to type %qT from "
@@ -7435,19 +7485,17 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
}
}
- TREE_TYPE (inside_init) = type;
if (TYPE_DOMAIN (type) != NULL_TREE
&& TYPE_SIZE (type) != NULL_TREE
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
{
unsigned HOST_WIDE_INT len = TREE_STRING_LENGTH (inside_init);
+ unsigned unit = TYPE_PRECISION (typ1) / BITS_PER_UNIT;
/* Subtract the size of a single (possibly wide) character
because it's ok to ignore the terminating null char
that is counted in the length of the constant. */
- if (compare_tree_int (TYPE_SIZE_UNIT (type),
- (len - (TYPE_PRECISION (typ1)
- / BITS_PER_UNIT))) < 0)
+ if (compare_tree_int (TYPE_SIZE_UNIT (type), len - unit) < 0)
pedwarn_init (init_loc, 0,
("initializer-string for array of chars "
"is too long"));
@@ -7456,8 +7504,17 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
warning_at (init_loc, OPT_Wc___compat,
("initializer-string for array chars "
"is too long for C++"));
+ if (compare_tree_int (TYPE_SIZE_UNIT (type), len) < 0)
+ {
+ unsigned HOST_WIDE_INT size
+ = tree_to_uhwi (TYPE_SIZE_UNIT (type));
+ const char *p = TREE_STRING_POINTER (inside_init);
+
+ inside_init = build_string (size, p);
+ }
}
+ TREE_TYPE (inside_init) = type;
return inside_init;
}
else if (INTEGRAL_TYPE_P (typ1))
@@ -9330,6 +9387,65 @@ output_init_element (location_t loc, tree value, tree origtype,
output_pending_init_elements (0, braced_init_obstack);
}
+/* For two FIELD_DECLs in the same chain, return -1 if field1
+ comes before field2, 1 if field1 comes after field2 and
+ 0 if field1 == field2. */
+
+static int
+init_field_decl_cmp (tree field1, tree field2)
+{
+ if (field1 == field2)
+ return 0;
+
+ tree bitpos1 = bit_position (field1);
+ tree bitpos2 = bit_position (field2);
+ if (tree_int_cst_equal (bitpos1, bitpos2))
+ {
+ /* If one of the fields has non-zero bitsize, then that
+ field must be the last one in a sequence of zero
+ sized fields, fields after it will have bigger
+ bit_position. */
+ if (TREE_TYPE (field1) != error_mark_node
+ && COMPLETE_TYPE_P (TREE_TYPE (field1))
+ && integer_nonzerop (TREE_TYPE (field1)))
+ return 1;
+ if (TREE_TYPE (field2) != error_mark_node
+ && COMPLETE_TYPE_P (TREE_TYPE (field2))
+ && integer_nonzerop (TREE_TYPE (field2)))
+ return -1;
+ /* Otherwise, fallback to DECL_CHAIN walk to find out
+ which field comes earlier. Walk chains of both
+ fields, so that if field1 and field2 are close to each
+ other in either order, it is found soon even for large
+ sequences of zero sized fields. */
+ tree f1 = field1, f2 = field2;
+ while (1)
+ {
+ f1 = DECL_CHAIN (f1);
+ f2 = DECL_CHAIN (f2);
+ if (f1 == NULL_TREE)
+ {
+ gcc_assert (f2);
+ return 1;
+ }
+ if (f2 == NULL_TREE)
+ return -1;
+ if (f1 == field2)
+ return -1;
+ if (f2 == field1)
+ return 1;
+ if (!tree_int_cst_equal (bit_position (f1), bitpos1))
+ return 1;
+ if (!tree_int_cst_equal (bit_position (f2), bitpos1))
+ return -1;
+ }
+ }
+ else if (tree_int_cst_lt (bitpos1, bitpos2))
+ return -1;
+ else
+ return 1;
+}
+
/* Output any pending elements which have become next.
As we output elements, constructor_unfilled_{fields,index}
advances, which may cause other elements to become next;
@@ -9401,25 +9517,18 @@ output_pending_init_elements (int all, struct obstack * braced_init_obstack)
}
else if (RECORD_OR_UNION_TYPE_P (constructor_type))
{
- tree ctor_unfilled_bitpos, elt_bitpos;
-
/* If the current record is complete we are done. */
if (constructor_unfilled_fields == NULL_TREE)
break;
- ctor_unfilled_bitpos = bit_position (constructor_unfilled_fields);
- elt_bitpos = bit_position (elt->purpose);
- /* We can't compare fields here because there might be empty
- fields in between. */
- if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos))
- {
- constructor_unfilled_fields = elt->purpose;
- output_init_element (input_location, elt->value, elt->origtype,
- true, TREE_TYPE (elt->purpose),
- elt->purpose, false, false,
- braced_init_obstack);
- }
- else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
+ int cmp = init_field_decl_cmp (constructor_unfilled_fields,
+ elt->purpose);
+ if (cmp == 0)
+ output_init_element (input_location, elt->value, elt->origtype,
+ true, TREE_TYPE (elt->purpose),
+ elt->purpose, false, false,
+ braced_init_obstack);
+ else if (cmp < 0)
{
/* Advance to the next smaller node. */
if (elt->left)
@@ -9445,8 +9554,8 @@ output_pending_init_elements (int all, struct obstack * braced_init_obstack)
elt = elt->parent;
elt = elt->parent;
if (elt
- && (tree_int_cst_lt (ctor_unfilled_bitpos,
- bit_position (elt->purpose))))
+ && init_field_decl_cmp (constructor_unfilled_fields,
+ elt->purpose) < 0)
{
next = elt->purpose;
break;
@@ -10935,6 +11044,38 @@ build_vec_cmp (tree_code code, tree type,
return build3 (VEC_COND_EXPR, type, cmp, minus_one_vec, zero_vec);
}
+/* Subclass of range_label for labelling the type of EXPR when reporting
+ a type mismatch between EXPR and OTHER_EXPR.
+ Either or both of EXPR and OTHER_EXPR could be NULL. */
+
+class maybe_range_label_for_tree_type_mismatch : public range_label
+{
+ public:
+ maybe_range_label_for_tree_type_mismatch (tree expr, tree other_expr)
+ : m_expr (expr), m_other_expr (other_expr)
+ {
+ }
+
+ label_text get_text (unsigned range_idx) const FINAL OVERRIDE
+ {
+ if (m_expr == NULL_TREE
+ || !EXPR_P (m_expr))
+ return label_text (NULL, false);
+ tree expr_type = TREE_TYPE (m_expr);
+
+ tree other_type = NULL_TREE;
+ if (m_other_expr && EXPR_P (m_other_expr))
+ other_type = TREE_TYPE (m_other_expr);
+
+ range_label_for_type_mismatch inner (expr_type, other_type);
+ return inner.get_text (range_idx);
+ }
+
+ private:
+ tree m_expr;
+ tree m_other_expr;
+};
+
/* Build a binary-operation expression without default conversions.
CODE is the kind of expression to build.
LOCATION is the operator's location.
@@ -11807,8 +11948,11 @@ build_binary_op (location_t location, enum tree_code code,
|| !vector_types_compatible_elements_p (type0, type1)))
{
gcc_rich_location richloc (location);
- richloc.maybe_add_expr (orig_op0);
- richloc.maybe_add_expr (orig_op1);
+ maybe_range_label_for_tree_type_mismatch
+ label_for_op0 (orig_op0, orig_op1),
+ label_for_op1 (orig_op1, orig_op0);
+ richloc.maybe_add_expr (orig_op0, &label_for_op0);
+ richloc.maybe_add_expr (orig_op1, &label_for_op1);
binary_op_error (&richloc, code, type0, type1);
return error_mark_node;
}
@@ -12049,8 +12193,11 @@ build_binary_op (location_t location, enum tree_code code,
if (!result_type)
{
gcc_rich_location richloc (location);
- richloc.maybe_add_expr (orig_op0);
- richloc.maybe_add_expr (orig_op1);
+ maybe_range_label_for_tree_type_mismatch
+ label_for_op0 (orig_op0, orig_op1),
+ label_for_op1 (orig_op1, orig_op0);
+ richloc.maybe_add_expr (orig_op0, &label_for_op0);
+ richloc.maybe_add_expr (orig_op1, &label_for_op1);
binary_op_error (&richloc, code, TREE_TYPE (op0), TREE_TYPE (op1));
return error_mark_node;
}
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index 1be5d14..ee2146f 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -450,6 +450,7 @@ c_parser_gimple_statement (c_parser *parser, gimple_seq *seq)
gimple-binary-expression:
gimple-unary-expression * gimple-unary-expression
+ gimple-unary-expression __MULT_HIGHPART gimple-unary-expression
gimple-unary-expression / gimple-unary-expression
gimple-unary-expression % gimple-unary-expression
gimple-unary-expression + gimple-unary-expression
@@ -544,6 +545,16 @@ c_parser_gimple_binary_expression (c_parser *parser)
case CPP_OR_OR:
c_parser_error (parser, "%<||%> not valid in GIMPLE");
return ret;
+ case CPP_NAME:
+ {
+ tree id = c_parser_peek_token (parser)->value;
+ if (strcmp (IDENTIFIER_POINTER (id), "__MULT_HIGHPART") == 0)
+ {
+ code = MULT_HIGHPART_EXPR;
+ break;
+ }
+ }
+ /* Fallthru. */
default:
/* Not a binary expression. */
return lhs;
diff --git a/gcc/calls.c b/gcc/calls.c
index 384c023..e9660b6 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -715,7 +715,7 @@ gimple_alloca_call_p (const gimple *stmt)
return false;
fndecl = gimple_call_fndecl (stmt);
- if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+ if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
switch (DECL_FUNCTION_CODE (fndecl))
{
CASE_BUILT_IN_ALLOCA:
@@ -1222,8 +1222,11 @@ alloc_max_size (void)
if (alloc_object_size_limit)
return alloc_object_size_limit;
- alloc_object_size_limit
- = build_int_cst (size_type_node, warn_alloc_size_limit);
+ HOST_WIDE_INT limit = warn_alloc_size_limit;
+ if (limit == HOST_WIDE_INT_MAX)
+ limit = tree_to_shwi (TYPE_MAX_VALUE (ptrdiff_type_node));
+
+ alloc_object_size_limit = build_int_cst (size_type_node, limit);
return alloc_object_size_limit;
}
@@ -1542,10 +1545,10 @@ get_attr_nonstring_decl (tree expr, tree *ref)
void
maybe_warn_nonstring_arg (tree fndecl, tree exp)
{
- if (!fndecl || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL)
+ if (!fndecl || !fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
return;
- if (TREE_NO_WARNING (exp))
+ if (TREE_NO_WARNING (exp) || !warn_stringop_overflow)
return;
unsigned nargs = call_expr_nargs (exp);
@@ -1573,7 +1576,9 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
the range of their known or possible lengths and use it
conservatively as the bound for the unbounded function,
and to adjust the range of the bound of the bounded ones. */
- for (unsigned argno = 0; argno < nargs && !*lenrng; argno ++)
+ for (unsigned argno = 0;
+ argno < MIN (nargs, 2)
+ && !(lenrng[1] && TREE_CODE (lenrng[1]) == INTEGER_CST); argno++)
{
tree arg = CALL_EXPR_ARG (exp, argno);
if (!get_attr_nonstring_decl (arg))
@@ -1585,12 +1590,12 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
case BUILT_IN_STRNCAT:
case BUILT_IN_STPNCPY:
case BUILT_IN_STRNCPY:
- if (2 < nargs)
+ if (nargs > 2)
bound = CALL_EXPR_ARG (exp, 2);
break;
case BUILT_IN_STRNDUP:
- if (1 < nargs)
+ if (nargs > 1)
bound = CALL_EXPR_ARG (exp, 1);
break;
@@ -1600,7 +1605,7 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
if (!get_attr_nonstring_decl (arg))
get_range_strlen (arg, lenrng);
- if (1 < nargs)
+ if (nargs > 1)
bound = CALL_EXPR_ARG (exp, 1);
break;
}
@@ -1640,11 +1645,9 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
}
}
- if (*lenrng)
+ if (lenrng[1] && TREE_CODE (lenrng[1]) == INTEGER_CST)
{
/* Add one for the nul. */
- lenrng[0] = const_binop (PLUS_EXPR, TREE_TYPE (lenrng[0]),
- lenrng[0], size_one_node);
lenrng[1] = const_binop (PLUS_EXPR, TREE_TYPE (lenrng[1]),
lenrng[1], size_one_node);
@@ -1773,6 +1776,7 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
bool warned = false;
+ auto_diagnostic_group d;
if (wi::ltu_p (asize, wibnd))
{
if (bndrng[0] == bndrng[1])
diff --git a/gcc/cfg.c b/gcc/cfg.c
index 6d55516..7be89d4 100644
--- a/gcc/cfg.c
+++ b/gcc/cfg.c
@@ -79,6 +79,8 @@ init_flow (struct function *the_fun)
= EXIT_BLOCK_PTR_FOR_FN (the_fun);
EXIT_BLOCK_PTR_FOR_FN (the_fun)->prev_bb
= ENTRY_BLOCK_PTR_FOR_FN (the_fun);
+ the_fun->cfg->edge_flags_allocated = EDGE_ALL_FLAGS;
+ the_fun->cfg->bb_flags_allocated = BB_ALL_FLAGS;
}
/* Helper function for remove_edge and clear_edges. Frees edge structure
diff --git a/gcc/cfg.h b/gcc/cfg.h
index 0953456..3d660bd 100644
--- a/gcc/cfg.h
+++ b/gcc/cfg.h
@@ -74,6 +74,10 @@ struct GTY(()) control_flow_graph {
/* Maximal count of BB in function. */
profile_count count_max;
+
+ /* Dynamically allocated edge/bb flags. */
+ int edge_flags_allocated;
+ int bb_flags_allocated;
};
@@ -121,4 +125,60 @@ extern basic_block get_bb_copy (basic_block);
void set_loop_copy (struct loop *, struct loop *);
struct loop *get_loop_copy (struct loop *);
+/* Generic RAII class to allocate a bit from storage of integer type T.
+ The allocated bit is accessible as mask with the single bit set
+ via the conversion operator to T. */
+
+template <class T>
+class auto_flag
+{
+public:
+ /* static assert T is integer type of max HOST_WIDE_INT precision. */
+ auto_flag (T *sptr)
+ {
+ m_sptr = sptr;
+ int free_bit = ffs_hwi (~*sptr);
+ /* If there are no unset bits... */
+ if (free_bit == 0)
+ gcc_unreachable ();
+ m_flag = HOST_WIDE_INT_1U << (free_bit - 1);
+ /* ...or if T is signed and thus the complement is sign-extended,
+ check if we ran out of bits. We could spare us this bit
+ if we could use C++11 std::make_unsigned<T>::type to pass
+ ~*sptr to ffs_hwi. */
+ if (m_flag == 0)
+ gcc_unreachable ();
+ gcc_checking_assert ((*sptr & m_flag) == 0);
+ *sptr |= m_flag;
+ }
+ ~auto_flag ()
+ {
+ gcc_checking_assert ((*m_sptr & m_flag) == m_flag);
+ *m_sptr &= ~m_flag;
+ }
+ operator T () const { return m_flag; }
+private:
+ T *m_sptr;
+ T m_flag;
+};
+
+/* RAII class to allocate an edge flag for temporary use. You have
+ to clear the flag from all edges when you are finished using it. */
+
+class auto_edge_flag : public auto_flag<int>
+{
+public:
+ auto_edge_flag (function *fun)
+ : auto_flag<int> (&fun->cfg->edge_flags_allocated) {}
+};
+
+/* RAII class to allocate a bb flag for temporary use. You have
+ to clear the flag from all edges when you are finished using it. */
+class auto_bb_flag : public auto_flag<int>
+{
+public:
+ auto_bb_flag (function *fun)
+ : auto_flag<int> (&fun->cfg->bb_flags_allocated) {}
+};
+
#endif /* GCC_CFG_H */
diff --git a/gcc/cfganal.c b/gcc/cfganal.c
index a901b3f..3b80758 100644
--- a/gcc/cfganal.c
+++ b/gcc/cfganal.c
@@ -1057,8 +1057,121 @@ pre_and_rev_post_order_compute (int *pre_order, int *rev_post_order,
return pre_order_num;
}
+/* Unlike pre_and_rev_post_order_compute we fill rev_post_order backwards
+ so iterating in RPO order needs to start with rev_post_order[n - 1]
+ going to rev_post_order[0]. If FOR_ITERATION is true then try to
+ make CFG cycles fit into small contiguous regions of the RPO order.
+ When FOR_ITERATION is true this requires up-to-date loop structures. */
+
+int
+rev_post_order_and_mark_dfs_back_seme (struct function *fn, edge entry,
+ bitmap exit_bbs, bool for_iteration,
+ int *rev_post_order)
+{
+ int pre_order_num = 0;
+ int rev_post_order_num = 0;
+
+ /* Allocate stack for back-tracking up CFG. Worst case we need
+ O(n^2) edges but the following should suffice in practice without
+ a need to re-allocate. */
+ auto_vec<edge, 20> stack (2 * n_basic_blocks_for_fn (fn));
+
+ int *pre = XNEWVEC (int, 2 * last_basic_block_for_fn (fn));
+ int *post = pre + last_basic_block_for_fn (fn);
+
+ /* BB flag to track nodes that have been visited. */
+ auto_bb_flag visited (fn);
+ /* BB flag to track which nodes have post[] assigned to avoid
+ zeroing post. */
+ auto_bb_flag post_assigned (fn);
+
+ /* Push the first edge on to the stack. */
+ stack.quick_push (entry);
+
+ while (!stack.is_empty ())
+ {
+ basic_block src;
+ basic_block dest;
+
+ /* Look at the edge on the top of the stack. */
+ int idx = stack.length () - 1;
+ edge e = stack[idx];
+ src = e->src;
+ dest = e->dest;
+ e->flags &= ~EDGE_DFS_BACK;
+
+ /* Check if the edge destination has been visited yet. */
+ if (! bitmap_bit_p (exit_bbs, dest->index)
+ && ! (dest->flags & visited))
+ {
+ /* Mark that we have visited the destination. */
+ dest->flags |= visited;
+
+ pre[dest->index] = pre_order_num++;
+
+ if (EDGE_COUNT (dest->succs) > 0)
+ {
+ /* Since the DEST node has been visited for the first
+ time, check its successors. */
+ /* Push the edge vector in reverse to match previous behavior. */
+ stack.reserve (EDGE_COUNT (dest->succs));
+ for (int i = EDGE_COUNT (dest->succs) - 1; i >= 0; --i)
+ stack.quick_push (EDGE_SUCC (dest, i));
+ /* Generalize to handle more successors? */
+ if (for_iteration
+ && EDGE_COUNT (dest->succs) == 2)
+ {
+ edge &e1 = stack[stack.length () - 2];
+ if (loop_exit_edge_p (e1->src->loop_father, e1))
+ std::swap (e1, stack.last ());
+ }
+ }
+ else
+ {
+ /* There are no successors for the DEST node so assign
+ its reverse completion number. */
+ post[dest->index] = rev_post_order_num;
+ dest->flags |= post_assigned;
+ rev_post_order[rev_post_order_num] = dest->index;
+ rev_post_order_num++;
+ }
+ }
+ else
+ {
+ if (dest->flags & visited
+ && src != entry->src
+ && pre[src->index] >= pre[dest->index]
+ && !(dest->flags & post_assigned))
+ e->flags |= EDGE_DFS_BACK;
+
+ if (idx != 0 && stack[idx - 1]->src != src)
+ {
+ /* There are no more successors for the SRC node
+ so assign its reverse completion number. */
+ post[src->index] = rev_post_order_num;
+ src->flags |= post_assigned;
+ rev_post_order[rev_post_order_num] = src->index;
+ rev_post_order_num++;
+ }
+
+ stack.pop ();
+ }
+ }
+
+ XDELETEVEC (pre);
+
+ /* Clear the temporarily allocated flags. */
+ for (int i = 0; i < rev_post_order_num; ++i)
+ BASIC_BLOCK_FOR_FN (fn, rev_post_order[i])->flags
+ &= ~(post_assigned|visited);
+
+ return rev_post_order_num;
+}
+
+
+
/* Compute the depth first search order on the _reverse_ graph and
- store in the array DFS_ORDER, marking the nodes visited in VISITED.
+ store it in the array DFS_ORDER, marking the nodes visited in VISITED.
Returns the number of nodes visited.
The computation is split into three pieces:
@@ -1145,41 +1258,12 @@ dfs_enumerate_from (basic_block bb, int reverse,
{
basic_block *st, lbb;
int sp = 0, tv = 0;
- unsigned size;
-
- /* A bitmap to keep track of visited blocks. Allocating it each time
- this function is called is not possible, since dfs_enumerate_from
- is often used on small (almost) disjoint parts of cfg (bodies of
- loops), and allocating a large sbitmap would lead to quadratic
- behavior. */
- static sbitmap visited;
- static unsigned v_size;
-
-#define MARK_VISITED(BB) (bitmap_set_bit (visited, (BB)->index))
-#define UNMARK_VISITED(BB) (bitmap_clear_bit (visited, (BB)->index))
-#define VISITED_P(BB) (bitmap_bit_p (visited, (BB)->index))
-
- /* Resize the VISITED sbitmap if necessary. */
- size = last_basic_block_for_fn (cfun);
- if (size < 10)
- size = 10;
- if (!visited)
- {
+ auto_bb_flag visited (cfun);
- visited = sbitmap_alloc (size);
- bitmap_clear (visited);
- v_size = size;
- }
- else if (v_size < size)
- {
- /* Ensure that we increase the size of the sbitmap exponentially. */
- if (2 * v_size > size)
- size = 2 * v_size;
-
- visited = sbitmap_resize (visited, size, 0);
- v_size = size;
- }
+#define MARK_VISITED(BB) ((BB)->flags |= visited)
+#define UNMARK_VISITED(BB) ((BB)->flags &= ~visited)
+#define VISITED_P(BB) (((BB)->flags & visited) != 0)
st = XNEWVEC (basic_block, rslt_max);
rslt[tv++] = st[sp++] = bb;
diff --git a/gcc/cfganal.h b/gcc/cfganal.h
index 101124f..122c665 100644
--- a/gcc/cfganal.h
+++ b/gcc/cfganal.h
@@ -67,6 +67,8 @@ extern void inverted_post_order_compute (vec<int> *postorder, sbitmap *start_poi
extern int pre_and_rev_post_order_compute_fn (struct function *,
int *, int *, bool);
extern int pre_and_rev_post_order_compute (int *, int *, bool);
+extern int rev_post_order_and_mark_dfs_back_seme (struct function *, edge,
+ bitmap, bool, int *);
extern int dfs_enumerate_from (basic_block, int,
bool (*)(const_basic_block, const void *),
basic_block *, int, const void *);
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index d6e3c38..35ca276 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -1155,6 +1155,20 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data)
if (repr_decl == NULL_TREE)
repr_decl = stack_vars[i].decl;
data->asan_decl_vec.safe_push (repr_decl);
+
+ /* Make sure a representative is unpoison if another
+ variable in the partition is handled by
+ use-after-scope sanitization. */
+ if (asan_handled_variables != NULL
+ && !asan_handled_variables->contains (repr_decl))
+ {
+ for (j = i; j != EOC; j = stack_vars[j].next)
+ if (asan_handled_variables->contains (stack_vars[j].decl))
+ break;
+ if (j != EOC)
+ asan_handled_variables->add (repr_decl);
+ }
+
data->asan_alignb = MAX (data->asan_alignb, alignb);
if (data->asan_base == NULL)
data->asan_base = gen_reg_rtx (Pmode);
@@ -1257,10 +1271,10 @@ set_parm_rtl (tree parm, rtx x)
allocate it, which means that in-frame portion is just a
pointer. ??? We've got a pseudo for sure here, do we
actually dynamically allocate its spilling area if needed?
- ??? Isn't it a problem when POINTER_SIZE also exceeds
- MAX_SUPPORTED_STACK_ALIGNMENT, as on cris and lm32? */
+ ??? Isn't it a problem when Pmode alignment also exceeds
+ MAX_SUPPORTED_STACK_ALIGNMENT, as can happen on cris and lm32? */
if (align > MAX_SUPPORTED_STACK_ALIGNMENT)
- align = POINTER_SIZE;
+ align = GET_MODE_ALIGNMENT (Pmode);
record_alignment_for_reg_var (align);
}
@@ -1381,7 +1395,7 @@ expand_one_ssa_partition (tree var)
/* If the variable alignment is very large we'll dynamicaly allocate
it, which means that in-frame portion is just a pointer. */
if (align > MAX_SUPPORTED_STACK_ALIGNMENT)
- align = POINTER_SIZE;
+ align = GET_MODE_ALIGNMENT (Pmode);
record_alignment_for_reg_var (align);
@@ -1608,7 +1622,7 @@ expand_one_var (tree var, bool toplevel, bool really_expand)
/* If the variable alignment is very large we'll dynamicaly allocate
it, which means that in-frame portion is just a pointer. */
if (align > MAX_SUPPORTED_STACK_ALIGNMENT)
- align = POINTER_SIZE;
+ align = GET_MODE_ALIGNMENT (Pmode);
}
record_alignment_for_reg_var (align);
@@ -2477,6 +2491,13 @@ expand_gimple_cond (basic_block bb, gcond *stmt)
}
}
+ /* Optimize (x % C1) == C2 or (x % C1) != C2 if it is beneficial
+ into (x - C2) * C3 < C4. */
+ if ((code == EQ_EXPR || code == NE_EXPR)
+ && TREE_CODE (op0) == SSA_NAME
+ && TREE_CODE (op1) == INTEGER_CST)
+ code = maybe_optimize_mod_cmp (code, &op0, &op1);
+
last2 = last = get_last_insn ();
extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
@@ -2616,7 +2637,7 @@ expand_call_stmt (gcall *stmt)
exp = build_vl_exp (CALL_EXPR, gimple_call_num_args (stmt) + 3);
CALL_EXPR_FN (exp) = gimple_call_fn (stmt);
- builtin_p = decl && DECL_BUILT_IN (decl);
+ builtin_p = decl && fndecl_built_in_p (decl);
/* If this is not a builtin function, the function type through which the
call is made may be different from the type of the function. */
@@ -2655,7 +2676,7 @@ expand_call_stmt (gcall *stmt)
CALL_EXPR_MUST_TAIL_CALL (exp) = gimple_call_must_tail_p (stmt);
CALL_EXPR_RETURN_SLOT_OPT (exp) = gimple_call_return_slot_opt_p (stmt);
if (decl
- && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
+ && fndecl_built_in_p (decl, BUILT_IN_NORMAL)
&& ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (decl)))
CALL_ALLOCA_FOR_VAR_P (exp) = gimple_call_alloca_for_var_p (stmt);
else
@@ -3239,7 +3260,7 @@ expand_asm_stmt (gasm *stmt)
may insert further instructions into the same basic block after
asm goto and if we don't do this, insertion of instructions on
the fallthru edge might misbehave. See PR58670. */
- if (fallthru_bb && label_to_block_fn (cfun, label) == fallthru_bb)
+ if (fallthru_bb && label_to_block (cfun, label) == fallthru_bb)
{
if (fallthru_label == NULL_RTX)
fallthru_label = gen_label_rtx ();
@@ -3750,6 +3771,7 @@ expand_gimple_stmt (gimple *stmt)
/* If we want exceptions for non-call insns, any
may_trap_p instruction may throw. */
&& GET_CODE (PATTERN (insn)) != CLOBBER
+ && GET_CODE (PATTERN (insn)) != CLOBBER_HIGH
&& GET_CODE (PATTERN (insn)) != USE
&& insn_could_throw_p (insn))
make_reg_eh_region_note (insn, 0, lp_nr);
@@ -5809,6 +5831,8 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls)
last = PREV_INSN (last);
if (JUMP_TABLE_DATA_P (last))
last = PREV_INSN (PREV_INSN (last));
+ if (BARRIER_P (last))
+ last = PREV_INSN (last);
BB_END (bb) = last;
update_bb_for_insn (bb);
diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
index e27cd39..0917b71 100644
--- a/gcc/cfgloop.c
+++ b/gcc/cfgloop.c
@@ -1539,6 +1539,7 @@ verify_loop_structure (void)
/* Check irreducible loops. */
if (loops_state_satisfies_p (LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS))
{
+ auto_edge_flag saved_irr_mask (cfun);
/* Record old info. */
auto_sbitmap irreds (last_basic_block_for_fn (cfun));
FOR_EACH_BB_FN (bb, cfun)
@@ -1550,7 +1551,7 @@ verify_loop_structure (void)
bitmap_clear_bit (irreds, bb->index);
FOR_EACH_EDGE (e, ei, bb->succs)
if (e->flags & EDGE_IRREDUCIBLE_LOOP)
- e->flags |= EDGE_ALL_FLAGS + 1;
+ e->flags |= saved_irr_mask;
}
/* Recount it. */
@@ -1576,20 +1577,20 @@ verify_loop_structure (void)
FOR_EACH_EDGE (e, ei, bb->succs)
{
if ((e->flags & EDGE_IRREDUCIBLE_LOOP)
- && !(e->flags & (EDGE_ALL_FLAGS + 1)))
+ && !(e->flags & saved_irr_mask))
{
error ("edge from %d to %d should be marked irreducible",
e->src->index, e->dest->index);
err = 1;
}
else if (!(e->flags & EDGE_IRREDUCIBLE_LOOP)
- && (e->flags & (EDGE_ALL_FLAGS + 1)))
+ && (e->flags & saved_irr_mask))
{
error ("edge from %d to %d should not be marked irreducible",
e->src->index, e->dest->index);
err = 1;
}
- e->flags &= ~(EDGE_ALL_FLAGS + 1);
+ e->flags &= ~saved_irr_mask;
}
}
}
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index d19f1aa..148f29e 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -1559,8 +1559,7 @@ cgraph_update_edges_for_call_stmt_node (cgraph_node *node,
{
/* Keep calls marked as dead dead. */
if (new_stmt && is_gimple_call (new_stmt) && e->callee
- && DECL_BUILT_IN_CLASS (e->callee->decl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (e->callee->decl) == BUILT_IN_UNREACHABLE)
+ && fndecl_built_in_p (e->callee->decl, BUILT_IN_UNREACHABLE))
{
node->get_edge (old_stmt)->set_call_stmt
(as_a <gcall *> (new_stmt));
@@ -3060,8 +3059,8 @@ cgraph_edge::verify_corresponds_to_fndecl (tree decl)
/* Optimizers can redirect unreachable calls or calls triggering undefined
behavior to builtin_unreachable. */
- if (DECL_BUILT_IN_CLASS (callee->decl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (callee->decl) == BUILT_IN_UNREACHABLE)
+
+ if (fndecl_built_in_p (callee->decl, BUILT_IN_UNREACHABLE))
return false;
if (callee->former_clone_of != node->decl
@@ -3187,8 +3186,7 @@ cgraph_node::verify_node (void)
/* Optimized out calls are redirected to __builtin_unreachable. */
&& (e->count.nonzero_p ()
|| ! e->callee->decl
- || DECL_BUILT_IN_CLASS (e->callee->decl) != BUILT_IN_NORMAL
- || DECL_FUNCTION_CODE (e->callee->decl) != BUILT_IN_UNREACHABLE)
+ || !fndecl_built_in_p (e->callee->decl, BUILT_IN_UNREACHABLE))
&& count
== ENTRY_BLOCK_PTR_FOR_FN (DECL_STRUCT_FUNCTION (decl))->count
&& (!e->count.ipa_p ()
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index a8b1b4c..2b00f01 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -25,6 +25,14 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-ref.h"
#include "plugin-api.h"
+extern void debuginfo_early_init (void);
+extern void debuginfo_init (void);
+extern void debuginfo_fini (void);
+extern void debuginfo_start (void);
+extern void debuginfo_stop (void);
+extern void debuginfo_early_start (void);
+extern void debuginfo_early_stop (void);
+
class ipa_opt_pass_d;
typedef ipa_opt_pass_d *ipa_opt_pass;
diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
index 6e84a31..0c0a94b 100644
--- a/gcc/cgraphclones.c
+++ b/gcc/cgraphclones.c
@@ -222,7 +222,7 @@ build_function_decl_skip_args (tree orig_decl, bitmap args_to_skip,
DECL_VINDEX (new_decl) = NULL_TREE;
/* When signature changes, we need to clear builtin info. */
- if (DECL_BUILT_IN (new_decl)
+ if (fndecl_built_in_p (new_decl)
&& args_to_skip
&& !bitmap_empty_p (args_to_skip))
{
@@ -482,8 +482,7 @@ cgraph_node::create_clone (tree new_decl, profile_count prof_count,
version. The only exception is when the edge was proved to
be unreachable during the clonning procedure. */
if (!e->callee
- || DECL_BUILT_IN_CLASS (e->callee->decl) != BUILT_IN_NORMAL
- || DECL_FUNCTION_CODE (e->callee->decl) != BUILT_IN_UNREACHABLE)
+ || !fndecl_built_in_p (e->callee->decl, BUILT_IN_UNREACHABLE))
e->redirect_callee_duplicating_thunks (new_node);
}
new_node->expand_all_artificial_thunks ();
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 462e247..ec490d7 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1358,6 +1358,7 @@ maybe_diag_incompatible_alias (tree alias, tree target)
{
funcptr = build_pointer_type (funcptr);
+ auto_diagnostic_group d;
if (warning_at (DECL_SOURCE_LOCATION (target),
OPT_Wattribute_alias,
"%<ifunc%> resolver for %qD should return %qT",
@@ -1365,12 +1366,16 @@ maybe_diag_incompatible_alias (tree alias, tree target)
inform (DECL_SOURCE_LOCATION (alias),
"resolver indirect function declared here");
}
- else if (warning_at (DECL_SOURCE_LOCATION (alias),
- OPT_Wattribute_alias,
- "%qD alias between functions of incompatible "
- "types %qT and %qT", alias, altype, targtype))
- inform (DECL_SOURCE_LOCATION (target),
- "aliased declaration here");
+ else
+ {
+ auto_diagnostic_group d;
+ if (warning_at (DECL_SOURCE_LOCATION (alias),
+ OPT_Wattribute_alias,
+ "%qD alias between functions of incompatible "
+ "types %qT and %qT", alias, altype, targtype))
+ inform (DECL_SOURCE_LOCATION (target),
+ "aliased declaration here");
+ }
}
}
@@ -2636,6 +2641,89 @@ symbol_table::compile (void)
}
}
+/* Earlydebug dump file, flags, and number. */
+
+static int debuginfo_early_dump_nr;
+static FILE *debuginfo_early_dump_file;
+static dump_flags_t debuginfo_early_dump_flags;
+
+/* Debug dump file, flags, and number. */
+
+static int debuginfo_dump_nr;
+static FILE *debuginfo_dump_file;
+static dump_flags_t debuginfo_dump_flags;
+
+/* Register the debug and earlydebug dump files. */
+
+void
+debuginfo_early_init (void)
+{
+ gcc::dump_manager *dumps = g->get_dumps ();
+ debuginfo_early_dump_nr = dumps->dump_register (".earlydebug", "earlydebug",
+ "earlydebug", DK_tree,
+ OPTGROUP_NONE,
+ false);
+ debuginfo_dump_nr = dumps->dump_register (".debug", "debug",
+ "debug", DK_tree,
+ OPTGROUP_NONE,
+ false);
+}
+
+/* Initialize the debug and earlydebug dump files. */
+
+void
+debuginfo_init (void)
+{
+ gcc::dump_manager *dumps = g->get_dumps ();
+ debuginfo_dump_file = dump_begin (debuginfo_dump_nr, NULL);
+ debuginfo_dump_flags = dumps->get_dump_file_info (debuginfo_dump_nr)->pflags;
+ debuginfo_early_dump_file = dump_begin (debuginfo_early_dump_nr, NULL);
+ debuginfo_early_dump_flags
+ = dumps->get_dump_file_info (debuginfo_early_dump_nr)->pflags;
+}
+
+/* Finalize the debug and earlydebug dump files. */
+
+void
+debuginfo_fini (void)
+{
+ if (debuginfo_dump_file)
+ dump_end (debuginfo_dump_nr, debuginfo_dump_file);
+ if (debuginfo_early_dump_file)
+ dump_end (debuginfo_early_dump_nr, debuginfo_early_dump_file);
+}
+
+/* Set dump_file to the debug dump file. */
+
+void
+debuginfo_start (void)
+{
+ set_dump_file (debuginfo_dump_file);
+}
+
+/* Undo setting dump_file to the debug dump file. */
+
+void
+debuginfo_stop (void)
+{
+ set_dump_file (NULL);
+}
+
+/* Set dump_file to the earlydebug dump file. */
+
+void
+debuginfo_early_start (void)
+{
+ set_dump_file (debuginfo_early_dump_file);
+}
+
+/* Undo setting dump_file to the earlydebug dump file. */
+
+void
+debuginfo_early_stop (void)
+{
+ set_dump_file (NULL);
+}
/* Analyze the whole compilation unit once it is parsed completely. */
@@ -2691,7 +2779,9 @@ symbol_table::finalize_compilation_unit (void)
/* Clean up anything that needs cleaning up after initial debug
generation. */
+ debuginfo_early_start ();
(*debug_hooks->early_finish) (main_input_filename);
+ debuginfo_early_stop ();
}
/* Finally drive the pass manager. */
diff --git a/gcc/combine-stack-adj.c b/gcc/combine-stack-adj.c
index 4573dc2..bd7f5d0 100644
--- a/gcc/combine-stack-adj.c
+++ b/gcc/combine-stack-adj.c
@@ -133,6 +133,7 @@ single_set_for_csa (rtx_insn *insn)
&& SET_SRC (this_rtx) == SET_DEST (this_rtx))
;
else if (GET_CODE (this_rtx) != CLOBBER
+ && GET_CODE (this_rtx) != CLOBBER_HIGH
&& GET_CODE (this_rtx) != USE)
return NULL_RTX;
}
diff --git a/gcc/combine.c b/gcc/combine.c
index 3a5883a..60cfe97 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -570,6 +570,7 @@ find_single_use_1 (rtx dest, rtx *loc)
case SYMBOL_REF:
CASE_CONST_ANY:
case CLOBBER:
+ case CLOBBER_HIGH:
return 0;
case SET:
@@ -1752,6 +1753,9 @@ set_nonzero_bits_and_sign_copies (rtx x, const_rtx set, void *data)
return;
}
+ /* Should not happen as we only using pseduo registers. */
+ gcc_assert (GET_CODE (set) != CLOBBER_HIGH);
+
/* If this register is being initialized using itself, and the
register is uninitialized in this basic block, and there are
no LOG_LINKS which set the register, then part of the
@@ -1910,6 +1914,7 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn *pred ATTRIBUTE_UNUSED,
/* We can ignore CLOBBERs. */
case CLOBBER:
+ case CLOBBER_HIGH:
break;
case SET:
@@ -2570,10 +2575,17 @@ is_parallel_of_n_reg_sets (rtx pat, int n)
|| !REG_P (SET_DEST (XVECEXP (pat, 0, i))))
return false;
for ( ; i < len; i++)
- if (GET_CODE (XVECEXP (pat, 0, i)) != CLOBBER
- || XEXP (XVECEXP (pat, 0, i), 0) == const0_rtx)
- return false;
-
+ switch (GET_CODE (XVECEXP (pat, 0, i)))
+ {
+ case CLOBBER:
+ if (XEXP (XVECEXP (pat, 0, i), 0) == const0_rtx)
+ return false;
+ break;
+ case CLOBBER_HIGH:
+ break;
+ default:
+ return false;
+ }
return true;
}
@@ -2860,7 +2872,8 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
for (i = 0; ok && i < XVECLEN (p2, 0); i++)
{
if ((GET_CODE (XVECEXP (p2, 0, i)) == SET
- || GET_CODE (XVECEXP (p2, 0, i)) == CLOBBER)
+ || GET_CODE (XVECEXP (p2, 0, i)) == CLOBBER
+ || GET_CODE (XVECEXP (p2, 0, i)) == CLOBBER_HIGH)
&& reg_overlap_mentioned_p (SET_DEST (PATTERN (i3)),
SET_DEST (XVECEXP (p2, 0, i))))
ok = false;
@@ -3297,7 +3310,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
{
/* Replace cc_use_loc with entire new RTX. */
SUBST (*cc_use_loc,
- gen_rtx_fmt_ee (compare_code, compare_mode,
+ gen_rtx_fmt_ee (compare_code, GET_MODE (*cc_use_loc),
newpat_dest, const0_rtx));
undobuf.other_insn = cc_use_insn;
}
@@ -3306,7 +3319,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
/* Just replace the CC reg with a new mode. */
SUBST (XEXP (*cc_use_loc, 0), newpat_dest);
undobuf.other_insn = cc_use_insn;
- }
+ }
}
/* Now we modify the current newpat:
@@ -4023,7 +4036,10 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
other insns to combine, but the destination of that SET is still live.
Also do this if we started with two insns and (at least) one of the
- resulting sets is a noop; this noop will be deleted later. */
+ resulting sets is a noop; this noop will be deleted later.
+
+ Also do this if we started with two insns neither of which was a simple
+ move. */
else if (insn_code_number < 0 && asm_noperands (newpat) < 0
&& GET_CODE (newpat) == PARALLEL
@@ -4053,13 +4069,15 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
one which uses any regs/memory set in between i2 and i3 can't
be first. The PARALLEL might also have been pre-existing in i3,
so we need to make sure that we won't wrongly hoist a SET to i2
- that would conflict with a death note present in there. */
+ that would conflict with a death note present in there, or would
+ have its dest modified between i2 and i3. */
if (!modified_between_p (SET_SRC (set1), i2, i3)
&& !(REG_P (SET_DEST (set1))
&& find_reg_note (i2, REG_DEAD, SET_DEST (set1)))
&& !(GET_CODE (SET_DEST (set1)) == SUBREG
&& find_reg_note (i2, REG_DEAD,
SUBREG_REG (SET_DEST (set1))))
+ && !modified_between_p (SET_DEST (set1), i2, i3)
&& (!HAVE_cc0 || !reg_referenced_p (cc0_rtx, set0))
/* If I3 is a jump, ensure that set0 is a jump so that
we do not create invalid RTL. */
@@ -4075,6 +4093,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
&& !(GET_CODE (SET_DEST (set0)) == SUBREG
&& find_reg_note (i2, REG_DEAD,
SUBREG_REG (SET_DEST (set0))))
+ && !modified_between_p (SET_DEST (set0), i2, i3)
&& (!HAVE_cc0 || !reg_referenced_p (cc0_rtx, set1))
/* If I3 is a jump, ensure that set1 is a jump so that
we do not create invalid RTL. */
@@ -6476,7 +6495,7 @@ simplify_if_then_else (rtx x)
pc_rtx, pc_rtx, 0, 0, 0);
if (reg_mentioned_p (from, false_rtx))
false_rtx = subst (known_cond (copy_rtx (false_rtx), false_code,
- from, false_val),
+ from, false_val),
pc_rtx, pc_rtx, 0, 0, 0);
SUBST (XEXP (x, 1), swapped ? false_rtx : true_rtx);
@@ -9316,6 +9335,7 @@ if_then_else_cond (rtx x, rtx *ptrue, rtx *pfalse)
if (COMPARISON_P (cond0)
&& COMPARISON_P (cond1)
+ && SCALAR_INT_MODE_P (mode)
&& ((GET_CODE (cond0) == reversed_comparison_code (cond1, NULL)
&& rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 0))
&& rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 1)))
@@ -9496,12 +9516,12 @@ known_cond (rtx x, enum rtx_code cond, rtx reg, rtx val)
if (COMPARISON_P (x))
{
if (comparison_dominates_p (cond, code))
- return const_true_rtx;
+ return VECTOR_MODE_P (GET_MODE (x)) ? x : const_true_rtx;
code = reversed_comparison_code (x, NULL);
if (code != UNKNOWN
&& comparison_dominates_p (cond, code))
- return const0_rtx;
+ return CONST0_RTX (GET_MODE (x));
else
return x;
}
@@ -9544,7 +9564,7 @@ known_cond (rtx x, enum rtx_code cond, rtx reg, rtx val)
/* We must simplify subreg here, before we lose track of the
original inner_mode. */
new_rtx = simplify_subreg (GET_MODE (x), r,
- inner_mode, SUBREG_BYTE (x));
+ inner_mode, SUBREG_BYTE (x));
if (new_rtx)
return new_rtx;
else
@@ -9569,7 +9589,7 @@ known_cond (rtx x, enum rtx_code cond, rtx reg, rtx val)
/* We must simplify the zero_extend here, before we lose
track of the original inner_mode. */
new_rtx = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x),
- r, inner_mode);
+ r, inner_mode);
if (new_rtx)
return new_rtx;
else
@@ -13315,6 +13335,15 @@ record_dead_and_set_regs_1 (rtx dest, const_rtx setter, void *data)
? SET_SRC (setter)
: gen_lowpart (GET_MODE (dest),
SET_SRC (setter)));
+ else if (GET_CODE (setter) == CLOBBER_HIGH)
+ {
+ reg_stat_type *rsp = &reg_stat[REGNO (dest)];
+ if (rsp->last_set_value
+ && reg_is_clobbered_by_clobber_high
+ (REGNO (dest), GET_MODE (rsp->last_set_value),
+ XEXP (setter, 0)))
+ record_value_for_reg (dest, NULL, NULL_RTX);
+ }
else
record_value_for_reg (dest, record_dead_insn, NULL_RTX);
}
@@ -13735,6 +13764,7 @@ get_last_value (const_rtx x)
static unsigned int reg_dead_regno, reg_dead_endregno;
static int reg_dead_flag;
+rtx reg_dead_reg;
/* Function called via note_stores from reg_dead_at_p.
@@ -13749,6 +13779,10 @@ reg_dead_at_p_1 (rtx dest, const_rtx x, void *data ATTRIBUTE_UNUSED)
if (!REG_P (dest))
return;
+ if (GET_CODE (x) == CLOBBER_HIGH
+ && !reg_is_clobbered_by_clobber_high (reg_dead_reg, XEXP (x, 0)))
+ return;
+
regno = REGNO (dest);
endregno = END_REGNO (dest);
if (reg_dead_endregno > regno && reg_dead_regno < endregno)
@@ -13772,6 +13806,7 @@ reg_dead_at_p (rtx reg, rtx_insn *insn)
/* Set variables for reg_dead_at_p_1. */
reg_dead_regno = REGNO (reg);
reg_dead_endregno = END_REGNO (reg);
+ reg_dead_reg = reg;
reg_dead_flag = 0;
diff --git a/gcc/common.opt b/gcc/common.opt
index 5bb6452..ef6a630 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1087,7 +1087,7 @@ Common Report Var(flag_caller_saves) Optimization
Save registers around function calls.
fcheck-data-deps
-Common Report Var(flag_check_data_deps)
+Common Ignore
This switch is deprecated; do not use.
fcheck-new
@@ -1233,6 +1233,14 @@ fdiagnostics-show-caret
Common Var(flag_diagnostics_show_caret) Init(1)
Show the source line with a caret indicating the column.
+fdiagnostics-show-labels
+Common Var(flag_diagnostics_show_labels) Init(1)
+Show labels annotating ranges of source code when showing source
+
+fdiagnostics-show-line-numbers
+Common Var(flag_diagnostics_show_line_numbers) Init(1)
+Show line numbers in the left margin when showing source
+
fdiagnostics-color
Common Alias(fdiagnostics-color=,always,never)
;
@@ -2765,7 +2773,6 @@ Enable basic block vectorization (SLP) on trees.
fvect-cost-model=
Common Joined RejectNegative Enum(vect_cost_model) Var(flag_vect_cost_model) Init(VECT_COST_MODEL_DEFAULT) Optimization
-Specifies the cost model for vectorization.
-fvect-cost-model=[unlimited|dynamic|cheap] Specifies the cost model for vectorization.
fsimd-cost-model=
@@ -2890,19 +2897,19 @@ Common Driver Var(dwarf2out_as_locview_support) Init(2)
Assume assembler support for view in (DWARF2+) .loc directives
gcoff
-Common Driver Ignore Warn(switch %qs no longer supported)
+Common Driver Deprecated
Does nothing. Preserved for backward compatibility.
gcoff1
-Common Driver Ignore Warn(switch %qs no longer supported)
+Common Driver Deprecated
Does nothing. Preserved for backward compatibility.
gcoff2
-Common Driver Ignore Warn(switch %qs no longer supported)
+Common Driver Deprecated
Does nothing. Preserved for backward compatibility.
gcoff3
-Common Driver Ignore Warn(switch %qs no longer supported)
+Common Driver Deprecated
Does nothing. Preserved for backward compatibility.
gcolumn-info
@@ -2969,6 +2976,10 @@ gstrict-dwarf
Common Driver Report Var(dwarf_strict) Init(0)
Don't emit DWARF additions beyond selected version.
+gdescribe-dies
+Common Driver Report Var(flag_describe_dies) Init(0)
+Add description attributes to some DWARF DIEs that have no name attribute.
+
gtoggle
Common Driver Report Var(flag_gtoggle)
Toggle debug information generation.
diff --git a/gcc/common/common-target.def b/gcc/common/common-target.def
index e0afbc6..019b1e7 100644
--- a/gcc/common/common-target.def
+++ b/gcc/common/common-target.def
@@ -80,6 +80,17 @@ DEFHOOK
bool, (bool report, struct gcc_options *opts),
hook_bool_bool_gcc_optionsp_false)
+DEFHOOK
+(get_valid_option_values,
+"The hook is used for options that have a non-trivial list of\
+ possible option values. OPTION_CODE is option code of opt_code\
+ enum type. PREFIX is used for bash completion and allows an implementation\
+ to return more specific completion based on the prefix. All string values\
+ should be allocated from heap memory and consumers should release them. \
+ The result will be pruned to cases with PREFIX if not NULL.",
+ vec<const char *>, (int option_code, const char *prefix),
+ default_get_valid_option_values)
+
/* Leave the boolean fields at the end. */
/* True if unwinding tables should be generated by default. */
diff --git a/gcc/common/common-targhooks.c b/gcc/common/common-targhooks.c
index b109019..1b1a015 100644
--- a/gcc/common/common-targhooks.c
+++ b/gcc/common/common-targhooks.c
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "tm.h"
#include "common/common-target.h"
#include "common/common-targhooks.h"
+#include "opts.h"
/* Determine the exception handling mechanism for the target. */
@@ -77,6 +78,14 @@ default_target_handle_option (struct gcc_options *opts ATTRIBUTE_UNUSED,
return true;
}
+/* Default version of TARGET_GET_VALID_OPTION_VALUES. */
+
+vec<const char *>
+default_get_valid_option_values (int, const char *)
+{
+ return vec<const char *> ();
+}
+
const struct default_options empty_optimization_table[] =
{
{ OPT_LEVELS_NONE, 0, NULL, 0 }
diff --git a/gcc/common/common-targhooks.h b/gcc/common/common-targhooks.h
index d290d7f..4bdf8ef 100644
--- a/gcc/common/common-targhooks.h
+++ b/gcc/common/common-targhooks.h
@@ -28,6 +28,7 @@ extern bool default_target_handle_option (struct gcc_options *,
struct gcc_options *,
const struct cl_decoded_option *,
location_t);
+extern vec<const char *> default_get_valid_option_values (int, const char *);
extern const struct default_options empty_optimization_table[];
diff --git a/gcc/common/config/csky/csky-common.c b/gcc/common/config/csky/csky-common.c
new file mode 100644
index 0000000..39095bf
--- /dev/null
+++ b/gcc/common/config/csky/csky-common.c
@@ -0,0 +1,42 @@
+/* Common hooks for CSKY.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ Contributed by C-SKY Microsystems and Mentor Graphics.
+
+ 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 "common/common-target.h"
+#include "common/common-target-def.h"
+
+/* Set default optimization options. */
+static const struct default_options csky_option_optimization_table[] =
+ {
+ /* Enable section anchors by default at -O1 or higher. */
+ { OPT_LEVELS_1_PLUS, OPT_fsection_anchors, NULL, 1 },
+ { OPT_LEVELS_NONE, 0, NULL, 0 }
+ };
+
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
+
+#undef TARGET_OPTION_OPTIMIZATION_TABLE
+#define TARGET_OPTION_OPTIMIZATION_TABLE csky_option_optimization_table
+
+struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c
index 70b3c3f..3b5312d 100644
--- a/gcc/common/config/i386/i386-common.c
+++ b/gcc/common/config/i386/i386-common.c
@@ -59,7 +59,7 @@ along with GCC; see the file COPYING3. If not see
#define OPTION_MASK_ISA_FXSR_SET OPTION_MASK_ISA_FXSR
#define OPTION_MASK_ISA_XSAVE_SET OPTION_MASK_ISA_XSAVE
#define OPTION_MASK_ISA_XSAVEOPT_SET \
- (OPTION_MASK_ISA_XSAVEOPT | OPTION_MASK_ISA_XSAVE)
+ (OPTION_MASK_ISA_XSAVEOPT | OPTION_MASK_ISA_XSAVE_SET)
#define OPTION_MASK_ISA_AVX512F_SET \
(OPTION_MASK_ISA_AVX512F | OPTION_MASK_ISA_AVX2_SET)
#define OPTION_MASK_ISA_AVX512CD_SET \
@@ -95,9 +95,9 @@ along with GCC; see the file COPYING3. If not see
#define OPTION_MASK_ISA_PREFETCHWT1_SET OPTION_MASK_ISA_PREFETCHWT1
#define OPTION_MASK_ISA_CLFLUSHOPT_SET OPTION_MASK_ISA_CLFLUSHOPT
#define OPTION_MASK_ISA_XSAVES_SET \
- (OPTION_MASK_ISA_XSAVES | OPTION_MASK_ISA_XSAVE)
+ (OPTION_MASK_ISA_XSAVES | OPTION_MASK_ISA_XSAVE_SET)
#define OPTION_MASK_ISA_XSAVEC_SET \
- (OPTION_MASK_ISA_XSAVEC | OPTION_MASK_ISA_XSAVE)
+ (OPTION_MASK_ISA_XSAVEC | OPTION_MASK_ISA_XSAVE_SET)
#define OPTION_MASK_ISA_CLWB_SET OPTION_MASK_ISA_CLWB
/* SSE4 includes both SSE4.1 and SSE4.2. -msse4 should be the same
@@ -185,7 +185,8 @@ along with GCC; see the file COPYING3. If not see
#define OPTION_MASK_ISA_FMA_UNSET OPTION_MASK_ISA_FMA
#define OPTION_MASK_ISA_FXSR_UNSET OPTION_MASK_ISA_FXSR
#define OPTION_MASK_ISA_XSAVE_UNSET \
- (OPTION_MASK_ISA_XSAVE | OPTION_MASK_ISA_XSAVEOPT_UNSET)
+ (OPTION_MASK_ISA_XSAVE | OPTION_MASK_ISA_XSAVEOPT_UNSET \
+ | OPTION_MASK_ISA_XSAVES_UNSET | OPTION_MASK_ISA_XSAVEC_UNSET)
#define OPTION_MASK_ISA_XSAVEOPT_UNSET OPTION_MASK_ISA_XSAVEOPT
#define OPTION_MASK_ISA_AVX2_UNSET \
(OPTION_MASK_ISA_AVX2 | OPTION_MASK_ISA_AVX512F_UNSET)
@@ -1459,4 +1460,267 @@ i386_except_unwind_info (struct gcc_options *opts)
#undef TARGET_SUPPORTS_SPLIT_STACK
#define TARGET_SUPPORTS_SPLIT_STACK ix86_supports_split_stack
+/* This table must be in sync with enum processor_type in i386.h. */
+const char *const processor_names[PROCESSOR_max] =
+{
+ "generic",
+ "i386",
+ "i486",
+ "pentium",
+ "lakemont",
+ "pentiumpro",
+ "pentium4",
+ "nocona",
+ "core2",
+ "nehalem",
+ "sandybridge",
+ "haswell",
+ "bonnell",
+ "silvermont",
+ "goldmont",
+ "goldmont-plus",
+ "tremont",
+ "knl",
+ "knm",
+ "skylake",
+ "skylake-avx512",
+ "cannonlake",
+ "icelake-client",
+ "icelake-server",
+ "intel",
+ "geode",
+ "k6",
+ "athlon",
+ "k8",
+ "amdfam10",
+ "bdver1",
+ "bdver2",
+ "bdver3",
+ "bdver4",
+ "btver1",
+ "btver2",
+ "znver1"
+};
+
+const pta processor_alias_table[] =
+{
+ {"i386", PROCESSOR_I386, CPU_NONE, 0},
+ {"i486", PROCESSOR_I486, CPU_NONE, 0},
+ {"i586", PROCESSOR_PENTIUM, CPU_PENTIUM, 0},
+ {"pentium", PROCESSOR_PENTIUM, CPU_PENTIUM, 0},
+ {"lakemont", PROCESSOR_LAKEMONT, CPU_PENTIUM, PTA_NO_80387},
+ {"pentium-mmx", PROCESSOR_PENTIUM, CPU_PENTIUM, PTA_MMX},
+ {"winchip-c6", PROCESSOR_I486, CPU_NONE, PTA_MMX},
+ {"winchip2", PROCESSOR_I486, CPU_NONE, PTA_MMX | PTA_3DNOW},
+ {"c3", PROCESSOR_I486, CPU_NONE, PTA_MMX | PTA_3DNOW},
+ {"samuel-2", PROCESSOR_I486, CPU_NONE, PTA_MMX | PTA_3DNOW},
+ {"c3-2", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO,
+ PTA_MMX | PTA_SSE | PTA_FXSR},
+ {"nehemiah", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO,
+ PTA_MMX | PTA_SSE | PTA_FXSR},
+ {"c7", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO,
+ PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_FXSR},
+ {"esther", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO,
+ PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_FXSR},
+ {"i686", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, 0},
+ {"pentiumpro", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, 0},
+ {"pentium2", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, PTA_MMX | PTA_FXSR},
+ {"pentium3", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO,
+ PTA_MMX | PTA_SSE | PTA_FXSR},
+ {"pentium3m", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO,
+ PTA_MMX | PTA_SSE | PTA_FXSR},
+ {"pentium-m", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO,
+ PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_FXSR},
+ {"pentium4", PROCESSOR_PENTIUM4, CPU_NONE,
+ PTA_MMX |PTA_SSE | PTA_SSE2 | PTA_FXSR},
+ {"pentium4m", PROCESSOR_PENTIUM4, CPU_NONE,
+ PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_FXSR},
+ {"prescott", PROCESSOR_NOCONA, CPU_NONE,
+ PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_FXSR},
+ {"nocona", PROCESSOR_NOCONA, CPU_NONE,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+ | PTA_CX16 | PTA_NO_SAHF | PTA_FXSR},
+ {"core2", PROCESSOR_CORE2, CPU_CORE2, PTA_CORE2},
+ {"nehalem", PROCESSOR_NEHALEM, CPU_NEHALEM, PTA_NEHALEM},
+ {"corei7", PROCESSOR_NEHALEM, CPU_NEHALEM, PTA_NEHALEM},
+ {"westmere", PROCESSOR_NEHALEM, CPU_NEHALEM, PTA_WESTMERE},
+ {"sandybridge", PROCESSOR_SANDYBRIDGE, CPU_NEHALEM,
+ PTA_SANDYBRIDGE},
+ {"corei7-avx", PROCESSOR_SANDYBRIDGE, CPU_NEHALEM,
+ PTA_SANDYBRIDGE},
+ {"ivybridge", PROCESSOR_SANDYBRIDGE, CPU_NEHALEM,
+ PTA_IVYBRIDGE},
+ {"core-avx-i", PROCESSOR_SANDYBRIDGE, CPU_NEHALEM,
+ PTA_IVYBRIDGE},
+ {"haswell", PROCESSOR_HASWELL, CPU_HASWELL, PTA_HASWELL},
+ {"core-avx2", PROCESSOR_HASWELL, CPU_HASWELL, PTA_HASWELL},
+ {"broadwell", PROCESSOR_HASWELL, CPU_HASWELL, PTA_BROADWELL},
+ {"skylake", PROCESSOR_SKYLAKE, CPU_HASWELL, PTA_SKYLAKE},
+ {"skylake-avx512", PROCESSOR_SKYLAKE_AVX512, CPU_HASWELL,
+ PTA_SKYLAKE_AVX512},
+ {"cannonlake", PROCESSOR_CANNONLAKE, CPU_HASWELL, PTA_CANNONLAKE},
+ {"icelake-client", PROCESSOR_ICELAKE_CLIENT, CPU_HASWELL,
+ PTA_ICELAKE_CLIENT},
+ {"icelake-server", PROCESSOR_ICELAKE_SERVER, CPU_HASWELL,
+ PTA_ICELAKE_SERVER},
+ {"bonnell", PROCESSOR_BONNELL, CPU_ATOM, PTA_BONNELL},
+ {"atom", PROCESSOR_BONNELL, CPU_ATOM, PTA_BONNELL},
+ {"silvermont", PROCESSOR_SILVERMONT, CPU_SLM, PTA_SILVERMONT},
+ {"slm", PROCESSOR_SILVERMONT, CPU_SLM, PTA_SILVERMONT},
+ {"goldmont", PROCESSOR_GOLDMONT, CPU_GLM, PTA_GOLDMONT},
+ {"goldmont-plus", PROCESSOR_GOLDMONT_PLUS, CPU_GLM, PTA_GOLDMONT_PLUS},
+ {"tremont", PROCESSOR_TREMONT, CPU_GLM, PTA_TREMONT},
+ {"knl", PROCESSOR_KNL, CPU_SLM, PTA_KNL},
+ {"knm", PROCESSOR_KNM, CPU_SLM, PTA_KNM},
+ {"intel", PROCESSOR_INTEL, CPU_SLM, PTA_NEHALEM},
+ {"geode", PROCESSOR_GEODE, CPU_GEODE,
+ PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_PREFETCH_SSE},
+ {"k6", PROCESSOR_K6, CPU_K6, PTA_MMX},
+ {"k6-2", PROCESSOR_K6, CPU_K6, PTA_MMX | PTA_3DNOW},
+ {"k6-3", PROCESSOR_K6, CPU_K6, PTA_MMX | PTA_3DNOW},
+ {"athlon", PROCESSOR_ATHLON, CPU_ATHLON,
+ PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_PREFETCH_SSE},
+ {"athlon-tbird", PROCESSOR_ATHLON, CPU_ATHLON,
+ PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_PREFETCH_SSE},
+ {"athlon-4", PROCESSOR_ATHLON, CPU_ATHLON,
+ PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE | PTA_FXSR},
+ {"athlon-xp", PROCESSOR_ATHLON, CPU_ATHLON,
+ PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE | PTA_FXSR},
+ {"athlon-mp", PROCESSOR_ATHLON, CPU_ATHLON,
+ PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE | PTA_FXSR},
+ {"x86-64", PROCESSOR_K8, CPU_K8,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_NO_SAHF | PTA_FXSR},
+ {"eden-x2", PROCESSOR_K8, CPU_K8,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_FXSR},
+ {"nano", PROCESSOR_K8, CPU_K8,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+ | PTA_SSSE3 | PTA_FXSR},
+ {"nano-1000", PROCESSOR_K8, CPU_K8,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+ | PTA_SSSE3 | PTA_FXSR},
+ {"nano-2000", PROCESSOR_K8, CPU_K8,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+ | PTA_SSSE3 | PTA_FXSR},
+ {"nano-3000", PROCESSOR_K8, CPU_K8,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+ | PTA_SSSE3 | PTA_SSE4_1 | PTA_FXSR},
+ {"nano-x2", PROCESSOR_K8, CPU_K8,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+ | PTA_SSSE3 | PTA_SSE4_1 | PTA_FXSR},
+ {"eden-x4", PROCESSOR_K8, CPU_K8,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+ | PTA_SSSE3 | PTA_SSE4_1 | PTA_FXSR},
+ {"nano-x4", PROCESSOR_K8, CPU_K8,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+ | PTA_SSSE3 | PTA_SSE4_1 | PTA_FXSR},
+ {"k8", PROCESSOR_K8, CPU_K8,
+ PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE
+ | PTA_SSE2 | PTA_NO_SAHF | PTA_FXSR},
+ {"k8-sse3", PROCESSOR_K8, CPU_K8,
+ PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE
+ | PTA_SSE2 | PTA_SSE3 | PTA_NO_SAHF | PTA_FXSR},
+ {"opteron", PROCESSOR_K8, CPU_K8,
+ PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE
+ | PTA_SSE2 | PTA_NO_SAHF | PTA_FXSR},
+ {"opteron-sse3", PROCESSOR_K8, CPU_K8,
+ PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE
+ | PTA_SSE2 | PTA_SSE3 | PTA_NO_SAHF | PTA_FXSR},
+ {"athlon64", PROCESSOR_K8, CPU_K8,
+ PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE
+ | PTA_SSE2 | PTA_NO_SAHF | PTA_FXSR},
+ {"athlon64-sse3", PROCESSOR_K8, CPU_K8,
+ PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE
+ | PTA_SSE2 | PTA_SSE3 | PTA_NO_SAHF | PTA_FXSR},
+ {"athlon-fx", PROCESSOR_K8, CPU_K8,
+ PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE
+ | PTA_SSE2 | PTA_NO_SAHF | PTA_FXSR},
+ {"amdfam10", PROCESSOR_AMDFAM10, CPU_AMDFAM10,
+ PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE | PTA_SSE2
+ | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_PRFCHW | PTA_FXSR},
+ {"barcelona", PROCESSOR_AMDFAM10, CPU_AMDFAM10,
+ PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE | PTA_SSE2
+ | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_PRFCHW | PTA_FXSR},
+ {"bdver1", PROCESSOR_BDVER1, CPU_BDVER1,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+ | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1
+ | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_FMA4
+ | PTA_XOP | PTA_LWP | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE},
+ {"bdver2", PROCESSOR_BDVER2, CPU_BDVER2,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+ | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1
+ | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_FMA4
+ | PTA_XOP | PTA_LWP | PTA_BMI | PTA_TBM | PTA_F16C
+ | PTA_FMA | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE},
+ {"bdver3", PROCESSOR_BDVER3, CPU_BDVER3,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+ | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1
+ | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_FMA4
+ | PTA_XOP | PTA_LWP | PTA_BMI | PTA_TBM | PTA_F16C
+ | PTA_FMA | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE
+ | PTA_XSAVEOPT | PTA_FSGSBASE},
+ {"bdver4", PROCESSOR_BDVER4, CPU_BDVER4,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+ | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1
+ | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_AVX2
+ | PTA_FMA4 | PTA_XOP | PTA_LWP | PTA_BMI | PTA_BMI2
+ | PTA_TBM | PTA_F16C | PTA_FMA | PTA_PRFCHW | PTA_FXSR
+ | PTA_XSAVE | PTA_XSAVEOPT | PTA_FSGSBASE | PTA_RDRND
+ | PTA_MOVBE | PTA_MWAITX},
+ {"znver1", PROCESSOR_ZNVER1, CPU_ZNVER1,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+ | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1
+ | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_AVX2
+ | PTA_BMI | PTA_BMI2 | PTA_F16C | PTA_FMA | PTA_PRFCHW
+ | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT | PTA_FSGSBASE
+ | PTA_RDRND | PTA_MOVBE | PTA_MWAITX | PTA_ADX | PTA_RDSEED
+ | PTA_CLZERO | PTA_CLFLUSHOPT | PTA_XSAVEC | PTA_XSAVES
+ | PTA_SHA | PTA_LZCNT | PTA_POPCNT},
+ {"btver1", PROCESSOR_BTVER1, CPU_GENERIC,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+ | PTA_SSSE3 | PTA_SSE4A |PTA_ABM | PTA_CX16 | PTA_PRFCHW
+ | PTA_FXSR | PTA_XSAVE},
+ {"btver2", PROCESSOR_BTVER2, CPU_BTVER2,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+ | PTA_SSSE3 | PTA_SSE4A |PTA_ABM | PTA_CX16 | PTA_SSE4_1
+ | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX
+ | PTA_BMI | PTA_F16C | PTA_MOVBE | PTA_PRFCHW
+ | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT},
+
+ {"generic", PROCESSOR_GENERIC, CPU_GENERIC,
+ PTA_64BIT
+ | PTA_HLE /* flags are only used for -march switch. */ },
+};
+
+int const pta_size = ARRAY_SIZE (processor_alias_table);
+
+/* Provide valid option values for -march and -mtune options. */
+
+vec<const char *>
+ix86_get_valid_option_values (int option_code,
+ const char *prefix ATTRIBUTE_UNUSED)
+{
+ vec<const char *> v;
+ v.create (0);
+ opt_code opt = (opt_code) option_code;
+
+ switch (opt)
+ {
+ case OPT_march_:
+ for (unsigned i = 0; i < pta_size; i++)
+ v.safe_push (processor_alias_table[i].name);
+ break;
+ case OPT_mtune_:
+ for (unsigned i = 0; i < PROCESSOR_max; i++)
+ v.safe_push (processor_names[i]);
+ break;
+ default:
+ break;
+ }
+
+ return v;
+}
+
+#undef TARGET_GET_VALID_OPTION_VALUES
+#define TARGET_GET_VALID_OPTION_VALUES ix86_get_valid_option_values
+
struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
diff --git a/gcc/common/config/nds32/nds32-common.c b/gcc/common/config/nds32/nds32-common.c
index 197f06c..4823660 100644
--- a/gcc/common/config/nds32/nds32-common.c
+++ b/gcc/common/config/nds32/nds32-common.c
@@ -53,6 +53,16 @@ nds32_handle_option (struct gcc_options *opts ATTRIBUTE_UNUSED,
return true;
+ case OPT_misr_secure_:
+ /* Check the valid security level: 0 1 2 3. */
+ if (value < 0 || value > 3)
+ {
+ error_at (loc, "for the option -misr-secure=X, the valid X "
+ "must be: 0, 1, 2, or 3");
+ return false;
+ }
+ return true;
+
case OPT_mcache_block_size_:
/* Check valid value: 4 8 16 32 64 128 256 512. */
if (exact_log2 (value) < 2 || exact_log2 (value) > 9)
@@ -85,6 +95,8 @@ static const struct default_options nds32_option_optimization_table[] =
{ OPT_LEVELS_ALL, OPT_fomit_frame_pointer, NULL, 1 },
/* Enable -mrelax-hint by default at all optimization levels. */
{ OPT_LEVELS_ALL, OPT_mrelax_hint, NULL, 1 },
+ /* Enalbe -malways-align by default at -O1 and above, but not -Os or -Og. */
+ { OPT_LEVELS_1_PLUS_SPEED_ONLY, OPT_malways_align, NULL, 1 },
/* Enable -mv3push by default at -Os, but it is useless under V2 ISA. */
{ OPT_LEVELS_SIZE, OPT_mv3push, NULL, 1 },
diff --git a/gcc/common/config/nvptx/nvptx-common.c b/gcc/common/config/nvptx/nvptx-common.c
index 27a4f46..3a124e8 100644
--- a/gcc/common/config/nvptx/nvptx-common.c
+++ b/gcc/common/config/nvptx/nvptx-common.c
@@ -30,10 +30,19 @@ along with GCC; see the file COPYING3. If not see
#include "opts.h"
#include "flags.h"
+enum unwind_info_type
+nvptx_except_unwind_info (struct gcc_options *opts ATTRIBUTE_UNUSED)
+{
+ return UI_NONE;
+}
+
#undef TARGET_HAVE_NAMED_SECTIONS
#define TARGET_HAVE_NAMED_SECTIONS false
#undef TARGET_DEFAULT_TARGET_FLAGS
#define TARGET_DEFAULT_TARGET_FLAGS MASK_ABI64
+#undef TARGET_EXCEPT_UNWIND_INFO
+#define TARGET_EXCEPT_UNWIND_INFO nvptx_except_unwind_info
+
struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
diff --git a/gcc/common/config/s390/s390-common.c b/gcc/common/config/s390/s390-common.c
index d38e47f..a56443c 100644
--- a/gcc/common/config/s390/s390-common.c
+++ b/gcc/common/config/s390/s390-common.c
@@ -29,8 +29,6 @@ along with GCC; see the file COPYING3. If not see
EXPORTED_CONST int processor_flags_table[] =
{
- /* g5 */ PF_IEEE_FLOAT,
- /* g6 */ PF_IEEE_FLOAT,
/* z900 */ PF_IEEE_FLOAT | PF_ZARCH,
/* z990 */ PF_IEEE_FLOAT | PF_ZARCH | PF_LONG_DISPLACEMENT,
/* z9-109 */ PF_IEEE_FLOAT | PF_ZARCH | PF_LONG_DISPLACEMENT
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 78e84c2..0c579d1 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -304,7 +304,7 @@ aarch64*-*-*)
extra_headers="arm_fp16.h arm_neon.h arm_acle.h"
c_target_objs="aarch64-c.o"
cxx_target_objs="aarch64-c.o"
- extra_objs="aarch64-builtins.o aarch-common.o cortex-a57-fma-steering.o"
+ extra_objs="aarch64-builtins.o aarch-common.o cortex-a57-fma-steering.o aarch64-speculation.o falkor-tag-collision-avoidance.o"
target_gtfiles="\$(srcdir)/config/aarch64/aarch64-builtins.c"
target_has_targetm_common=yes
;;
@@ -447,7 +447,7 @@ mips*-*-*)
;;
nds32*)
cpu_type=nds32
- extra_headers="nds32_intrinsic.h"
+ extra_headers="nds32_intrinsic.h nds32_isr.h nds32_init.inc"
case ${target} in
nds32*-*-linux*)
extra_options="${extra_options} nds32/nds32-linux.opt"
@@ -588,7 +588,6 @@ i[34567]86-*-*)
if test "x$enable_frame_pointer" = xyes; then
tm_defines="${tm_defines} USE_IX86_FRAME_POINTER=1"
fi
- tm_file="vxworks-dummy.h ${tm_file}"
;;
x86_64-*-*)
case ${with_abi} in
@@ -615,14 +614,9 @@ x86_64-*-*)
if test "x$enable_frame_pointer" = xyes; then
tm_defines="${tm_defines} USE_IX86_FRAME_POINTER=1"
fi
- tm_file="vxworks-dummy.h ${tm_file}"
;;
arm*-*-*)
tm_p_file="arm/arm-flags.h ${tm_p_file} arm/aarch-common-protos.h"
- tm_file="vxworks-dummy.h ${tm_file}"
- ;;
-mips*-*-* | sh*-*-* | sparc*-*-*)
- tm_file="vxworks-dummy.h ${tm_file}"
;;
esac
@@ -941,6 +935,11 @@ case ${target} in
tm_defines="$tm_defines TARGET_VXWORKS7=1"
;;
esac
+ case $target in
+ *64-*-vxworks*)
+ tm_defines="$tm_defines TARGET_VXWORKS64=1"
+ ;;
+ esac
;;
*-*-elf|arc*-*-elf*)
# Assume that newlib is being used and so __cxa_atexit is provided.
@@ -1144,7 +1143,7 @@ arm*-*-linux-*) # ARM GNU/Linux with ELF
;;
esac
tmake_file="${tmake_file} arm/t-arm arm/t-arm-elf arm/t-bpabi arm/t-linux-eabi"
- tm_file="$tm_file arm/bpabi.h arm/linux-eabi.h arm/aout.h vxworks-dummy.h arm/arm.h"
+ tm_file="$tm_file arm/bpabi.h arm/linux-eabi.h arm/aout.h arm/arm.h"
# Generation of floating-point instructions requires at least ARMv5te.
if [ "$with_float" = "hard" -o "$with_float" = "softfp" ] ; then
target_cpu_cname="arm10e"
@@ -1164,7 +1163,7 @@ arm*-*-linux-*) # ARM GNU/Linux with ELF
arm*-*-uclinux*eabi*) # ARM ucLinux
tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/linux-gas.h arm/uclinux-elf.h glibc-stdint.h"
tmake_file="${tmake_file} arm/t-arm arm/t-arm-elf arm/t-bpabi"
- tm_file="$tm_file arm/bpabi.h arm/uclinux-eabi.h arm/aout.h vxworks-dummy.h arm/arm.h"
+ tm_file="$tm_file arm/bpabi.h arm/uclinux-eabi.h arm/aout.h arm/arm.h"
target_cpu_cname="arm7tdmi"
# The EABI requires the use of __cxa_atexit.
default_use_cxa_atexit=yes
@@ -1208,7 +1207,7 @@ arm*-*-eabi* | arm*-*-symbianelf* | arm*-*-rtems* | arm*-*-fuchsia*)
target_cpu_cname="arm10tdmi"
;;
esac
- tm_file="${tm_file} arm/aout.h vxworks-dummy.h arm/arm.h"
+ tm_file="${tm_file} arm/aout.h arm/arm.h"
;;
avr-*-*)
tm_file="elfos.h avr/elf.h avr/avr-arch.h avr/avr.h avr/specs.h dbxelf.h avr/avr-stdint.h"
@@ -1278,6 +1277,70 @@ crisv32-*-linux* | cris-*-linux*)
;;
esac
;;
+csky-*-*)
+ if test x${with_endian} != x; then
+ case ${with_endian} in
+ big|little) ;;
+ *)
+ echo "with_endian=${with_endian} not supported."
+ exit 1
+ ;;
+ esac
+ fi
+ if test x${with_float} != x; then
+ case ${with_float} in
+ soft | hard) ;;
+ *) echo
+ "Unknown floating point type used in --with-float=$with_float"
+ exit 1
+ ;;
+ esac
+ fi
+ tm_file="csky/csky.h"
+ md_file="csky/csky.md"
+ out_file="csky/csky.c"
+ tm_p_file="${tm_p_file} csky/csky-protos.h"
+ extra_options="${extra_options} csky/csky_tables.opt"
+
+ if test x${enable_tpf_debug} = xyes; then
+ tm_defines="${tm_defines} ENABLE_TPF_DEBUG"
+ fi
+
+ case ${target} in
+ csky-*-elf*)
+ tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file} csky/csky-elf.h"
+ tmake_file="csky/t-csky csky/t-csky-elf"
+ default_use_cxa_atexit=no
+ ;;
+ csky-*-linux*)
+ tm_file="dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h ${tm_file} csky/csky-linux-elf.h"
+ tmake_file="${tmake_file} csky/t-csky csky/t-csky-linux"
+
+ if test "x${enable_multilib}" = xyes ; then
+ tm_file="$tm_file ./sysroot-suffix.h"
+ tmake_file="${tmake_file} csky/t-sysroot-suffix"
+ fi
+
+ case ${target} in
+ csky-*-linux-gnu*)
+ tm_defines="$tm_defines DEFAULT_LIBC=LIBC_GLIBC"
+ ;;
+ csky-*-linux-uclibc*)
+ tm_defines="$tm_defines DEFAULT_LIBC=LIBC_UCLIBC"
+ default_use_cxa_atexit=no
+ ;;
+ *)
+ echo "Unknown target $target"
+ exit 1
+ ;;
+ esac
+ ;;
+ *)
+ echo "Unknown target $target"
+ exit 1
+ ;;
+ esac
+ ;;
epiphany-*-elf | epiphany-*-rtems*)
tm_file="${tm_file} dbxelf.h elfos.h"
tmake_file="${tmake_file} epiphany/t-epiphany"
@@ -2635,42 +2698,6 @@ powerpcle-*-eabi*)
extra_options="${extra_options} rs6000/sysv4.opt"
use_gcc_stdint=wrap
;;
-rs6000-ibm-aix4.[3456789]* | powerpc-ibm-aix4.[3456789]*)
- tm_file="rs6000/biarch64.h ${tm_file} rs6000/aix.h rs6000/aix43.h rs6000/xcoff.h rs6000/aix-stdint.h"
- tmake_file="rs6000/t-aix43 t-slibgcc"
- extra_options="${extra_options} rs6000/aix64.opt"
- use_collect2=yes
- thread_file='aix'
- use_gcc_stdint=provide
- extra_headers=
- ;;
-rs6000-ibm-aix5.1.* | powerpc-ibm-aix5.1.*)
- tm_file="rs6000/biarch64.h ${tm_file} rs6000/aix.h rs6000/aix51.h rs6000/xcoff.h rs6000/aix-stdint.h"
- extra_options="${extra_options} rs6000/aix64.opt"
- tmake_file="rs6000/t-aix43 t-slibgcc"
- use_collect2=yes
- thread_file='aix'
- use_gcc_stdint=wrap
- extra_headers=
- ;;
-rs6000-ibm-aix5.2.* | powerpc-ibm-aix5.2.*)
- tm_file="${tm_file} rs6000/aix.h rs6000/aix52.h rs6000/xcoff.h rs6000/aix-stdint.h"
- tmake_file="rs6000/t-aix52 t-slibgcc"
- extra_options="${extra_options} rs6000/aix64.opt"
- use_collect2=yes
- thread_file='aix'
- use_gcc_stdint=wrap
- extra_headers=
- ;;
-rs6000-ibm-aix5.3.* | powerpc-ibm-aix5.3.*)
- tm_file="${tm_file} rs6000/aix.h rs6000/aix53.h rs6000/xcoff.h rs6000/aix-stdint.h"
- tmake_file="rs6000/t-aix52 t-slibgcc"
- extra_options="${extra_options} rs6000/aix64.opt"
- use_collect2=yes
- thread_file='aix'
- use_gcc_stdint=wrap
- extra_headers=altivec.h
- ;;
rs6000-ibm-aix6.* | powerpc-ibm-aix6.*)
tm_file="${tm_file} rs6000/aix.h rs6000/aix61.h rs6000/xcoff.h rs6000/aix-stdint.h"
tmake_file="rs6000/t-aix52 t-slibgcc"
@@ -3831,6 +3858,10 @@ case "${target}" in
fi
;;
+ csky-*-*)
+ supported_defaults="cpu endian float"
+ ;;
+
arm*-*-*)
supported_defaults="arch cpu float tune fpu abi mode tls"
for which in cpu tune arch; do
@@ -4422,7 +4453,7 @@ case "${target}" in
;;
glibc)
# OK
- tm_defines="${tm_defines} TARGET_DEFAULT_TLSDESC_TRAMPOLINE=1"
+ tm_defines="${tm_defines} TARGET_DEFAULT_TLSDESC_TRAMPOLINE=0"
;;
uclibc)
;;
@@ -4574,7 +4605,7 @@ case "${target}" in
for which in arch tune; do
eval "val=\$with_$which"
case ${val} in
- "" | native | g5 | g6 | z900 | z990 | z9-109 | z9-ec | z10 | z196 | zEC12 | z13 | z14 | arch3 | arch5 | arch6 | arch7 | arch8 | arch9 | arch10 | arch11 | arch12)
+ "" | native | z900 | z990 | z9-109 | z9-ec | z10 | z196 | zEC12 | z13 | z14 | arch5 | arch6 | arch7 | arch8 | arch9 | arch10 | arch11 | arch12)
# OK
;;
*)
@@ -4702,6 +4733,18 @@ case "${target}" in
;;
esac
+# Targets for which there is at least one VxWorks port should include
+# vxworks-dummy.h to allow safe references to various TARGET_VXWORKS kinds
+# of markers from other files in the port, including the vxworks*.h files to
+# distinguish VxWorks variants such as VxWorks 7 or 64).
+
+case ${target} in
+arm*-*-* | i[34567]86-*-* | mips*-*-* | powerpc*-*-* | sh*-*-* \
+| sparc*-*-* | x86_64-*-*)
+ tm_file="vxworks-dummy.h ${tm_file}"
+ ;;
+esac
+
# Set some miscellaneous flags for particular targets.
target_cpu_default2=
case ${target} in
diff --git a/gcc/config.in b/gcc/config.in
index 2856e72..775536e 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1297,6 +1297,12 @@
#endif
+/* Define if your assembler supports the .loc is_stmt sub-directive. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_LOC_STMT
+#endif
+
+
/* Define if your assembler supports specifying the maximum number of bytes to
skip when using the GAS .p2align command. */
#ifndef USED_FOR_TARGET
diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 02c6738..8cced94 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -643,6 +643,10 @@ aarch64_init_simd_builtin_types (void)
/* Poly types are a world of their own. */
aarch64_simd_types[Poly8_t].eltype = aarch64_simd_types[Poly8_t].itype =
build_distinct_type_copy (unsigned_intQI_type_node);
+ /* Prevent front-ends from transforming Poly8_t arrays into string
+ literals. */
+ TYPE_STRING_FLAG (aarch64_simd_types[Poly8_t].eltype) = false;
+
aarch64_simd_types[Poly16_t].eltype = aarch64_simd_types[Poly16_t].itype =
build_distinct_type_copy (unsigned_intHI_type_node);
aarch64_simd_types[Poly64_t].eltype = aarch64_simd_types[Poly64_t].itype =
diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
index 3d876b8..b1278fc 100644
--- a/gcc/config/aarch64/aarch64-cores.def
+++ b/gcc/config/aarch64/aarch64-cores.def
@@ -71,6 +71,9 @@ AARCH64_CORE("qdf24xx", qdf24xx, falkor, 8A, AARCH64_FL_FOR_ARCH8 | AA
/* Samsung ('S') cores. */
AARCH64_CORE("exynos-m1", exynosm1, exynosm1, 8A, AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, exynosm1, 0x53, 0x001, -1)
+/* HXT ('h') cores. */
+AARCH64_CORE("phecda", phecda, falkor, 8A, AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, qdf24xx, 0x68, 0x000, -1)
+
/* ARMv8.1-A Architecture Processors. */
/* Broadcom ('B') cores. */
@@ -89,6 +92,9 @@ AARCH64_CORE("cortex-a76", cortexa76, cortexa57, 8_2A, AARCH64_FL_FOR_ARCH8_2
/* ARMv8.4-A Architecture Processors. */
+/* HiSilicon ('H') cores. */
+AARCH64_CORE("tsv110", tsv110, cortexa57, 8_4A, AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_CRYPTO | AARCH64_FL_F16 | AARCH64_FL_AES | AARCH64_FL_SHA2, tsv110, 0x48, 0xd01, -1)
+
/* Qualcomm ('Q') cores. */
AARCH64_CORE("saphira", saphira, falkor, 8_4A, AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_CRYPTO | AARCH64_FL_RCPC, saphira, 0x51, 0xC01, -1)
diff --git a/gcc/config/aarch64/aarch64-cost-tables.h b/gcc/config/aarch64/aarch64-cost-tables.h
index a455c62..b138aa3 100644
--- a/gcc/config/aarch64/aarch64-cost-tables.h
+++ b/gcc/config/aarch64/aarch64-cost-tables.h
@@ -334,4 +334,108 @@ const struct cpu_cost_table thunderx2t99_extra_costs =
}
};
+const struct cpu_cost_table tsv110_extra_costs =
+{
+ /* ALU */
+ {
+ 0, /* arith. */
+ 0, /* logical. */
+ 0, /* shift. */
+ 0, /* shift_reg. */
+ COSTS_N_INSNS (1), /* arith_shift. */
+ COSTS_N_INSNS (1), /* arith_shift_reg. */
+ COSTS_N_INSNS (1), /* log_shift. */
+ COSTS_N_INSNS (1), /* log_shift_reg. */
+ 0, /* extend. */
+ COSTS_N_INSNS (1), /* extend_arith. */
+ 0, /* bfi. */
+ 0, /* bfx. */
+ 0, /* clz. */
+ 0, /* rev. */
+ 0, /* non_exec. */
+ true /* non_exec_costs_exec. */
+ },
+
+ {
+ /* MULT SImode */
+ {
+ COSTS_N_INSNS (2), /* simple. */
+ COSTS_N_INSNS (2), /* flag_setting. */
+ COSTS_N_INSNS (2), /* extend. */
+ COSTS_N_INSNS (2), /* add. */
+ COSTS_N_INSNS (2), /* extend_add. */
+ COSTS_N_INSNS (11) /* idiv. */
+ },
+ /* MULT DImode */
+ {
+ COSTS_N_INSNS (3), /* simple. */
+ 0, /* flag_setting (N/A). */
+ COSTS_N_INSNS (3), /* extend. */
+ COSTS_N_INSNS (3), /* add. */
+ COSTS_N_INSNS (3), /* extend_add. */
+ COSTS_N_INSNS (19) /* idiv. */
+ }
+ },
+ /* LD/ST */
+ {
+ COSTS_N_INSNS (3), /* load. */
+ COSTS_N_INSNS (4), /* load_sign_extend. */
+ COSTS_N_INSNS (3), /* ldrd. */
+ COSTS_N_INSNS (3), /* ldm_1st. */
+ 1, /* ldm_regs_per_insn_1st. */
+ 2, /* ldm_regs_per_insn_subsequent. */
+ COSTS_N_INSNS (4), /* loadf. */
+ COSTS_N_INSNS (4), /* loadd. */
+ COSTS_N_INSNS (4), /* load_unaligned. */
+ 0, /* store. */
+ 0, /* strd. */
+ 0, /* stm_1st. */
+ 1, /* stm_regs_per_insn_1st. */
+ 2, /* stm_regs_per_insn_subsequent. */
+ 0, /* storef. */
+ 0, /* stored. */
+ COSTS_N_INSNS (1), /* store_unaligned. */
+ COSTS_N_INSNS (4), /* loadv. */
+ COSTS_N_INSNS (4) /* storev. */
+ },
+ {
+ /* FP SFmode */
+ {
+ COSTS_N_INSNS (10), /* div. */
+ COSTS_N_INSNS (4), /* mult. */
+ COSTS_N_INSNS (4), /* mult_addsub. */
+ COSTS_N_INSNS (4), /* fma. */
+ COSTS_N_INSNS (4), /* addsub. */
+ COSTS_N_INSNS (1), /* fpconst. */
+ COSTS_N_INSNS (1), /* neg. */
+ COSTS_N_INSNS (1), /* compare. */
+ COSTS_N_INSNS (2), /* widen. */
+ COSTS_N_INSNS (2), /* narrow. */
+ COSTS_N_INSNS (2), /* toint. */
+ COSTS_N_INSNS (1), /* fromint. */
+ COSTS_N_INSNS (2) /* roundint. */
+ },
+ /* FP DFmode */
+ {
+ COSTS_N_INSNS (17), /* div. */
+ COSTS_N_INSNS (4), /* mult. */
+ COSTS_N_INSNS (6), /* mult_addsub. */
+ COSTS_N_INSNS (6), /* fma. */
+ COSTS_N_INSNS (3), /* addsub. */
+ COSTS_N_INSNS (1), /* fpconst. */
+ COSTS_N_INSNS (1), /* neg. */
+ COSTS_N_INSNS (1), /* compare. */
+ COSTS_N_INSNS (2), /* widen. */
+ COSTS_N_INSNS (2), /* narrow. */
+ COSTS_N_INSNS (2), /* toint. */
+ COSTS_N_INSNS (1), /* fromint. */
+ COSTS_N_INSNS (2) /* roundint. */
+ }
+ },
+ /* Vector */
+ {
+ COSTS_N_INSNS (1) /* alu. */
+ }
+};
+
#endif
diff --git a/gcc/config/aarch64/aarch64-passes.def b/gcc/config/aarch64/aarch64-passes.def
index 87747b4..3982b6e 100644
--- a/gcc/config/aarch64/aarch64-passes.def
+++ b/gcc/config/aarch64/aarch64-passes.def
@@ -19,3 +19,5 @@
<http://www.gnu.org/licenses/>. */
INSERT_PASS_AFTER (pass_regrename, 1, pass_fma_steering);
+INSERT_PASS_BEFORE (pass_reorder_blocks, 1, pass_track_speculation);
+INSERT_PASS_AFTER (pass_machine_reorg, 1, pass_tag_collision_avoidance);
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index af5db9c..caf1d20 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -288,6 +288,49 @@ struct tune_params
const struct cpu_prefetch_tune *prefetch;
};
+/* Classifies an address.
+
+ ADDRESS_REG_IMM
+ A simple base register plus immediate offset.
+
+ ADDRESS_REG_WB
+ A base register indexed by immediate offset with writeback.
+
+ ADDRESS_REG_REG
+ A base register indexed by (optionally scaled) register.
+
+ ADDRESS_REG_UXTW
+ A base register indexed by (optionally scaled) zero-extended register.
+
+ ADDRESS_REG_SXTW
+ A base register indexed by (optionally scaled) sign-extended register.
+
+ ADDRESS_LO_SUM
+ A LO_SUM rtx with a base register and "LO12" symbol relocation.
+
+ ADDRESS_SYMBOLIC:
+ A constant symbolic address, in pc-relative literal pool. */
+
+enum aarch64_address_type {
+ ADDRESS_REG_IMM,
+ ADDRESS_REG_WB,
+ ADDRESS_REG_REG,
+ ADDRESS_REG_UXTW,
+ ADDRESS_REG_SXTW,
+ ADDRESS_LO_SUM,
+ ADDRESS_SYMBOLIC
+};
+
+/* Address information. */
+struct aarch64_address_info {
+ enum aarch64_address_type type;
+ rtx base;
+ rtx offset;
+ poly_int64 const_offset;
+ int shift;
+ enum aarch64_symbol_type symbol_type;
+};
+
#define AARCH64_FUSION_PAIR(x, name) \
AARCH64_FUSE_##name##_index,
/* Supported fusion operations. */
@@ -393,6 +436,7 @@ void aarch64_split_add_offset (scalar_int_mode, rtx, rtx, rtx, rtx, rtx);
bool aarch64_mov_operand_p (rtx, machine_mode);
rtx aarch64_reverse_mask (machine_mode, unsigned int);
bool aarch64_offset_7bit_signed_scaled_p (machine_mode, poly_int64);
+bool aarch64_offset_9bit_signed_unscaled_p (machine_mode, poly_int64);
char *aarch64_output_sve_cnt_immediate (const char *, const char *, rtx);
char *aarch64_output_sve_addvl_addpl (rtx, rtx, rtx);
char *aarch64_output_sve_inc_dec_immediate (const char *, rtx);
@@ -561,6 +605,11 @@ void aarch64_swap_ldrstr_operands (rtx *, bool);
extern void aarch64_asm_output_pool_epilogue (FILE *, const char *,
tree, HOST_WIDE_INT);
+
+extern bool aarch64_classify_address (struct aarch64_address_info *, rtx,
+ machine_mode, bool,
+ aarch64_addr_query_type = ADDR_QUERY_M);
+
/* Defined in common/config/aarch64-common.c. */
bool aarch64_handle_option (struct gcc_options *, struct gcc_options *,
const struct cl_decoded_option *, location_t);
@@ -570,8 +619,12 @@ enum aarch64_parse_opt_result aarch64_parse_extension (const char *,
std::string aarch64_get_extension_string_for_isa_flags (unsigned long,
unsigned long);
-rtl_opt_pass *make_pass_fma_steering (gcc::context *ctxt);
+rtl_opt_pass *make_pass_fma_steering (gcc::context *);
+rtl_opt_pass *make_pass_track_speculation (gcc::context *);
+rtl_opt_pass *make_pass_tag_collision_avoidance (gcc::context *);
poly_uint64 aarch64_regmode_natural_size (machine_mode);
+bool aarch64_high_bits_all_ones_p (HOST_WIDE_INT);
+
#endif /* GCC_AARCH64_PROTOS_H */
diff --git a/gcc/config/aarch64/aarch64-simd-builtins.def b/gcc/config/aarch64/aarch64-simd-builtins.def
index c4a5d0d..980c903 100644
--- a/gcc/config/aarch64/aarch64-simd-builtins.def
+++ b/gcc/config/aarch64/aarch64-simd-builtins.def
@@ -413,8 +413,6 @@
BUILTIN_VALL (BINOP, trn1, 0)
BUILTIN_VALL (BINOP, trn2, 0)
- /* Implemented by
- aarch64_frecp<FRECP:frecp_suffix><mode>. */
BUILTIN_GPF_F16 (UNOP, frecpe, 0)
BUILTIN_GPF_F16 (UNOP, frecpx, 0)
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index 9ee9bbe..c4be310 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -257,7 +257,7 @@
DONE;
})
-(define_expand "aarch64_split_simd_mov<mode>"
+(define_expand "@aarch64_split_simd_mov<mode>"
[(set (match_operand:VQ 0)
(match_operand:VQ 1))]
"TARGET_SIMD"
@@ -559,7 +559,7 @@
[(set_attr "type" "neon<fp>_mul_<stype>_scalar<q>")]
)
-(define_insn "aarch64_rsqrte<mode>"
+(define_insn "@aarch64_rsqrte<mode>"
[(set (match_operand:VHSDF_HSDF 0 "register_operand" "=w")
(unspec:VHSDF_HSDF [(match_operand:VHSDF_HSDF 1 "register_operand" "w")]
UNSPEC_RSQRTE))]
@@ -567,7 +567,7 @@
"frsqrte\\t%<v>0<Vmtype>, %<v>1<Vmtype>"
[(set_attr "type" "neon_fp_rsqrte_<stype><q>")])
-(define_insn "aarch64_rsqrts<mode>"
+(define_insn "@aarch64_rsqrts<mode>"
[(set (match_operand:VHSDF_HSDF 0 "register_operand" "=w")
(unspec:VHSDF_HSDF [(match_operand:VHSDF_HSDF 1 "register_operand" "w")
(match_operand:VHSDF_HSDF 2 "register_operand" "w")]
@@ -1352,9 +1352,8 @@
fmov\\t%d0, %1
dup\\t%d0, %1"
[(set_attr "type" "neon_dup<q>,f_mcr,neon_dup<q>")
- (set_attr "simd" "yes,*,yes")
- (set_attr "fp" "*,yes,*")
- (set_attr "length" "4")]
+ (set_attr "length" "4")
+ (set_attr "arch" "simd,fp,simd")]
)
(define_insn "move_lo_quad_internal_<mode>"
@@ -1368,9 +1367,8 @@
fmov\\t%d0, %1
dup\\t%d0, %1"
[(set_attr "type" "neon_dup<q>,f_mcr,neon_dup<q>")
- (set_attr "simd" "yes,*,yes")
- (set_attr "fp" "*,yes,*")
- (set_attr "length" "4")]
+ (set_attr "length" "4")
+ (set_attr "arch" "simd,fp,simd")]
)
(define_insn "move_lo_quad_internal_be_<mode>"
@@ -1384,9 +1382,8 @@
fmov\\t%d0, %1
dup\\t%d0, %1"
[(set_attr "type" "neon_dup<q>,f_mcr,neon_dup<q>")
- (set_attr "simd" "yes,*,yes")
- (set_attr "fp" "*,yes,*")
- (set_attr "length" "4")]
+ (set_attr "length" "4")
+ (set_attr "arch" "simd,fp,simd")]
)
(define_insn "move_lo_quad_internal_be_<mode>"
@@ -1400,9 +1397,8 @@
fmov\\t%d0, %1
dup\\t%d0, %1"
[(set_attr "type" "neon_dup<q>,f_mcr,neon_dup<q>")
- (set_attr "simd" "yes,*,yes")
- (set_attr "fp" "*,yes,*")
- (set_attr "length" "4")]
+ (set_attr "length" "4")
+ (set_attr "arch" "simd,fp,simd")]
)
(define_expand "move_lo_quad_<mode>"
@@ -3030,21 +3026,22 @@
operands[2] = aarch64_endian_lane_rtx (<MODE>mode, INTVAL (operands[2]));
return "smov\\t%<GPI:w>0, %1.<VDQQH:Vetype>[%2]";
}
- [(set_attr "type" "neon_to_gp<q>")]
-)
-
-(define_insn "*aarch64_get_lane_zero_extendsi<mode>"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (zero_extend:SI
- (vec_select:<VEL>
- (match_operand:VDQQH 1 "register_operand" "w")
- (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
- "TARGET_SIMD"
- {
- operands[2] = aarch64_endian_lane_rtx (<MODE>mode, INTVAL (operands[2]));
- return "umov\\t%w0, %1.<Vetype>[%2]";
- }
- [(set_attr "type" "neon_to_gp<q>")]
+ [(set_attr "type" "neon_to_gp<q>")]
+)
+
+(define_insn "*aarch64_get_lane_zero_extend<GPI:mode><VDQQH:mode>"
+ [(set (match_operand:GPI 0 "register_operand" "=r")
+ (zero_extend:GPI
+ (vec_select:<VEL>
+ (match_operand:VDQQH 1 "register_operand" "w")
+ (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
+ "TARGET_SIMD"
+ {
+ operands[2] = aarch64_endian_lane_rtx (<VDQQH:MODE>mode,
+ INTVAL (operands[2]));
+ return "umov\\t%w0, %1.<Vetype>[%2]";
+ }
+ [(set_attr "type" "neon_to_gp<q>")]
)
;; Lane extraction of a value, neither sign nor zero extension
@@ -3113,8 +3110,7 @@
fmov\t%d0, %1
ldr\\t%d0, %1"
[(set_attr "type" "neon_move<q>, neon_from_gp, neon_load1_1reg")
- (set_attr "simd" "yes,*,yes")
- (set_attr "fp" "*,yes,*")]
+ (set_attr "arch" "simd,fp,simd")]
)
(define_insn "*aarch64_combinez_be<mode>"
@@ -3128,8 +3124,7 @@
fmov\t%d0, %1
ldr\\t%d0, %1"
[(set_attr "type" "neon_move<q>, neon_from_gp, neon_load1_1reg")
- (set_attr "simd" "yes,*,yes")
- (set_attr "fp" "*,yes,*")]
+ (set_attr "arch" "simd,fp,simd")]
)
(define_expand "aarch64_combine<mode>"
@@ -3144,7 +3139,7 @@
}
)
-(define_expand "aarch64_simd_combine<mode>"
+(define_expand "@aarch64_simd_combine<mode>"
[(match_operand:<VDBL> 0 "register_operand")
(match_operand:VDC 1 "register_operand")
(match_operand:VDC 2 "register_operand")]
@@ -5877,25 +5872,26 @@
)
-(define_insn "aarch64_frecpe<mode>"
- [(set (match_operand:VHSDF 0 "register_operand" "=w")
- (unspec:VHSDF [(match_operand:VHSDF 1 "register_operand" "w")]
+(define_insn "@aarch64_frecpe<mode>"
+ [(set (match_operand:VHSDF_HSDF 0 "register_operand" "=w")
+ (unspec:VHSDF_HSDF
+ [(match_operand:VHSDF_HSDF 1 "register_operand" "w")]
UNSPEC_FRECPE))]
"TARGET_SIMD"
- "frecpe\\t%0.<Vtype>, %1.<Vtype>"
+ "frecpe\t%<v>0<Vmtype>, %<v>1<Vmtype>"
[(set_attr "type" "neon_fp_recpe_<stype><q>")]
)
-(define_insn "aarch64_frecp<FRECP:frecp_suffix><mode>"
+(define_insn "aarch64_frecpx<mode>"
[(set (match_operand:GPF_F16 0 "register_operand" "=w")
(unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
- FRECP))]
+ UNSPEC_FRECPX))]
"TARGET_SIMD"
- "frecp<FRECP:frecp_suffix>\\t%<s>0, %<s>1"
- [(set_attr "type" "neon_fp_recp<FRECP:frecp_suffix>_<GPF_F16:stype>")]
+ "frecpx\t%<s>0, %<s>1"
+ [(set_attr "type" "neon_fp_recpx_<GPF_F16:stype>")]
)
-(define_insn "aarch64_frecps<mode>"
+(define_insn "@aarch64_frecps<mode>"
[(set (match_operand:VHSDF_HSDF 0 "register_operand" "=w")
(unspec:VHSDF_HSDF
[(match_operand:VHSDF_HSDF 1 "register_operand" "w")
diff --git a/gcc/config/aarch64/aarch64-speculation.cc b/gcc/config/aarch64/aarch64-speculation.cc
new file mode 100644
index 0000000..3cd9ba0
--- /dev/null
+++ b/gcc/config/aarch64/aarch64-speculation.cc
@@ -0,0 +1,494 @@
+/* Speculation tracking and mitigation (e.g. CVE 2017-5753) for AArch64.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ 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 "target.h"
+#include "rtl.h"
+#include "tree-pass.h"
+#include "profile-count.h"
+#include "backend.h"
+#include "cfgbuild.h"
+#include "print-rtl.h"
+#include "cfgrtl.h"
+#include "function.h"
+#include "basic-block.h"
+#include "memmodel.h"
+#include "emit-rtl.h"
+#include "insn-attr.h"
+#include "df.h"
+#include "tm_p.h"
+#include "insn-config.h"
+#include "recog.h"
+
+/* This pass scans the RTL just before the final branch
+ re-organisation pass. The aim is to identify all places where
+ there is conditional control flow and to insert code that tracks
+ any speculative execution of a conditional branch.
+
+ To do this we reserve a call-clobbered register (so that it can be
+ initialized very early in the function prologue) that can then be
+ updated each time there is a conditional branch. At each such
+ branch we then generate a code sequence that uses conditional
+ select operations that are not subject to speculation themselves
+ (we ignore for the moment situations where that might not always be
+ strictly true). For example, a branch sequence such as:
+
+ B.EQ <dst>
+ ...
+ <dst>:
+
+ is transformed to:
+
+ B.EQ <dst>
+ CSEL tracker, tracker, XZr, ne
+ ...
+ <dst>:
+ CSEL tracker, tracker, XZr, eq
+
+ Since we start with the tracker initialized to all bits one, if at any
+ time the predicted control flow diverges from the architectural program
+ behavior, then the tracker will become zero (but not otherwise).
+
+ The tracker value can be used at any time at which a value needs
+ guarding against incorrect speculation. This can be done in
+ several ways, but they all amount to the same thing. For an
+ untrusted address, or an untrusted offset to a trusted address, we
+ can simply mask the address with the tracker with the untrusted
+ value. If the CPU is not speculating, or speculating correctly,
+ then the value will remain unchanged, otherwise it will be clamped
+ to zero. For more complex scenarios we can compare the tracker
+ against zero and use the flags to form a new selection with an
+ alternate safe value.
+
+ On implementations where the data processing instructions may
+ themselves produce speculative values, the architecture requires
+ that a CSDB instruction will resolve such data speculation, so each
+ time we use the tracker for protecting a vulnerable value we also
+ emit a CSDB: we do not need to do that each time the tracker itself
+ is updated.
+
+ At function boundaries, we need to communicate the speculation
+ tracking state with the caller or the callee. This is tricky
+ because there is no register available for such a purpose without
+ creating a new ABI. We deal with this by relying on the principle
+ that in all real programs the stack pointer, SP will never be NULL
+ at a function boundary; we can thus encode the speculation state in
+ SP by clearing SP if the speculation tracker itself is NULL. After
+ the call we recover the tracking state back from SP into the
+ tracker register. The results is that a function call sequence is
+ transformed to
+
+ MOV tmp, SP
+ AND tmp, tmp, tracker
+ MOV SP, tmp
+ BL <callee>
+ CMP SP, #0
+ CSETM tracker, ne
+
+ The additional MOV instructions in the pre-call sequence are needed
+ because SP cannot be used directly with the AND instruction.
+
+ The code inside a function body uses the post-call sequence in the
+ prologue to establish the tracker and the pre-call sequence in the
+ epilogue to re-encode the state for the return.
+
+ The code sequences have the nice property that if called from, or
+ calling a function that does not track speculation then the stack pointer
+ will always be non-NULL and hence the tracker will be initialized to all
+ bits one as we need: we lose the ability to fully track speculation in that
+ case, but we are still architecturally safe.
+
+ Tracking speculation in this way is quite expensive, both in code
+ size and execution time. We employ a number of tricks to try to
+ limit this:
+
+ 1) Simple leaf functions with no conditional branches (or use of
+ the tracker) do not need to establish a new tracker: they simply
+ carry the tracking state through SP for the duration of the call.
+ The same is also true for leaf functions that end in a tail-call.
+
+ 2) Back-to-back function calls in a single basic block also do not
+ need to re-establish the tracker between the calls. Again, we can
+ carry the tracking state in SP for this period of time unless the
+ tracker value is needed at that point in time.
+
+ We run the pass just before the final branch reorganization pass so
+ that we can handle most of the conditional branch cases using the
+ standard edge insertion code. The reorg pass will hopefully clean
+ things up for afterwards so that the results aren't too
+ horrible. */
+
+/* Generate a code sequence to clobber SP if speculating incorreclty. */
+static rtx_insn *
+aarch64_speculation_clobber_sp ()
+{
+ rtx sp = gen_rtx_REG (DImode, SP_REGNUM);
+ rtx tracker = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
+ rtx scratch = gen_rtx_REG (DImode, SPECULATION_SCRATCH_REGNUM);
+
+ start_sequence ();
+ emit_insn (gen_rtx_SET (scratch, sp));
+ emit_insn (gen_anddi3 (scratch, scratch, tracker));
+ emit_insn (gen_rtx_SET (sp, scratch));
+ rtx_insn *seq = get_insns ();
+ end_sequence ();
+ return seq;
+}
+
+/* Generate a code sequence to establish the tracker variable from the
+ contents of SP. */
+static rtx_insn *
+aarch64_speculation_establish_tracker ()
+{
+ rtx sp = gen_rtx_REG (DImode, SP_REGNUM);
+ rtx tracker = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
+ start_sequence ();
+ rtx cc = aarch64_gen_compare_reg (EQ, sp, const0_rtx);
+ emit_insn (gen_cstoredi_neg (tracker,
+ gen_rtx_NE (CCmode, cc, const0_rtx), cc));
+ rtx_insn *seq = get_insns ();
+ end_sequence ();
+ return seq;
+}
+
+/* Main speculation tracking pass. */
+unsigned int
+aarch64_do_track_speculation ()
+{
+ basic_block bb;
+ bool needs_tracking = false;
+ bool need_second_pass = false;
+ rtx_insn *insn;
+ int fixups_pending = 0;
+
+ FOR_EACH_BB_FN (bb, cfun)
+ {
+ insn = BB_END (bb);
+
+ if (dump_file)
+ fprintf (dump_file, "Basic block %d:\n", bb->index);
+
+ while (insn != BB_HEAD (bb)
+ && NOTE_P (insn))
+ insn = PREV_INSN (insn);
+
+ if (control_flow_insn_p (insn))
+ {
+ if (any_condjump_p (insn))
+ {
+ if (dump_file)
+ {
+ fprintf (dump_file, " condjump\n");
+ dump_insn_slim (dump_file, insn);
+ }
+
+ rtx src = SET_SRC (pc_set (insn));
+
+ /* Check for an inverted jump, where the fall-through edge
+ appears first. */
+ bool inverted = GET_CODE (XEXP (src, 2)) != PC;
+ /* The other edge must be the PC (we assume that we don't
+ have conditional return instructions). */
+ gcc_assert (GET_CODE (XEXP (src, 1 + !inverted)) == PC);
+
+ rtx cond = copy_rtx (XEXP (src, 0));
+ gcc_assert (COMPARISON_P (cond)
+ && REG_P (XEXP (cond, 0))
+ && REGNO (XEXP (cond, 0)) == CC_REGNUM
+ && XEXP (cond, 1) == const0_rtx);
+ enum rtx_code inv_cond_code
+ = reversed_comparison_code (cond, insn);
+ /* We should be able to reverse all conditions. */
+ gcc_assert (inv_cond_code != UNKNOWN);
+ rtx inv_cond = gen_rtx_fmt_ee (inv_cond_code, GET_MODE (cond),
+ copy_rtx (XEXP (cond, 0)),
+ copy_rtx (XEXP (cond, 1)));
+ if (inverted)
+ std::swap (cond, inv_cond);
+
+ insert_insn_on_edge (gen_speculation_tracker (cond),
+ BRANCH_EDGE (bb));
+ insert_insn_on_edge (gen_speculation_tracker (inv_cond),
+ FALLTHRU_EDGE (bb));
+ needs_tracking = true;
+ }
+ else if (GET_CODE (PATTERN (insn)) == RETURN)
+ {
+ /* If we already know we'll need a second pass, don't put
+ out the return sequence now, or we might end up with
+ two copies. Instead, we'll do all return statements
+ during the second pass. However, if this is the
+ first return insn we've found and we already
+ know that we'll need to emit the code, we can save a
+ second pass by emitting the code now. */
+ if (needs_tracking && ! need_second_pass)
+ {
+ rtx_insn *seq = aarch64_speculation_clobber_sp ();
+ emit_insn_before (seq, insn);
+ }
+ else
+ {
+ fixups_pending++;
+ need_second_pass = true;
+ }
+ }
+ else if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
+ {
+ rtx_insn *seq = aarch64_speculation_clobber_sp ();
+ emit_insn_before (seq, insn);
+ needs_tracking = true;
+ }
+ }
+ else
+ {
+ if (dump_file)
+ {
+ fprintf (dump_file, " other\n");
+ dump_insn_slim (dump_file, insn);
+ }
+ }
+ }
+
+ FOR_EACH_BB_FN (bb, cfun)
+ {
+ rtx_insn *end = BB_END (bb);
+ rtx_insn *call_insn = NULL;
+
+ if (bb->flags & BB_NON_LOCAL_GOTO_TARGET)
+ {
+ rtx_insn *label = NULL;
+ /* For non-local goto targets we have to recover the
+ speculation state from SP. Find the last code label at
+ the head of the block and place the fixup sequence after
+ that. */
+ for (insn = BB_HEAD (bb); insn != end; insn = NEXT_INSN (insn))
+ {
+ if (LABEL_P (insn))
+ label = insn;
+ /* Never put anything before the basic block note. */
+ if (NOTE_INSN_BASIC_BLOCK_P (insn))
+ label = insn;
+ if (INSN_P (insn))
+ break;
+ }
+
+ gcc_assert (label);
+ emit_insn_after (aarch64_speculation_establish_tracker (), label);
+ }
+
+ /* Scan the insns looking for calls. We need to pass the
+ speculation tracking state encoded in to SP. After a call we
+ restore the speculation tracking into the tracker register.
+ To avoid unnecessary transfers we look for two or more calls
+ within a single basic block and eliminate, where possible,
+ any redundant operations. */
+ for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
+ {
+ if (NONDEBUG_INSN_P (insn)
+ && recog_memoized (insn) >= 0
+ && (get_attr_speculation_barrier (insn)
+ == SPECULATION_BARRIER_TRUE))
+ {
+ if (call_insn)
+ {
+ /* This instruction requires the speculation
+ tracking to be in the tracker register. If there
+ was an earlier call in this block, we need to
+ copy the speculation tracking back there. */
+ emit_insn_after (aarch64_speculation_establish_tracker (),
+ call_insn);
+ call_insn = NULL;
+ }
+
+ needs_tracking = true;
+ }
+
+ if (CALL_P (insn))
+ {
+ bool tailcall
+ = (SIBLING_CALL_P (insn)
+ || find_reg_note (insn, REG_NORETURN, NULL_RTX));
+
+ /* Tailcalls are like returns, we can eliminate the
+ transfer between the tracker register and SP if we
+ know that this function does not itself need
+ tracking. */
+ if (tailcall && (need_second_pass || !needs_tracking))
+ {
+ /* Don't clear call_insn if it is set - needs_tracking
+ will be true in that case and so we will end
+ up putting out mitigation sequences. */
+ fixups_pending++;
+ need_second_pass = true;
+ break;
+ }
+
+ needs_tracking = true;
+
+ /* We always need a transfer before the first call in a BB. */
+ if (!call_insn)
+ emit_insn_before (aarch64_speculation_clobber_sp (), insn);
+
+ /* Tail-calls and no-return calls don't need any post-call
+ reestablishment of the tracker. */
+ if (! tailcall)
+ call_insn = insn;
+ else
+ call_insn = NULL;
+ }
+
+ if (insn == end)
+ break;
+ }
+
+ if (call_insn)
+ {
+ rtx_insn *seq = aarch64_speculation_establish_tracker ();
+
+ /* Handle debug insns at the end of the BB. Put the extra
+ insns after them. This ensures that we have consistent
+ behaviour for the placement of the extra insns between
+ debug and non-debug builds. */
+ for (insn = call_insn;
+ insn != end && DEBUG_INSN_P (NEXT_INSN (insn));
+ insn = NEXT_INSN (insn))
+ ;
+
+ if (insn == end)
+ {
+ edge e = find_fallthru_edge (bb->succs);
+ /* We need to be very careful about some calls that
+ appear at the end of a basic block. If the call
+ involves exceptions, then the compiler may depend on
+ this being the last instruction in the block. The
+ easiest way to handle this is to commit the new
+ instructions on the fall-through edge and to let
+ commit_edge_insertions clean things up for us.
+
+ Sometimes, eg with OMP, there may not even be an
+ outgoing edge after the call. In that case, there's
+ not much we can do, presumably the compiler has
+ decided that the call can never return in this
+ context. */
+ if (e)
+ {
+ /* We need to set the location lists explicitly in
+ this case. */
+ if (! INSN_P (seq))
+ {
+ start_sequence ();
+ emit_insn (seq);
+ seq = get_insns ();
+ end_sequence ();
+ }
+
+ for (rtx_insn *list = seq; list; list = NEXT_INSN (list))
+ INSN_LOCATION (list) = INSN_LOCATION (call_insn);
+
+ insert_insn_on_edge (seq, e);
+ }
+ }
+ else
+ emit_insn_after (seq, call_insn);
+ }
+ }
+
+ if (needs_tracking)
+ {
+ if (need_second_pass)
+ {
+ /* We found a return instruction before we found out whether
+ or not we need to emit the tracking code, but we now
+ know we do. Run quickly over the basic blocks and
+ fix up the return insns. */
+ FOR_EACH_BB_FN (bb, cfun)
+ {
+ insn = BB_END (bb);
+
+ while (insn != BB_HEAD (bb)
+ && NOTE_P (insn))
+ insn = PREV_INSN (insn);
+
+ if ((control_flow_insn_p (insn)
+ && GET_CODE (PATTERN (insn)) == RETURN)
+ || (CALL_P (insn)
+ && (SIBLING_CALL_P (insn)
+ || find_reg_note (insn, REG_NORETURN, NULL_RTX))))
+ {
+ rtx_insn *seq = aarch64_speculation_clobber_sp ();
+ emit_insn_before (seq, insn);
+ fixups_pending--;
+ }
+ }
+ gcc_assert (fixups_pending == 0);
+ }
+
+ /* Set up the initial value of the tracker, using the incoming SP. */
+ insert_insn_on_edge (aarch64_speculation_establish_tracker (),
+ single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
+ commit_edge_insertions ();
+ }
+
+ return 0;
+}
+
+namespace {
+
+const pass_data pass_data_aarch64_track_speculation =
+{
+ RTL_PASS, /* type. */
+ "speculation", /* name. */
+ OPTGROUP_NONE, /* optinfo_flags. */
+ TV_MACH_DEP, /* tv_id. */
+ 0, /* properties_required. */
+ 0, /* properties_provided. */
+ 0, /* properties_destroyed. */
+ 0, /* todo_flags_start. */
+ 0 /* todo_flags_finish. */
+};
+
+class pass_track_speculation : public rtl_opt_pass
+{
+ public:
+ pass_track_speculation(gcc::context *ctxt)
+ : rtl_opt_pass(pass_data_aarch64_track_speculation, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual bool gate (function *)
+ {
+ return aarch64_track_speculation;
+ }
+
+ virtual unsigned int execute (function *)
+ {
+ return aarch64_do_track_speculation ();
+ }
+}; // class pass_track_speculation.
+} // anon namespace.
+
+/* Create a new pass instance. */
+rtl_opt_pass *
+make_pass_track_speculation (gcc::context *ctxt)
+{
+ return new pass_track_speculation (ctxt);
+}
diff --git a/gcc/config/aarch64/aarch64-tune.md b/gcc/config/aarch64/aarch64-tune.md
index f82222c..ad52d89d 100644
--- a/gcc/config/aarch64/aarch64-tune.md
+++ b/gcc/config/aarch64/aarch64-tune.md
@@ -1,5 +1,5 @@
;; -*- buffer-read-only: t -*-
;; Generated automatically by gentune.sh from aarch64-cores.def
(define_attr "tune"
- "cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,thunderxt81,thunderxt83,xgene1,falkor,qdf24xx,exynosm1,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,saphira,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55"
+ "cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,thunderxt81,thunderxt83,xgene1,falkor,qdf24xx,exynosm1,phecda,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,tsv110,saphira,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55"
(const (symbol_ref "((enum attr_tune) aarch64_tune)")))
diff --git a/gcc/config/aarch64/aarch64-tuning-flags.def b/gcc/config/aarch64/aarch64-tuning-flags.def
index fb9700c..88a2b25 100644
--- a/gcc/config/aarch64/aarch64-tuning-flags.def
+++ b/gcc/config/aarch64/aarch64-tuning-flags.def
@@ -44,4 +44,6 @@ AARCH64_EXTRA_TUNING_OPTION ("cheap_shift_extend", CHEAP_SHIFT_EXTEND)
/* Disallow load/store pair instructions on Q-registers. */
AARCH64_EXTRA_TUNING_OPTION ("no_ldp_stp_qregs", NO_LDP_STP_QREGS)
+AARCH64_EXTRA_TUNING_OPTION ("rename_load_regs", RENAME_LOAD_REGS)
+
#undef AARCH64_EXTRA_TUNING_OPTION
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index fa01475..9c68025 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -78,48 +78,6 @@
/* Defined for convenience. */
#define POINTER_BYTES (POINTER_SIZE / BITS_PER_UNIT)
-/* Classifies an address.
-
- ADDRESS_REG_IMM
- A simple base register plus immediate offset.
-
- ADDRESS_REG_WB
- A base register indexed by immediate offset with writeback.
-
- ADDRESS_REG_REG
- A base register indexed by (optionally scaled) register.
-
- ADDRESS_REG_UXTW
- A base register indexed by (optionally scaled) zero-extended register.
-
- ADDRESS_REG_SXTW
- A base register indexed by (optionally scaled) sign-extended register.
-
- ADDRESS_LO_SUM
- A LO_SUM rtx with a base register and "LO12" symbol relocation.
-
- ADDRESS_SYMBOLIC:
- A constant symbolic address, in pc-relative literal pool. */
-
-enum aarch64_address_type {
- ADDRESS_REG_IMM,
- ADDRESS_REG_WB,
- ADDRESS_REG_REG,
- ADDRESS_REG_UXTW,
- ADDRESS_REG_SXTW,
- ADDRESS_LO_SUM,
- ADDRESS_SYMBOLIC
-};
-
-struct aarch64_address_info {
- enum aarch64_address_type type;
- rtx base;
- rtx offset;
- poly_int64 const_offset;
- int shift;
- enum aarch64_symbol_type symbol_type;
-};
-
/* Information about a legitimate vector immediate operand. */
struct simd_immediate_info
{
@@ -318,6 +276,22 @@ static const struct cpu_addrcost_table thunderx2t99_addrcost_table =
0, /* imm_offset */
};
+static const struct cpu_addrcost_table tsv110_addrcost_table =
+{
+ {
+ 1, /* hi */
+ 0, /* si */
+ 0, /* di */
+ 1, /* ti */
+ },
+ 0, /* pre_modify */
+ 0, /* post_modify */
+ 0, /* register_offset */
+ 1, /* register_sextend */
+ 1, /* register_zextend */
+ 0, /* imm_offset */
+};
+
static const struct cpu_addrcost_table qdf24xx_addrcost_table =
{
{
@@ -329,7 +303,7 @@ static const struct cpu_addrcost_table qdf24xx_addrcost_table =
1, /* pre_modify */
1, /* post_modify */
3, /* register_offset */
- 4, /* register_sextend */
+ 3, /* register_sextend */
3, /* register_zextend */
2, /* imm_offset */
};
@@ -410,6 +384,16 @@ static const struct cpu_regmove_cost thunderx2t99_regmove_cost =
4 /* FP2FP */
};
+static const struct cpu_regmove_cost tsv110_regmove_cost =
+{
+ 1, /* GP2GP */
+ /* Avoid the use of slow int<->fp moves for spilling by setting
+ their cost higher than memmov_cost. */
+ 2, /* GP2FP */
+ 3, /* FP2GP */
+ 2 /* FP2FP */
+};
+
/* Generic costs for vector insn classes. */
static const struct cpu_vector_cost generic_vector_cost =
{
@@ -430,6 +414,26 @@ static const struct cpu_vector_cost generic_vector_cost =
1 /* cond_not_taken_branch_cost */
};
+/* QDF24XX costs for vector insn classes. */
+static const struct cpu_vector_cost qdf24xx_vector_cost =
+{
+ 1, /* scalar_int_stmt_cost */
+ 1, /* scalar_fp_stmt_cost */
+ 1, /* scalar_load_cost */
+ 1, /* scalar_store_cost */
+ 1, /* vec_int_stmt_cost */
+ 3, /* vec_fp_stmt_cost */
+ 2, /* vec_permute_cost */
+ 1, /* vec_to_scalar_cost */
+ 1, /* scalar_to_vec_cost */
+ 1, /* vec_align_load_cost */
+ 1, /* vec_unalign_load_cost */
+ 1, /* vec_unalign_store_cost */
+ 1, /* vec_store_cost */
+ 3, /* cond_taken_branch_cost */
+ 1 /* cond_not_taken_branch_cost */
+};
+
/* ThunderX costs for vector insn classes. */
static const struct cpu_vector_cost thunderx_vector_cost =
{
@@ -450,6 +454,25 @@ static const struct cpu_vector_cost thunderx_vector_cost =
3 /* cond_not_taken_branch_cost */
};
+static const struct cpu_vector_cost tsv110_vector_cost =
+{
+ 1, /* scalar_int_stmt_cost */
+ 1, /* scalar_fp_stmt_cost */
+ 5, /* scalar_load_cost */
+ 1, /* scalar_store_cost */
+ 2, /* vec_int_stmt_cost */
+ 2, /* vec_fp_stmt_cost */
+ 2, /* vec_permute_cost */
+ 3, /* vec_to_scalar_cost */
+ 2, /* scalar_to_vec_cost */
+ 5, /* vec_align_load_cost */
+ 5, /* vec_unalign_load_cost */
+ 1, /* vec_unalign_store_cost */
+ 1, /* vec_store_cost */
+ 1, /* cond_taken_branch_cost */
+ 1 /* cond_not_taken_branch_cost */
+};
+
/* Generic costs for vector insn classes. */
static const struct cpu_vector_cost cortexa57_vector_cost =
{
@@ -627,6 +650,17 @@ static const cpu_prefetch_tune thunderx2t99_prefetch_tune =
-1 /* default_opt_level */
};
+static const cpu_prefetch_tune tsv110_prefetch_tune =
+{
+ 0, /* num_slots */
+ 64, /* l1_cache_size */
+ 64, /* l1_cache_line_size */
+ 512, /* l2_cache_size */
+ true, /* prefetch_dynamic_strides */
+ -1, /* minimum_stride */
+ -1 /* default_opt_level */
+};
+
static const struct tune_params generic_tunings =
{
&cortexa57_extra_costs,
@@ -860,6 +894,32 @@ static const struct tune_params thunderx_tunings =
&thunderx_prefetch_tune
};
+static const struct tune_params tsv110_tunings =
+{
+ &tsv110_extra_costs,
+ &tsv110_addrcost_table,
+ &tsv110_regmove_cost,
+ &tsv110_vector_cost,
+ &generic_branch_cost,
+ &generic_approx_modes,
+ 4, /* memmov_cost */
+ 4, /* issue_rate */
+ (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH
+ | AARCH64_FUSE_ALU_BRANCH), /* fusible_ops */
+ "16", /* function_align. */
+ "4", /* jump_align. */
+ "8", /* loop_align. */
+ 2, /* int_reassoc_width. */
+ 4, /* fp_reassoc_width. */
+ 1, /* vec_reassoc_width. */
+ 2, /* min_div_recip_mul_sf. */
+ 2, /* min_div_recip_mul_df. */
+ 0, /* max_case_values. */
+ tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */
+ (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */
+ &tsv110_prefetch_tune
+};
+
static const struct tune_params xgene1_tunings =
{
&xgene1_extra_costs,
@@ -890,7 +950,7 @@ static const struct tune_params qdf24xx_tunings =
&qdf24xx_extra_costs,
&qdf24xx_addrcost_table,
&qdf24xx_regmove_cost,
- &generic_vector_cost,
+ &qdf24xx_vector_cost,
&generic_branch_cost,
&generic_approx_modes,
4, /* memmov_cost */
@@ -907,7 +967,7 @@ static const struct tune_params qdf24xx_tunings =
2, /* min_div_recip_mul_df. */
0, /* max_case_values. */
tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */
- (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */
+ AARCH64_EXTRA_TUNE_RENAME_LOAD_REGS, /* tune_flags. */
&qdf24xx_prefetch_tune
};
@@ -1454,6 +1514,13 @@ aarch64_hard_regno_caller_save_mode (unsigned regno, unsigned,
return SImode;
}
+/* Return true if I's bits are consecutive ones from the MSB. */
+bool
+aarch64_high_bits_all_ones_p (HOST_WIDE_INT i)
+{
+ return exact_log2 (-i) != HOST_WIDE_INT_M1;
+}
+
/* Implement TARGET_CONSTANT_ALIGNMENT. Make strings word-aligned so
that strcpy from constants will be faster. */
@@ -1981,16 +2048,8 @@ aarch64_split_128bit_move (rtx dst, rtx src)
src_lo = gen_lowpart (word_mode, src);
src_hi = gen_highpart (word_mode, src);
- if (mode == TImode)
- {
- emit_insn (gen_aarch64_movtilow_di (dst, src_lo));
- emit_insn (gen_aarch64_movtihigh_di (dst, src_hi));
- }
- else
- {
- emit_insn (gen_aarch64_movtflow_di (dst, src_lo));
- emit_insn (gen_aarch64_movtfhigh_di (dst, src_hi));
- }
+ emit_insn (gen_aarch64_movlow_di (mode, dst, src_lo));
+ emit_insn (gen_aarch64_movhigh_di (mode, dst, src_hi));
return;
}
else if (GP_REGNUM_P (dst_regno) && FP_REGNUM_P (src_regno))
@@ -1998,16 +2057,8 @@ aarch64_split_128bit_move (rtx dst, rtx src)
dst_lo = gen_lowpart (word_mode, dst);
dst_hi = gen_highpart (word_mode, dst);
- if (mode == TImode)
- {
- emit_insn (gen_aarch64_movdi_tilow (dst_lo, src));
- emit_insn (gen_aarch64_movdi_tihigh (dst_hi, src));
- }
- else
- {
- emit_insn (gen_aarch64_movdi_tflow (dst_lo, src));
- emit_insn (gen_aarch64_movdi_tfhigh (dst_hi, src));
- }
+ emit_insn (gen_aarch64_movdi_low (mode, dst_lo, src));
+ emit_insn (gen_aarch64_movdi_high (mode, dst_hi, src));
return;
}
}
@@ -2050,36 +2101,7 @@ aarch64_split_simd_combine (rtx dst, rtx src1, rtx src2)
&& register_operand (src1, src_mode)
&& register_operand (src2, src_mode));
- rtx (*gen) (rtx, rtx, rtx);
-
- switch (src_mode)
- {
- case E_V8QImode:
- gen = gen_aarch64_simd_combinev8qi;
- break;
- case E_V4HImode:
- gen = gen_aarch64_simd_combinev4hi;
- break;
- case E_V2SImode:
- gen = gen_aarch64_simd_combinev2si;
- break;
- case E_V4HFmode:
- gen = gen_aarch64_simd_combinev4hf;
- break;
- case E_V2SFmode:
- gen = gen_aarch64_simd_combinev2sf;
- break;
- case E_DImode:
- gen = gen_aarch64_simd_combinedi;
- break;
- case E_DFmode:
- gen = gen_aarch64_simd_combinedf;
- break;
- default:
- gcc_unreachable ();
- }
-
- emit_insn (gen (dst, src1, src2));
+ emit_insn (gen_aarch64_simd_combine (src_mode, dst, src1, src2));
return;
}
@@ -2095,39 +2117,8 @@ aarch64_split_simd_move (rtx dst, rtx src)
if (REG_P (dst) && REG_P (src))
{
- rtx (*gen) (rtx, rtx);
-
gcc_assert (VECTOR_MODE_P (src_mode));
-
- switch (src_mode)
- {
- case E_V16QImode:
- gen = gen_aarch64_split_simd_movv16qi;
- break;
- case E_V8HImode:
- gen = gen_aarch64_split_simd_movv8hi;
- break;
- case E_V4SImode:
- gen = gen_aarch64_split_simd_movv4si;
- break;
- case E_V2DImode:
- gen = gen_aarch64_split_simd_movv2di;
- break;
- case E_V8HFmode:
- gen = gen_aarch64_split_simd_movv8hf;
- break;
- case E_V4SFmode:
- gen = gen_aarch64_split_simd_movv4sf;
- break;
- case E_V2DFmode:
- gen = gen_aarch64_split_simd_movv2df;
- break;
- default:
- gcc_unreachable ();
- }
-
- emit_insn (gen (dst, src));
- return;
+ emit_insn (gen_aarch64_split_simd_mov (src_mode, dst, src));
}
}
@@ -4036,9 +4027,6 @@ aarch64_layout_frame (void)
HOST_WIDE_INT offset = 0;
int regno, last_fp_reg = INVALID_REGNUM;
- if (reload_completed && cfun->machine->frame.laid_out)
- return;
-
cfun->machine->frame.emit_frame_chain = aarch64_needs_frame_chain ();
#define SLOT_NOT_REQUIRED (-2)
@@ -4546,9 +4534,9 @@ aarch64_offset_7bit_signed_scaled_p (machine_mode mode, poly_int64 offset)
/* Return true if OFFSET is a signed 9-bit value. */
-static inline bool
-offset_9bit_signed_unscaled_p (machine_mode mode ATTRIBUTE_UNUSED,
- poly_int64 offset)
+bool
+aarch64_offset_9bit_signed_unscaled_p (machine_mode mode ATTRIBUTE_UNUSED,
+ poly_int64 offset)
{
HOST_WIDE_INT const_offset;
return (offset.is_constant (&const_offset)
@@ -4582,8 +4570,6 @@ offset_12bit_unsigned_scaled_p (machine_mode mode, poly_int64 offset)
static sbitmap
aarch64_get_separate_components (void)
{
- aarch64_layout_frame ();
-
sbitmap components = sbitmap_alloc (LAST_SAVED_REGNUM + 1);
bitmap_clear (components);
@@ -4607,7 +4593,7 @@ aarch64_get_separate_components (void)
unsigned reg1 = cfun->machine->frame.wb_candidate1;
unsigned reg2 = cfun->machine->frame.wb_candidate2;
- /* If aarch64_layout_frame has chosen registers to store/restore with
+ /* If registers have been chosen to be stored/restored with
writeback don't interfere with them to avoid having to output explicit
stack adjustment instructions. */
if (reg2 != INVALID_REGNUM)
@@ -4865,8 +4851,6 @@ aarch64_add_cfa_expression (rtx_insn *insn, unsigned int reg,
void
aarch64_expand_prologue (void)
{
- aarch64_layout_frame ();
-
poly_int64 frame_size = cfun->machine->frame.frame_size;
poly_int64 initial_adjust = cfun->machine->frame.initial_adjust;
HOST_WIDE_INT callee_adjust = cfun->machine->frame.callee_adjust;
@@ -4979,8 +4963,6 @@ aarch64_use_return_insn_p (void)
if (crtl->profile)
return false;
- aarch64_layout_frame ();
-
return known_eq (cfun->machine->frame.frame_size, 0);
}
@@ -4992,8 +4974,6 @@ aarch64_use_return_insn_p (void)
void
aarch64_expand_epilogue (bool for_sibcall)
{
- aarch64_layout_frame ();
-
poly_int64 initial_adjust = cfun->machine->frame.initial_adjust;
HOST_WIDE_INT callee_adjust = cfun->machine->frame.callee_adjust;
poly_int64 final_adjust = cfun->machine->frame.final_adjust;
@@ -5727,10 +5707,10 @@ virt_or_elim_regno_p (unsigned regno)
If it is, fill in INFO appropriately. STRICT_P is true if
REG_OK_STRICT is in effect. */
-static bool
+bool
aarch64_classify_address (struct aarch64_address_info *info,
rtx x, machine_mode mode, bool strict_p,
- aarch64_addr_query_type type = ADDR_QUERY_M)
+ aarch64_addr_query_type type)
{
enum rtx_code code = GET_CODE (x);
rtx op0, op1;
@@ -5823,7 +5803,7 @@ aarch64_classify_address (struct aarch64_address_info *info,
instruction memory accesses. */
if (mode == TImode || mode == TFmode)
return (aarch64_offset_7bit_signed_scaled_p (DImode, offset)
- && (offset_9bit_signed_unscaled_p (mode, offset)
+ && (aarch64_offset_9bit_signed_unscaled_p (mode, offset)
|| offset_12bit_unsigned_scaled_p (mode, offset)));
/* A 7bit offset check because OImode will emit a ldp/stp
@@ -5837,7 +5817,8 @@ aarch64_classify_address (struct aarch64_address_info *info,
ldr/str instructions (only big endian will get here). */
if (mode == CImode)
return (aarch64_offset_7bit_signed_scaled_p (TImode, offset)
- && (offset_9bit_signed_unscaled_p (V16QImode, offset + 32)
+ && (aarch64_offset_9bit_signed_unscaled_p (V16QImode,
+ offset + 32)
|| offset_12bit_unsigned_scaled_p (V16QImode,
offset + 32)));
@@ -5877,7 +5858,7 @@ aarch64_classify_address (struct aarch64_address_info *info,
|| known_eq (GET_MODE_SIZE (mode), 16))
&& aarch64_offset_7bit_signed_scaled_p (mode, offset));
else
- return (offset_9bit_signed_unscaled_p (mode, offset)
+ return (aarch64_offset_9bit_signed_unscaled_p (mode, offset)
|| offset_12bit_unsigned_scaled_p (mode, offset));
}
@@ -5930,7 +5911,7 @@ aarch64_classify_address (struct aarch64_address_info *info,
*/
if (mode == TImode || mode == TFmode)
return (aarch64_offset_7bit_signed_scaled_p (mode, offset)
- && offset_9bit_signed_unscaled_p (mode, offset));
+ && aarch64_offset_9bit_signed_unscaled_p (mode, offset));
if (load_store_pair_p)
return ((known_eq (GET_MODE_SIZE (mode), 4)
@@ -5938,7 +5919,7 @@ aarch64_classify_address (struct aarch64_address_info *info,
|| known_eq (GET_MODE_SIZE (mode), 16))
&& aarch64_offset_7bit_signed_scaled_p (mode, offset));
else
- return offset_9bit_signed_unscaled_p (mode, offset);
+ return aarch64_offset_9bit_signed_unscaled_p (mode, offset);
}
return false;
@@ -6785,6 +6766,12 @@ aarch64_print_operand (FILE *f, rtx x, int code)
break;
case 'H':
+ if (x == const0_rtx)
+ {
+ asm_fprintf (f, "xzr");
+ break;
+ }
+
if (!REG_P (x) || !GP_REGNUM_P (REGNO (x) + 1))
{
output_operand_lossage ("invalid operand for '%%%c'", code);
@@ -7437,51 +7424,6 @@ aarch64_legitimize_address (rtx x, rtx /* orig_x */, machine_mode mode)
return x;
}
-/* Return the reload icode required for a constant pool in mode. */
-static enum insn_code
-aarch64_constant_pool_reload_icode (machine_mode mode)
-{
- switch (mode)
- {
- case E_SFmode:
- return CODE_FOR_aarch64_reload_movcpsfdi;
-
- case E_DFmode:
- return CODE_FOR_aarch64_reload_movcpdfdi;
-
- case E_TFmode:
- return CODE_FOR_aarch64_reload_movcptfdi;
-
- case E_V8QImode:
- return CODE_FOR_aarch64_reload_movcpv8qidi;
-
- case E_V16QImode:
- return CODE_FOR_aarch64_reload_movcpv16qidi;
-
- case E_V4HImode:
- return CODE_FOR_aarch64_reload_movcpv4hidi;
-
- case E_V8HImode:
- return CODE_FOR_aarch64_reload_movcpv8hidi;
-
- case E_V2SImode:
- return CODE_FOR_aarch64_reload_movcpv2sidi;
-
- case E_V4SImode:
- return CODE_FOR_aarch64_reload_movcpv4sidi;
-
- case E_V2DImode:
- return CODE_FOR_aarch64_reload_movcpv2didi;
-
- case E_V2DFmode:
- return CODE_FOR_aarch64_reload_movcpv2dfdi;
-
- default:
- gcc_unreachable ();
- }
-
- gcc_unreachable ();
-}
static reg_class_t
aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
reg_class_t rclass,
@@ -7509,7 +7451,7 @@ aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
|| targetm.vector_mode_supported_p (GET_MODE (x)))
&& !aarch64_pcrelative_literal_loads)
{
- sri->icode = aarch64_constant_pool_reload_icode (mode);
+ sri->icode = code_for_aarch64_reload_movcp (mode, DImode);
return NO_REGS;
}
@@ -7519,10 +7461,7 @@ aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
&& FP_REGNUM_P (REGNO (x)) && !TARGET_SIMD
&& reg_class_subset_p (rclass, FP_REGS))
{
- if (mode == TFmode)
- sri->icode = CODE_FOR_aarch64_reload_movtf;
- else if (mode == TImode)
- sri->icode = CODE_FOR_aarch64_reload_movti;
+ sri->icode = code_for_aarch64_reload_mov (mode);
return NO_REGS;
}
@@ -7554,8 +7493,6 @@ aarch64_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
poly_int64
aarch64_initial_elimination_offset (unsigned from, unsigned to)
{
- aarch64_layout_frame ();
-
if (to == HARD_FRAME_POINTER_REGNUM)
{
if (from == ARG_POINTER_REGNUM)
@@ -9888,43 +9825,6 @@ aarch64_builtin_reciprocal (tree fndecl)
return aarch64_builtin_rsqrt (DECL_FUNCTION_CODE (fndecl));
}
-typedef rtx (*rsqrte_type) (rtx, rtx);
-
-/* Select reciprocal square root initial estimate insn depending on machine
- mode. */
-
-static rsqrte_type
-get_rsqrte_type (machine_mode mode)
-{
- switch (mode)
- {
- case E_DFmode: return gen_aarch64_rsqrtedf;
- case E_SFmode: return gen_aarch64_rsqrtesf;
- case E_V2DFmode: return gen_aarch64_rsqrtev2df;
- case E_V2SFmode: return gen_aarch64_rsqrtev2sf;
- case E_V4SFmode: return gen_aarch64_rsqrtev4sf;
- default: gcc_unreachable ();
- }
-}
-
-typedef rtx (*rsqrts_type) (rtx, rtx, rtx);
-
-/* Select reciprocal square root series step insn depending on machine mode. */
-
-static rsqrts_type
-get_rsqrts_type (machine_mode mode)
-{
- switch (mode)
- {
- case E_DFmode: return gen_aarch64_rsqrtsdf;
- case E_SFmode: return gen_aarch64_rsqrtssf;
- case E_V2DFmode: return gen_aarch64_rsqrtsv2df;
- case E_V2SFmode: return gen_aarch64_rsqrtsv2sf;
- case E_V4SFmode: return gen_aarch64_rsqrtsv4sf;
- default: gcc_unreachable ();
- }
-}
-
/* Emit instruction sequence to compute either the approximate square root
or its approximate reciprocal, depending on the flag RECP, and return
whether the sequence was emitted or not. */
@@ -9969,7 +9869,7 @@ aarch64_emit_approx_sqrt (rtx dst, rtx src, bool recp)
/* Estimate the approximate reciprocal square root. */
rtx xdst = gen_reg_rtx (mode);
- emit_insn ((*get_rsqrte_type (mode)) (xdst, src));
+ emit_insn (gen_aarch64_rsqrte (mode, xdst, src));
/* Iterate over the series twice for SF and thrice for DF. */
int iterations = (GET_MODE_INNER (mode) == DFmode) ? 3 : 2;
@@ -9988,7 +9888,7 @@ aarch64_emit_approx_sqrt (rtx dst, rtx src, bool recp)
rtx x2 = gen_reg_rtx (mode);
emit_set_insn (x2, gen_rtx_MULT (mode, xdst, xdst));
- emit_insn ((*get_rsqrts_type (mode)) (x1, src, x2));
+ emit_insn (gen_aarch64_rsqrts (mode, x1, src, x2));
if (iterations > 0)
emit_set_insn (xdst, gen_rtx_MULT (mode, xdst, x1));
@@ -10013,42 +9913,6 @@ aarch64_emit_approx_sqrt (rtx dst, rtx src, bool recp)
return true;
}
-typedef rtx (*recpe_type) (rtx, rtx);
-
-/* Select reciprocal initial estimate insn depending on machine mode. */
-
-static recpe_type
-get_recpe_type (machine_mode mode)
-{
- switch (mode)
- {
- case E_SFmode: return (gen_aarch64_frecpesf);
- case E_V2SFmode: return (gen_aarch64_frecpev2sf);
- case E_V4SFmode: return (gen_aarch64_frecpev4sf);
- case E_DFmode: return (gen_aarch64_frecpedf);
- case E_V2DFmode: return (gen_aarch64_frecpev2df);
- default: gcc_unreachable ();
- }
-}
-
-typedef rtx (*recps_type) (rtx, rtx, rtx);
-
-/* Select reciprocal series step insn depending on machine mode. */
-
-static recps_type
-get_recps_type (machine_mode mode)
-{
- switch (mode)
- {
- case E_SFmode: return (gen_aarch64_frecpssf);
- case E_V2SFmode: return (gen_aarch64_frecpsv2sf);
- case E_V4SFmode: return (gen_aarch64_frecpsv4sf);
- case E_DFmode: return (gen_aarch64_frecpsdf);
- case E_V2DFmode: return (gen_aarch64_frecpsv2df);
- default: gcc_unreachable ();
- }
-}
-
/* Emit the instruction sequence to compute the approximation for the division
of NUM by DEN in QUO and return whether the sequence was emitted or not. */
@@ -10076,7 +9940,7 @@ aarch64_emit_approx_div (rtx quo, rtx num, rtx den)
/* Estimate the approximate reciprocal. */
rtx xrcp = gen_reg_rtx (mode);
- emit_insn ((*get_recpe_type (mode)) (xrcp, den));
+ emit_insn (gen_aarch64_frecpe (mode, xrcp, den));
/* Iterate over the series twice for SF and thrice for DF. */
int iterations = (GET_MODE_INNER (mode) == DFmode) ? 3 : 2;
@@ -10090,7 +9954,7 @@ aarch64_emit_approx_div (rtx quo, rtx num, rtx den)
rtx xtmp = gen_reg_rtx (mode);
while (iterations--)
{
- emit_insn ((*get_recps_type (mode)) (xtmp, xrcp, den));
+ emit_insn (gen_aarch64_frecps (mode, xtmp, xrcp, den));
if (iterations > 0)
emit_set_insn (xrcp, gen_rtx_MULT (mode, xrcp, xtmp));
@@ -10728,6 +10592,13 @@ aarch64_override_options_internal (struct gcc_options *opts)
&& opts->x_optimize >= aarch64_tune_params.prefetch->default_opt_level)
opts->x_flag_prefetch_loop_arrays = 1;
+ if (opts->x_aarch64_arch_string == NULL)
+ opts->x_aarch64_arch_string = selected_arch->name;
+ if (opts->x_aarch64_cpu_string == NULL)
+ opts->x_aarch64_cpu_string = selected_cpu->name;
+ if (opts->x_aarch64_tune_string == NULL)
+ opts->x_aarch64_tune_string = selected_tune->name;
+
aarch64_override_options_after_change_1 (opts);
}
@@ -12602,6 +12473,19 @@ aarch64_conditional_register_usage (void)
fixed_regs[i] = 1;
call_used_regs[i] = 1;
}
+
+ /* When tracking speculation, we need a couple of call-clobbered registers
+ to track the speculation state. It would be nice to just use
+ IP0 and IP1, but currently there are numerous places that just
+ assume these registers are free for other uses (eg pointer
+ authentication). */
+ if (aarch64_track_speculation)
+ {
+ fixed_regs[SPECULATION_TRACKER_REGNUM] = 1;
+ call_used_regs[SPECULATION_TRACKER_REGNUM] = 1;
+ fixed_regs[SPECULATION_SCRATCH_REGNUM] = 1;
+ call_used_regs[SPECULATION_SCRATCH_REGNUM] = 1;
+ }
}
/* Walk down the type tree of TYPE counting consecutive base elements.
@@ -14228,19 +14112,7 @@ static void
aarch64_emit_load_exclusive (machine_mode mode, rtx rval,
rtx mem, rtx model_rtx)
{
- rtx (*gen) (rtx, rtx, rtx);
-
- switch (mode)
- {
- case E_QImode: gen = gen_aarch64_load_exclusiveqi; break;
- case E_HImode: gen = gen_aarch64_load_exclusivehi; break;
- case E_SImode: gen = gen_aarch64_load_exclusivesi; break;
- case E_DImode: gen = gen_aarch64_load_exclusivedi; break;
- default:
- gcc_unreachable ();
- }
-
- emit_insn (gen (rval, mem, model_rtx));
+ emit_insn (gen_aarch64_load_exclusive (mode, rval, mem, model_rtx));
}
/* Emit store exclusive. */
@@ -14249,19 +14121,7 @@ static void
aarch64_emit_store_exclusive (machine_mode mode, rtx bval,
rtx rval, rtx mem, rtx model_rtx)
{
- rtx (*gen) (rtx, rtx, rtx, rtx);
-
- switch (mode)
- {
- case E_QImode: gen = gen_aarch64_store_exclusiveqi; break;
- case E_HImode: gen = gen_aarch64_store_exclusivehi; break;
- case E_SImode: gen = gen_aarch64_store_exclusivesi; break;
- case E_DImode: gen = gen_aarch64_store_exclusivedi; break;
- default:
- gcc_unreachable ();
- }
-
- emit_insn (gen (bval, rval, mem, model_rtx));
+ emit_insn (gen_aarch64_store_exclusive (mode, bval, rval, mem, model_rtx));
}
/* Mark the previous jump instruction as unlikely. */
@@ -14280,23 +14140,6 @@ aarch64_expand_compare_and_swap (rtx operands[])
{
rtx bval, rval, mem, oldval, newval, is_weak, mod_s, mod_f, x;
machine_mode mode, cmp_mode;
- typedef rtx (*gen_cas_fn) (rtx, rtx, rtx, rtx, rtx, rtx, rtx);
- int idx;
- gen_cas_fn gen;
- const gen_cas_fn split_cas[] =
- {
- gen_aarch64_compare_and_swapqi,
- gen_aarch64_compare_and_swaphi,
- gen_aarch64_compare_and_swapsi,
- gen_aarch64_compare_and_swapdi
- };
- const gen_cas_fn atomic_cas[] =
- {
- gen_aarch64_compare_and_swapqi_lse,
- gen_aarch64_compare_and_swaphi_lse,
- gen_aarch64_compare_and_swapsi_lse,
- gen_aarch64_compare_and_swapdi_lse
- };
bval = operands[0];
rval = operands[1];
@@ -14339,21 +14182,14 @@ aarch64_expand_compare_and_swap (rtx operands[])
gcc_unreachable ();
}
- switch (mode)
- {
- case E_QImode: idx = 0; break;
- case E_HImode: idx = 1; break;
- case E_SImode: idx = 2; break;
- case E_DImode: idx = 3; break;
- default:
- gcc_unreachable ();
- }
if (TARGET_LSE)
- gen = atomic_cas[idx];
+ emit_insn (gen_aarch64_compare_and_swap_lse (mode, rval, mem, oldval,
+ newval, is_weak, mod_s,
+ mod_f));
else
- gen = split_cas[idx];
+ emit_insn (gen_aarch64_compare_and_swap (mode, rval, mem, oldval, newval,
+ is_weak, mod_s, mod_f));
- emit_insn (gen (rval, mem, oldval, newval, is_weak, mod_s, mod_f));
if (mode == QImode || mode == HImode)
emit_move_insn (operands[1], gen_lowpart (mode, rval));
@@ -14416,26 +14252,15 @@ aarch64_gen_atomic_cas (rtx rval, rtx mem,
rtx expected, rtx desired,
rtx model)
{
- rtx (*gen) (rtx, rtx, rtx, rtx);
machine_mode mode;
mode = GET_MODE (mem);
- switch (mode)
- {
- case E_QImode: gen = gen_aarch64_atomic_casqi; break;
- case E_HImode: gen = gen_aarch64_atomic_cashi; break;
- case E_SImode: gen = gen_aarch64_atomic_cassi; break;
- case E_DImode: gen = gen_aarch64_atomic_casdi; break;
- default:
- gcc_unreachable ();
- }
-
/* Move the expected value into the CAS destination register. */
emit_insn (gen_rtx_SET (rval, expected));
/* Emit the CAS. */
- emit_insn (gen (rval, mem, desired, model));
+ emit_insn (gen_aarch64_atomic_cas (mode, rval, mem, desired, model));
/* Compare the expected value with the value loaded by the CAS, to establish
whether the swap was made. */
@@ -14494,7 +14319,16 @@ aarch64_split_compare_and_swap (rtx operands[])
if (strong_zero_p)
{
- x = gen_rtx_NE (VOIDmode, rval, const0_rtx);
+ if (aarch64_track_speculation)
+ {
+ /* Emit an explicit compare instruction, so that we can correctly
+ track the condition codes. */
+ rtx cc_reg = aarch64_gen_compare_reg (NE, rval, const0_rtx);
+ x = gen_rtx_NE (GET_MODE (cc_reg), cc_reg, const0_rtx);
+ }
+ else
+ x = gen_rtx_NE (VOIDmode, rval, const0_rtx);
+
x = gen_rtx_IF_THEN_ELSE (VOIDmode, x,
gen_rtx_LABEL_REF (Pmode, label2), pc_rtx);
aarch64_emit_unlikely_jump (gen_rtx_SET (pc_rtx, x));
@@ -14512,7 +14346,16 @@ aarch64_split_compare_and_swap (rtx operands[])
if (!is_weak)
{
- x = gen_rtx_NE (VOIDmode, scratch, const0_rtx);
+ if (aarch64_track_speculation)
+ {
+ /* Emit an explicit compare instruction, so that we can correctly
+ track the condition codes. */
+ rtx cc_reg = aarch64_gen_compare_reg (NE, scratch, const0_rtx);
+ x = gen_rtx_NE (GET_MODE (cc_reg), cc_reg, const0_rtx);
+ }
+ else
+ x = gen_rtx_NE (VOIDmode, scratch, const0_rtx);
+
x = gen_rtx_IF_THEN_ELSE (VOIDmode, x,
gen_rtx_LABEL_REF (Pmode, label1), pc_rtx);
aarch64_emit_unlikely_jump (gen_rtx_SET (pc_rtx, x));
@@ -14564,91 +14407,7 @@ static void
aarch64_emit_atomic_swap (machine_mode mode, rtx dst, rtx value,
rtx mem, rtx model)
{
- rtx (*gen) (rtx, rtx, rtx, rtx);
-
- switch (mode)
- {
- case E_QImode: gen = gen_aarch64_atomic_swpqi; break;
- case E_HImode: gen = gen_aarch64_atomic_swphi; break;
- case E_SImode: gen = gen_aarch64_atomic_swpsi; break;
- case E_DImode: gen = gen_aarch64_atomic_swpdi; break;
- default:
- gcc_unreachable ();
- }
-
- emit_insn (gen (dst, mem, value, model));
-}
-
-/* Operations supported by aarch64_emit_atomic_load_op. */
-
-enum aarch64_atomic_load_op_code
-{
- AARCH64_LDOP_PLUS, /* A + B */
- AARCH64_LDOP_XOR, /* A ^ B */
- AARCH64_LDOP_OR, /* A | B */
- AARCH64_LDOP_BIC /* A & ~B */
-};
-
-/* Emit an atomic load-operate. */
-
-static void
-aarch64_emit_atomic_load_op (enum aarch64_atomic_load_op_code code,
- machine_mode mode, rtx dst, rtx src,
- rtx mem, rtx model)
-{
- typedef rtx (*aarch64_atomic_load_op_fn) (rtx, rtx, rtx, rtx);
- const aarch64_atomic_load_op_fn plus[] =
- {
- gen_aarch64_atomic_loadaddqi,
- gen_aarch64_atomic_loadaddhi,
- gen_aarch64_atomic_loadaddsi,
- gen_aarch64_atomic_loadadddi
- };
- const aarch64_atomic_load_op_fn eor[] =
- {
- gen_aarch64_atomic_loadeorqi,
- gen_aarch64_atomic_loadeorhi,
- gen_aarch64_atomic_loadeorsi,
- gen_aarch64_atomic_loadeordi
- };
- const aarch64_atomic_load_op_fn ior[] =
- {
- gen_aarch64_atomic_loadsetqi,
- gen_aarch64_atomic_loadsethi,
- gen_aarch64_atomic_loadsetsi,
- gen_aarch64_atomic_loadsetdi
- };
- const aarch64_atomic_load_op_fn bic[] =
- {
- gen_aarch64_atomic_loadclrqi,
- gen_aarch64_atomic_loadclrhi,
- gen_aarch64_atomic_loadclrsi,
- gen_aarch64_atomic_loadclrdi
- };
- aarch64_atomic_load_op_fn gen;
- int idx = 0;
-
- switch (mode)
- {
- case E_QImode: idx = 0; break;
- case E_HImode: idx = 1; break;
- case E_SImode: idx = 2; break;
- case E_DImode: idx = 3; break;
- default:
- gcc_unreachable ();
- }
-
- switch (code)
- {
- case AARCH64_LDOP_PLUS: gen = plus[idx]; break;
- case AARCH64_LDOP_XOR: gen = eor[idx]; break;
- case AARCH64_LDOP_OR: gen = ior[idx]; break;
- case AARCH64_LDOP_BIC: gen = bic[idx]; break;
- default:
- gcc_unreachable ();
- }
-
- emit_insn (gen (dst, mem, src, model));
+ emit_insn (gen_aarch64_atomic_swp (mode, dst, mem, value, model));
}
/* Emit an atomic load+operate. CODE is the operation. OUT_DATA is the
@@ -14665,7 +14424,7 @@ aarch64_gen_atomic_ldop (enum rtx_code code, rtx out_data, rtx out_result,
machine_mode mode = GET_MODE (mem);
machine_mode wmode = (mode == DImode ? DImode : SImode);
const bool short_mode = (mode < SImode);
- aarch64_atomic_load_op_code ldop_code;
+ int ldop_code;
rtx src;
rtx x;
@@ -14712,15 +14471,15 @@ aarch64_gen_atomic_ldop (enum rtx_code code, rtx out_data, rtx out_result,
}
/* Fall-through. */
case PLUS:
- ldop_code = AARCH64_LDOP_PLUS;
+ ldop_code = UNSPECV_ATOMIC_LDOP_PLUS;
break;
case IOR:
- ldop_code = AARCH64_LDOP_OR;
+ ldop_code = UNSPECV_ATOMIC_LDOP_OR;
break;
case XOR:
- ldop_code = AARCH64_LDOP_XOR;
+ ldop_code = UNSPECV_ATOMIC_LDOP_XOR;
break;
case AND:
@@ -14737,7 +14496,7 @@ aarch64_gen_atomic_ldop (enum rtx_code code, rtx out_data, rtx out_result,
if (short_mode)
src = gen_lowpart (mode, src);
}
- ldop_code = AARCH64_LDOP_BIC;
+ ldop_code = UNSPECV_ATOMIC_LDOP_BIC;
break;
default:
@@ -14745,7 +14504,8 @@ aarch64_gen_atomic_ldop (enum rtx_code code, rtx out_data, rtx out_result,
gcc_unreachable ();
}
- aarch64_emit_atomic_load_op (ldop_code, mode, out_data, src, mem, model_rtx);
+ emit_insn (gen_aarch64_atomic_load (ldop_code, mode,
+ out_data, mem, src, model_rtx));
/* If necessary, calculate the data in memory after the update by redoing the
operation from values in registers. */
@@ -14848,7 +14608,16 @@ aarch64_split_atomic_op (enum rtx_code code, rtx old_out, rtx new_out, rtx mem,
aarch64_emit_store_exclusive (mode, cond, mem,
gen_lowpart (mode, new_out), model_rtx);
- x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
+ if (aarch64_track_speculation)
+ {
+ /* Emit an explicit compare instruction, so that we can correctly
+ track the condition codes. */
+ rtx cc_reg = aarch64_gen_compare_reg (NE, cond, const0_rtx);
+ x = gen_rtx_NE (GET_MODE (cc_reg), cc_reg, const0_rtx);
+ }
+ else
+ x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
+
x = gen_rtx_IF_THEN_ELSE (VOIDmode, x,
gen_rtx_LABEL_REF (Pmode, label), pc_rtx);
aarch64_emit_unlikely_jump (gen_rtx_SET (pc_rtx, x));
@@ -14923,8 +14692,8 @@ aarch64_float_const_representable_p (rtx x)
if (!CONST_DOUBLE_P (x))
return false;
- /* We don't support HFmode constants yet. */
- if (GET_MODE (x) == VOIDmode || GET_MODE (x) == HFmode)
+ if (GET_MODE (x) == VOIDmode
+ || (GET_MODE (x) == HFmode && !TARGET_FP_F16INST))
return false;
r = *CONST_DOUBLE_REAL_VALUE (x);
@@ -15696,7 +15465,10 @@ aarch64_evpc_sve_tbl (struct expand_vec_perm_d *d)
machine_mode sel_mode = mode_for_int_vector (d->vmode).require ();
rtx sel = vec_perm_indices_to_rtx (sel_mode, d->perm);
- aarch64_expand_sve_vec_perm (d->target, d->op0, d->op1, sel);
+ if (d->one_vector_p)
+ emit_unspec2 (d->target, UNSPEC_TBL, d->op0, force_reg (sel_mode, sel));
+ else
+ aarch64_expand_sve_vec_perm (d->target, d->op0, d->op1, sel);
return true;
}
@@ -15734,7 +15506,7 @@ aarch64_expand_vec_perm_const_1 (struct expand_vec_perm_d *d)
return true;
if (d->vec_flags == VEC_SVE_DATA)
return aarch64_evpc_sve_tbl (d);
- else if (d->vec_flags == VEC_SVE_DATA)
+ else if (d->vec_flags == VEC_ADVSIMD)
return aarch64_evpc_tbl (d);
}
return false;
@@ -15749,7 +15521,8 @@ aarch64_vectorize_vec_perm_const (machine_mode vmode, rtx target, rtx op0,
struct expand_vec_perm_d d;
/* Check whether the mask can be applied to a single vector. */
- if (op0 && rtx_equal_p (op0, op1))
+ if (sel.ninputs () == 1
+ || (op0 && rtx_equal_p (op0, op1)))
d.one_vector_p = true;
else if (sel.all_from_input_p (0))
{
@@ -16200,13 +15973,17 @@ aarch64_expand_movmem (rtx *operands)
/* Convert n to bits to make the rest of the code simpler. */
n = n * BITS_PER_UNIT;
+ /* Maximum amount to copy in one go. The AArch64 back-end has integer modes
+ larger than TImode, but we should not use them for loads/stores here. */
+ const int copy_limit = GET_MODE_BITSIZE (TImode);
+
while (n > 0)
{
/* Find the largest mode in which to do the copy in without over reading
or writing. */
opt_scalar_int_mode mode_iter;
FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_INT)
- if (GET_MODE_BITSIZE (mode_iter.require ()) <= n)
+ if (GET_MODE_BITSIZE (mode_iter.require ()) <= MIN (n, copy_limit))
cur_mode = mode_iter.require ();
gcc_assert (cur_mode != BLKmode);
@@ -16220,10 +15997,10 @@ aarch64_expand_movmem (rtx *operands)
cheaper. i.e. less instructions to do so. For instance doing a 15
byte copy it's more efficient to do two overlapping 8 byte copies than
8 + 6 + 1. */
- next_mode = smallest_mode_for_size (n, MODE_INT);
- int n_bits = GET_MODE_BITSIZE (next_mode).to_constant ();
- if (n > 0 && n_bits > n && n_bits <= 8 * BITS_PER_UNIT)
+ if (n > 0 && n <= 8 * BITS_PER_UNIT)
{
+ next_mode = smallest_mode_for_size (n, MODE_INT);
+ int n_bits = GET_MODE_BITSIZE (next_mode).to_constant ();
src = aarch64_move_pointer (src, (n - n_bits) / BITS_PER_UNIT);
dst = aarch64_move_pointer (dst, (n - n_bits) / BITS_PER_UNIT);
n = n_bits;
@@ -17224,9 +17001,26 @@ aarch64_operands_adjust_ok_for_ldpstp (rtx *operands, bool load,
return false;
}
- /* Check if addresses are clobbered by load. */
- if (load)
- for (int i = 0; i < num_insns; i++)
+ /* Check if the registers are of same class. */
+ rclass = REG_P (reg[0]) && FP_REGNUM_P (REGNO (reg[0]))
+ ? FP_REGS : GENERAL_REGS;
+
+ for (int i = 1; i < num_insns; i++)
+ if (REG_P (reg[i]) && FP_REGNUM_P (REGNO (reg[i])))
+ {
+ if (rclass != FP_REGS)
+ return false;
+ }
+ else
+ {
+ if (rclass != GENERAL_REGS)
+ return false;
+ }
+
+ /* Only the last register in the order in which they occur
+ may be clobbered by the load. */
+ if (rclass == GENERAL_REGS && load)
+ for (int i = 0; i < num_insns - 1; i++)
if (reg_mentioned_p (reg[i], mem[i]))
return false;
@@ -17266,22 +17060,6 @@ aarch64_operands_adjust_ok_for_ldpstp (rtx *operands, bool load,
&& MEM_ALIGN (mem[0]) < 8 * BITS_PER_UNIT)
return false;
- /* Check if the registers are of same class. */
- rclass = REG_P (reg[0]) && FP_REGNUM_P (REGNO (reg[0]))
- ? FP_REGS : GENERAL_REGS;
-
- for (int i = 1; i < num_insns; i++)
- if (REG_P (reg[i]) && FP_REGNUM_P (REGNO (reg[i])))
- {
- if (rclass != FP_REGS)
- return false;
- }
- else
- {
- if (rclass != GENERAL_REGS)
- return false;
- }
-
return true;
}
@@ -17738,6 +17516,45 @@ aarch64_select_early_remat_modes (sbitmap modes)
}
}
+/* Override the default target speculation_safe_value. */
+static rtx
+aarch64_speculation_safe_value (machine_mode mode,
+ rtx result, rtx val, rtx failval)
+{
+ /* Maybe we should warn if falling back to hard barriers. They are
+ likely to be noticably more expensive than the alternative below. */
+ if (!aarch64_track_speculation)
+ return default_speculation_safe_value (mode, result, val, failval);
+
+ if (!REG_P (val))
+ val = copy_to_mode_reg (mode, val);
+
+ if (!aarch64_reg_or_zero (failval, mode))
+ failval = copy_to_mode_reg (mode, failval);
+
+ switch (mode)
+ {
+ case E_QImode:
+ emit_insn (gen_despeculate_copyqi (result, val, failval));
+ break;
+ case E_HImode:
+ emit_insn (gen_despeculate_copyhi (result, val, failval));
+ break;
+ case E_SImode:
+ emit_insn (gen_despeculate_copysi (result, val, failval));
+ break;
+ case E_DImode:
+ emit_insn (gen_despeculate_copydi (result, val, failval));
+ break;
+ case E_TImode:
+ emit_insn (gen_despeculate_copyti (result, val, failval));
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ return result;
+}
+
/* Target-specific selftests. */
#if CHECKING_P
@@ -18210,6 +18027,9 @@ aarch64_libgcc_floating_mode_supported_p
#undef TARGET_SELECT_EARLY_REMAT_MODES
#define TARGET_SELECT_EARLY_REMAT_MODES aarch64_select_early_remat_modes
+#undef TARGET_SPECULATION_SAFE_VALUE
+#define TARGET_SPECULATION_SAFE_VALUE aarch64_speculation_safe_value
+
#if CHECKING_P
#undef TARGET_RUN_TARGET_SELFTESTS
#define TARGET_RUN_TARGET_SELFTESTS selftest::aarch64_run_selftests
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index c121850..e5cdb1d 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -157,9 +157,10 @@ extern unsigned aarch64_architecture_version;
#define AARCH64_FL_SM4 (1 << 17) /* Has ARMv8.4-A SM3 and SM4. */
#define AARCH64_FL_SHA3 (1 << 18) /* Has ARMv8.4-a SHA3 and SHA512. */
#define AARCH64_FL_F16FML (1 << 19) /* Has ARMv8.4-a FP16 extensions. */
+#define AARCH64_FL_RCPC8_4 (1 << 20) /* Has ARMv8.4-a RCPC extensions. */
/* Statistical Profiling extensions. */
-#define AARCH64_FL_PROFILE (1 << 20)
+#define AARCH64_FL_PROFILE (1 << 21)
/* Has FP and SIMD. */
#define AARCH64_FL_FPSIMD (AARCH64_FL_FP | AARCH64_FL_SIMD)
@@ -178,7 +179,7 @@ extern unsigned aarch64_architecture_version;
(AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_V8_3)
#define AARCH64_FL_FOR_ARCH8_4 \
(AARCH64_FL_FOR_ARCH8_3 | AARCH64_FL_V8_4 | AARCH64_FL_F16FML \
- | AARCH64_FL_DOTPROD)
+ | AARCH64_FL_DOTPROD | AARCH64_FL_RCPC8_4)
/* Macros to test ISA flags. */
@@ -199,6 +200,7 @@ extern unsigned aarch64_architecture_version;
#define AARCH64_ISA_SM4 (aarch64_isa_flags & AARCH64_FL_SM4)
#define AARCH64_ISA_SHA3 (aarch64_isa_flags & AARCH64_FL_SHA3)
#define AARCH64_ISA_F16FML (aarch64_isa_flags & AARCH64_FL_F16FML)
+#define AARCH64_ISA_RCPC8_4 (aarch64_isa_flags & AARCH64_FL_RCPC8_4)
/* Crypto is an optional extension to AdvSIMD. */
#define TARGET_CRYPTO (TARGET_SIMD && AARCH64_ISA_CRYPTO)
@@ -480,6 +482,9 @@ extern unsigned aarch64_architecture_version;
#undef DONT_USE_BUILTIN_SETJMP
#define DONT_USE_BUILTIN_SETJMP 1
+#undef TARGET_COMPUTE_FRAME_LAYOUT
+#define TARGET_COMPUTE_FRAME_LAYOUT aarch64_layout_frame
+
/* Register in which the structure value is to be returned. */
#define AARCH64_STRUCT_VALUE_REGNUM R8_REGNUM
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index e9c16f9..7e7ca15 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -57,14 +57,36 @@
(LR_REGNUM 30)
(SP_REGNUM 31)
(V0_REGNUM 32)
+ (V1_REGNUM 33)
+ (V2_REGNUM 34)
+ (V3_REGNUM 35)
(V4_REGNUM 36)
+ (V5_REGNUM 37)
+ (V6_REGNUM 38)
+ (V7_REGNUM 39)
(V8_REGNUM 40)
+ (V9_REGNUM 41)
+ (V10_REGNUM 42)
+ (V11_REGNUM 43)
(V12_REGNUM 44)
+ (V13_REGNUM 45)
+ (V14_REGNUM 46)
(V15_REGNUM 47)
(V16_REGNUM 48)
+ (V17_REGNUM 49)
+ (V18_REGNUM 50)
+ (V19_REGNUM 51)
(V20_REGNUM 52)
+ (V21_REGNUM 53)
+ (V22_REGNUM 54)
+ (V23_REGNUM 55)
(V24_REGNUM 56)
+ (V25_REGNUM 57)
+ (V26_REGNUM 58)
+ (V27_REGNUM 59)
(V28_REGNUM 60)
+ (V29_REGNUM 61)
+ (V30_REGNUM 62)
(V31_REGNUM 63)
(LAST_SAVED_REGNUM 63)
(SFP_REGNUM 64)
@@ -88,6 +110,10 @@
(P13_REGNUM 81)
(P14_REGNUM 82)
(P15_REGNUM 83)
+ ;; A couple of call-clobbered registers that we need to reserve when
+ ;; tracking speculation this is not ABI, so is subject to change.
+ (SPECULATION_TRACKER_REGNUM 15)
+ (SPECULATION_SCRATCH_REGNUM 14)
]
)
@@ -195,6 +221,7 @@
UNSPEC_CLASTB
UNSPEC_FADDA
UNSPEC_REV_SUBREG
+ UNSPEC_SPECULATION_TRACKER
])
(define_c_enum "unspecv" [
@@ -205,6 +232,7 @@
UNSPECV_SET_FPSR ; Represent assign of FPSR content.
UNSPECV_BLOCKAGE ; Represent a blockage
UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing.
+ UNSPECV_SPECULATION_BARRIER ; Represent speculation barrier.
]
)
@@ -231,41 +259,54 @@
;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
;; or TARGET_SIMD.
-;; Attribute that specifies whether or not the instruction touches fp
-;; registers. When this is set to yes for an alternative, that alternative
-;; will be disabled when !TARGET_FLOAT.
-(define_attr "fp" "no,yes" (const_string "no"))
+;; Attributes of the architecture required to support the instruction (or
+;; alternative). This attribute is used to compute attribute "enabled", use type
+;; "any" to enable an alternative in all cases.
-;; Attribute that specifies whether or not the instruction touches half
-;; precision fp registers. When this is set to yes for an alternative,
-;; that alternative will be disabled when !TARGET_FP_F16INST.
-(define_attr "fp16" "no,yes" (const_string "no"))
+(define_enum "arches" [ any rcpc8_4 fp simd sve fp16])
-;; Attribute that specifies whether or not the instruction touches simd
-;; registers. When this is set to yes for an alternative, that alternative
-;; will be disabled when !TARGET_SIMD.
-(define_attr "simd" "no,yes" (const_string "no"))
+(define_enum_attr "arch" "arches" (const_string "any"))
-;; Attribute that specifies whether or not the instruction uses SVE.
-;; When this is set to yes for an alternative, that alternative
-;; will be disabled when !TARGET_SVE.
-(define_attr "sve" "no,yes" (const_string "no"))
+;; [For compatibility with Arm in pipeline models]
+;; Attribute that specifies whether or not the instruction touches fp
+;; registers.
+;; Note that this attribute is not used anywhere in either the arm or aarch64
+;; backends except in the scheduling description for xgene1. In that
+;; scheduling description this attribute is used to subclass the load_4 and
+;; load_8 types.
+(define_attr "fp" "no,yes"
+ (if_then_else
+ (eq_attr "arch" "fp")
+ (const_string "yes")
+ (const_string "no")))
+
+(define_attr "arch_enabled" "no,yes"
+ (if_then_else
+ (ior
+ (eq_attr "arch" "any")
+
+ (and (eq_attr "arch" "rcpc8_4")
+ (match_test "AARCH64_ISA_RCPC8_4"))
+
+ (and (eq_attr "arch" "fp")
+ (match_test "TARGET_FLOAT"))
+
+ (and (eq_attr "arch" "simd")
+ (match_test "TARGET_SIMD"))
+
+ (and (eq_attr "arch" "fp16")
+ (match_test "TARGET_FP_F16INST"))
+
+ (and (eq_attr "arch" "sve")
+ (match_test "TARGET_SVE")))
+ (const_string "yes")
+ (const_string "no")))
;; Attribute that controls whether an alternative is enabled or not.
;; Currently it is only used to disable alternatives which touch fp or simd
-;; registers when -mgeneral-regs-only is specified.
-(define_attr "enabled" "no,yes"
- (cond [(ior
- (and (eq_attr "fp" "yes")
- (eq (symbol_ref "TARGET_FLOAT") (const_int 0)))
- (and (eq_attr "simd" "yes")
- (eq (symbol_ref "TARGET_SIMD") (const_int 0)))
- (and (eq_attr "fp16" "yes")
- (eq (symbol_ref "TARGET_FP_F16INST") (const_int 0)))
- (and (eq_attr "sve" "yes")
- (eq (symbol_ref "TARGET_SVE") (const_int 0))))
- (const_string "no")
- ] (const_string "yes")))
+;; registers when -mgeneral-regs-only is specified or to require a special
+;; architecture support.
+(define_attr "enabled" "no,yes" (attr "arch_enabled"))
;; Attribute that specifies whether we are dealing with a branch to a
;; label that is far away, i.e. further away than the maximum/minimum
@@ -286,6 +327,11 @@
;; no predicated insns.
(define_attr "predicated" "yes,no" (const_string "no"))
+;; Set to true on an insn that requires the speculation tracking state to be
+;; in the tracking register before the insn issues. Otherwise the compiler
+;; may chose to hold the tracking state encoded in SP.
+(define_attr "speculation_barrier" "true,false" (const_string "false"))
+
;; -------------------------------------------------------------------
;; Pipeline descriptions and scheduling
;; -------------------------------------------------------------------
@@ -689,7 +735,7 @@
(const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))]
- ""
+ "!aarch64_track_speculation"
{
if (get_attr_length (insn) == 8)
return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
@@ -719,7 +765,7 @@
(label_ref (match_operand 2 "" ""))
(pc)))
(clobber (reg:CC CC_REGNUM))]
- ""
+ "!aarch64_track_speculation"
{
if (get_attr_length (insn) == 8)
{
@@ -755,7 +801,7 @@
(label_ref (match_operand 1 "" ""))
(pc)))
(clobber (reg:CC CC_REGNUM))]
- ""
+ "!aarch64_track_speculation"
{
if (get_attr_length (insn) == 8)
{
@@ -976,8 +1022,7 @@
;; The "mov_imm" type for CNT is just a placeholder.
[(set_attr "type" "mov_reg,mov_imm,neon_move,mov_imm,load_4,load_4,store_4,
store_4,neon_to_gp<q>,neon_from_gp<q>,neon_dup")
- (set_attr "simd" "*,*,yes,*,*,*,*,*,yes,yes,yes")
- (set_attr "sve" "*,*,*,yes,*,*,*,*,*,*,*")]
+ (set_attr "arch" "*,*,simd,sve,*,*,*,*,simd,simd,simd")]
)
(define_expand "mov<mode>"
@@ -1036,9 +1081,7 @@
;; The "mov_imm" type for CNT is just a placeholder.
[(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,load_4,
load_4,store_4,store_4,adr,adr,f_mcr,f_mrc,fmov,neon_move")
- (set_attr "fp" "*,*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
- (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")
- (set_attr "sve" "*,*,*,*,*,yes,*,*,*,*,*,*,*,*,*,*")]
+ (set_attr "arch" "*,*,*,*,*,sve,*,fp,*,fp,*,*,fp,fp,fp,simd")]
)
(define_insn_and_split "*movdi_aarch64"
@@ -1075,9 +1118,7 @@
[(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,mov_imm,
load_8,load_8,store_8,store_8,adr,adr,f_mcr,f_mrc,fmov,
neon_move")
- (set_attr "fp" "*,*,*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
- (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")
- (set_attr "sve" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,*,*,*")]
+ (set_attr "arch" "*,*,*,*,*,*,sve,*,fp,*,fp,*,*,fp,fp,fp,simd")]
)
(define_insn "insv_imm<mode>"
@@ -1130,8 +1171,7 @@
load_16,store_16,store_16,\
load_16,store_16")
(set_attr "length" "8,8,8,4,4,4,4,4,4")
- (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
- (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
+ (set_attr "arch" "*,*,*,simd,*,*,*,fp,fp")]
)
;; Split a TImode register-register or register-immediate move into
@@ -1185,8 +1225,7 @@
mov\\t%w0, %w1"
[(set_attr "type" "neon_move,f_mcr,neon_move,neon_to_gp, neon_move,fconsts, \
neon_move,f_loads,f_stores,load_4,store_4,mov_reg")
- (set_attr "simd" "yes,*,yes,yes,yes,*,yes,*,*,*,*,*")
- (set_attr "fp16" "*,yes,*,*,*,yes,*,*,*,*,*,*")]
+ (set_attr "arch" "simd,fp16,simd,simd,simd,fp16,simd,*,*,*,*,*")]
)
(define_insn "*movsf_aarch64"
@@ -1210,7 +1249,7 @@
[(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,neon_move,\
f_loads,f_stores,load_4,store_4,mov_reg,\
fconsts")
- (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")]
+ (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
)
(define_insn "*movdf_aarch64"
@@ -1234,7 +1273,7 @@
[(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,neon_move,\
f_loadd,f_stored,load_8,store_8,mov_reg,\
fconstd")
- (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")]
+ (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
)
(define_split
@@ -1279,7 +1318,7 @@
[(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
f_loadd,f_stored,load_16,store_16,store_16")
(set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
- (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")]
+ (set_attr "arch" "simd,*,*,*,simd,*,*,*,*,*,*")]
)
(define_split
@@ -1326,7 +1365,7 @@
ldp\\t%w0, %w2, %1
ldp\\t%s0, %s2, %1"
[(set_attr "type" "load_8,neon_load1_2reg")
- (set_attr "fp" "*,yes")]
+ (set_attr "arch" "*,fp")]
)
;; Storing different modes that can still be merged
@@ -1343,7 +1382,7 @@
ldp\\t%x0, %x2, %1
ldp\\t%d0, %d2, %1"
[(set_attr "type" "load_16,neon_load1_2reg")
- (set_attr "fp" "*,yes")]
+ (set_attr "arch" "*,fp")]
)
;; Operands 0 and 2 are tied together by the final condition; so we allow
@@ -1361,7 +1400,7 @@
stp\\t%w1, %w3, %0
stp\\t%s1, %s3, %0"
[(set_attr "type" "store_8,neon_store1_2reg")
- (set_attr "fp" "*,yes")]
+ (set_attr "arch" "*,fp")]
)
;; Storing different modes that can still be merged
@@ -1378,7 +1417,7 @@
stp\\t%x1, %x3, %0
stp\\t%d1, %d3, %0"
[(set_attr "type" "store_16,neon_store1_2reg")
- (set_attr "fp" "*,yes")]
+ (set_attr "arch" "*,fp")]
)
;; Load pair with post-index writeback. This is primarily used in function
@@ -1604,7 +1643,7 @@
* return aarch64_output_sve_addvl_addpl (operands[0], operands[1], operands[2]);"
;; The "alu_imm" type for ADDVL/ADDPL is just a placeholder.
[(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple,alu_imm")
- (set_attr "simd" "*,*,yes,*,*,*")]
+ (set_attr "arch" "*,*,simd,*,*,*")]
)
;; zero_extend version of above
@@ -2418,7 +2457,7 @@
(plus:GPI
(match_operand:GPI 3 "aarch64_carry_operation" "")
(match_dup 1)))))
- (set (match_operand:GPI 0 "register_operand")
+ (set (match_operand:GPI 0 "register_operand" "=r")
(plus:GPI (match_dup 3) (match_dup 1)))]
""
"adcs\\t%<w>0, %<w>1, <w>zr"
@@ -2439,7 +2478,7 @@
(match_operand:GPI 4 "aarch64_carry_operation" "")
(match_dup 1))
(match_dup 2)))))
- (set (match_operand:GPI 0 "register_operand")
+ (set (match_operand:GPI 0 "register_operand" "=r")
(plus:GPI
(plus:GPI (match_dup 4) (match_dup 1))
(match_dup 2)))]
@@ -2484,7 +2523,7 @@
(plus:GPI
(match_operand:GPI 3 "aarch64_carry_operation" "")
(match_dup 1)))))
- (set (match_operand:GPI 0 "register_operand")
+ (set (match_operand:GPI 0 "register_operand" "=r")
(plus:GPI (match_dup 3) (match_dup 1)))]
""
"adcs\\t%<w>0, %<w>1, <w>zr"
@@ -2505,7 +2544,7 @@
(match_operand:GPI 4 "aarch64_carry_operation" "")
(match_dup 1))
(match_dup 2)))))
- (set (match_operand:GPI 0 "register_operand")
+ (set (match_operand:GPI 0 "register_operand" "=r")
(plus:GPI
(plus:GPI (match_dup 4) (match_dup 1))
(match_dup 2)))]
@@ -2607,7 +2646,7 @@
sub\\t%x0, %x1, %x2
sub\\t%d0, %d1, %d2"
[(set_attr "type" "alu_sreg, neon_sub")
- (set_attr "simd" "*,yes")]
+ (set_attr "arch" "*,simd")]
)
(define_expand "subv<mode>4"
@@ -3214,7 +3253,7 @@
neg\\t%<w>0, %<w>1
neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
[(set_attr "type" "alu_sreg, neon_neg<q>")
- (set_attr "simd" "*,yes")]
+ (set_attr "arch" "*,simd")]
)
;; zero_extend version of above
@@ -3539,7 +3578,7 @@
(define_insn "cmp<mode>"
[(set (reg:CC CC_REGNUM)
- (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r")
+ (compare:CC (match_operand:GPI 0 "register_operand" "rk,rk,rk")
(match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
""
"@
@@ -4059,7 +4098,7 @@
<logical>\\t%<w>0, %<w>1, %2
<logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
[(set_attr "type" "logic_reg,logic_imm,neon_logic")
- (set_attr "simd" "*,*,yes")]
+ (set_attr "arch" "*,*,simd")]
)
;; zero_extend version of above
@@ -4193,7 +4232,7 @@
mvn\\t%<w>0, %<w>1
mvn\\t%0.8b, %1.8b"
[(set_attr "type" "logic_reg,neon_logic")
- (set_attr "simd" "*,yes")]
+ (set_attr "arch" "*,simd")]
)
(define_insn "*one_cmpl_<optab><mode>2"
@@ -4216,7 +4255,7 @@
<NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
<NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
[(set_attr "type" "logic_reg,neon_logic")
- (set_attr "simd" "*,yes")]
+ (set_attr "arch" "*,simd")]
)
(define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
@@ -4256,7 +4295,7 @@
(set (match_dup 0) (not:GPI (match_dup 0)))]
""
[(set_attr "type" "logic_reg,multiple")
- (set_attr "simd" "*,yes")]
+ (set_attr "arch" "*,simd")]
)
(define_insn "*and_one_cmpl<mode>3_compare0"
@@ -4800,8 +4839,8 @@
lsl\t%<w>0, %<w>1, %<w>2
shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
- [(set_attr "simd" "no,no,yes,yes")
- (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")]
+ [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")
+ (set_attr "arch" "*,*,simd,simd")]
)
;; Logical right shift using SISD or Integer instruction
@@ -4818,8 +4857,8 @@
ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
#
#"
- [(set_attr "simd" "no,no,yes,yes,yes")
- (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
+ [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")
+ (set_attr "arch" "*,*,simd,simd,simd")]
)
(define_split
@@ -4866,8 +4905,8 @@
sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
#
#"
- [(set_attr "simd" "no,no,yes,yes,yes")
- (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
+ [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")
+ (set_attr "arch" "*,*,simd,simd,simd")]
)
(define_split
@@ -4907,8 +4946,7 @@
UNSPEC_SISD_USHL))]
"TARGET_SIMD"
"ushl\t%d0, %d1, %d2"
- [(set_attr "simd" "yes")
- (set_attr "type" "neon_shift_reg")]
+ [(set_attr "type" "neon_shift_reg")]
)
(define_insn "*aarch64_ushl_2s"
@@ -4918,8 +4956,7 @@
UNSPEC_USHL_2S))]
"TARGET_SIMD"
"ushl\t%0.2s, %1.2s, %2.2s"
- [(set_attr "simd" "yes")
- (set_attr "type" "neon_shift_reg")]
+ [(set_attr "type" "neon_shift_reg")]
)
(define_insn "*aarch64_sisd_sshl"
@@ -4929,8 +4966,7 @@
UNSPEC_SISD_SSHL))]
"TARGET_SIMD"
"sshl\t%d0, %d1, %d2"
- [(set_attr "simd" "yes")
- (set_attr "type" "neon_shift_reg")]
+ [(set_attr "type" "neon_shift_reg")]
)
(define_insn "*aarch64_sshl_2s"
@@ -4940,8 +4976,7 @@
UNSPEC_SSHL_2S))]
"TARGET_SIMD"
"sshl\t%0.2s, %1.2s, %2.2s"
- [(set_attr "simd" "yes")
- (set_attr "type" "neon_shift_reg")]
+ [(set_attr "type" "neon_shift_reg")]
)
(define_insn "*aarch64_sisd_neg_qi"
@@ -4950,8 +4985,7 @@
UNSPEC_SISD_NEG))]
"TARGET_SIMD"
"neg\t%d0, %d1"
- [(set_attr "simd" "yes")
- (set_attr "type" "neon_neg")]
+ [(set_attr "type" "neon_neg")]
)
;; Rotate right
@@ -5305,6 +5339,58 @@
[(set_attr "type" "rev")]
)
+(define_insn "*aarch64_bfxil<mode>"
+ [(set (match_operand:GPI 0 "register_operand" "=r,r")
+ (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "r,0")
+ (match_operand:GPI 3 "const_int_operand" "n, Ulc"))
+ (and:GPI (match_operand:GPI 2 "register_operand" "0,r")
+ (match_operand:GPI 4 "const_int_operand" "Ulc, n"))))]
+ "(INTVAL (operands[3]) == ~INTVAL (operands[4]))
+ && (aarch64_high_bits_all_ones_p (INTVAL (operands[3]))
+ || aarch64_high_bits_all_ones_p (INTVAL (operands[4])))"
+ {
+ switch (which_alternative)
+ {
+ case 0:
+ operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[3])));
+ return "bfxil\\t%<w>0, %<w>1, 0, %3";
+ case 1:
+ operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[4])));
+ return "bfxil\\t%<w>0, %<w>2, 0, %3";
+ default:
+ gcc_unreachable ();
+ }
+ }
+ [(set_attr "type" "bfm")]
+)
+
+; Zero-extended version of above (aarch64_bfxil)
+(define_insn "*aarch64_bfxilsi_uxtw"
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (zero_extend:DI (ior:SI (and:SI (match_operand:SI 1 "register_operand"
+ "r,0")
+ (match_operand:SI 3 "const_int_operand" "n, Ulc"))
+ (and:SI (match_operand:SI 2 "register_operand" "0,r")
+ (match_operand:SI 4 "const_int_operand" "Ulc, n")))))]
+ "(INTVAL (operands[3]) == ~INTVAL (operands[4]))
+ && (aarch64_high_bits_all_ones_p (INTVAL (operands[3]))
+ || aarch64_high_bits_all_ones_p (INTVAL (operands[4])))"
+ {
+ switch (which_alternative)
+ {
+ case 0:
+ operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[3])));
+ return "bfxil\\t%0, %1, 0, %3";
+ case 1:
+ operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[4])));
+ return "bfxil\\t%0, %2, 0, %3";
+ default:
+ gcc_unreachable ();
+ }
+ }
+ [(set_attr "type" "bfm")]
+)
+
;; There are no canonicalisation rules for the position of the lshiftrt, ashift
;; operations within an IOR/AND RTX, therefore we have two patterns matching
;; each valid permutation.
@@ -5587,9 +5673,8 @@
"@
<su_optab>cvtf\t%<GPF:s>0, %<s>1
<su_optab>cvtf\t%<GPF:s>0, %<w1>1"
- [(set_attr "simd" "yes,no")
- (set_attr "fp" "no,yes")
- (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
+ [(set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")
+ (set_attr "arch" "simd,fp")]
)
(define_insn "<optab><fcvt_iesize><GPF:mode>2"
@@ -5674,8 +5759,7 @@
<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2
<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2"
[(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
- (set_attr "fp" "yes, *")
- (set_attr "simd" "*, yes")]
+ (set_attr "arch" "fp,simd")]
)
(define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3"
@@ -5688,8 +5772,7 @@
<FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2
<FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2"
[(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
- (set_attr "fp" "yes, *")
- (set_attr "simd" "*, yes")]
+ (set_attr "arch" "fp,simd")]
)
(define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3"
@@ -5978,7 +6061,7 @@
;; -------------------------------------------------------------------
;; Reload Scalar Floating point modes from constant pool.
;; The AArch64 port doesn't have __int128 constant move support.
-(define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
+(define_expand "@aarch64_reload_movcp<GPF_TF:mode><P:mode>"
[(set (match_operand:GPF_TF 0 "register_operand" "=w")
(mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
(clobber (match_operand:P 2 "register_operand" "=&r"))]
@@ -5991,7 +6074,7 @@
)
;; Reload Vector modes from constant pool.
-(define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
+(define_expand "@aarch64_reload_movcp<VALL:mode><P:mode>"
[(set (match_operand:VALL 0 "register_operand" "=w")
(mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
(clobber (match_operand:P 2 "register_operand" "=&r"))]
@@ -6003,7 +6086,7 @@
}
)
-(define_expand "aarch64_reload_mov<mode>"
+(define_expand "@aarch64_reload_mov<mode>"
[(set (match_operand:TX 0 "register_operand" "=w")
(match_operand:TX 1 "register_operand" "w"))
(clobber (match_operand:DI 2 "register_operand" "=&r"))
@@ -6023,7 +6106,7 @@
;; after or during reload as we don't want these patterns to start
;; kicking in during the combiner.
-(define_insn "aarch64_movdi_<mode>low"
+(define_insn "@aarch64_movdi_<mode>low"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extract:DI (match_operand:TX 1 "register_operand" "w")
(const_int 64) (const_int 0)))]
@@ -6033,7 +6116,7 @@
(set_attr "length" "4")
])
-(define_insn "aarch64_movdi_<mode>high"
+(define_insn "@aarch64_movdi_<mode>high"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extract:DI (match_operand:TX 1 "register_operand" "w")
(const_int 64) (const_int 64)))]
@@ -6043,7 +6126,7 @@
(set_attr "length" "4")
])
-(define_insn "aarch64_mov<mode>high_di"
+(define_insn "@aarch64_mov<mode>high_di"
[(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
(const_int 64) (const_int 64))
(zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
@@ -6053,7 +6136,7 @@
(set_attr "length" "4")
])
-(define_insn "aarch64_mov<mode>low_di"
+(define_insn "@aarch64_mov<mode>low_di"
[(set (match_operand:TX 0 "register_operand" "=w")
(zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
"TARGET_FLOAT && (reload_completed || reload_in_progress)"
@@ -6302,24 +6385,47 @@
[(set_attr "type" "call")
(set_attr "length" "16")])
-;; For SVE, model tlsdesc calls as clobbering all vector and predicate
-;; registers, on top of the usual R0 and LR. In reality the calls
-;; preserve the low 128 bits of the vector registers, but we don't
-;; yet have a way of representing that in the instruction pattern.
+;; For SVE, model tlsdesc calls as clobbering the lower 128 bits of
+;; all vector registers, and clobber all predicate registers, on
+;; top of the usual R0 and LR.
(define_insn "tlsdesc_small_sve_<mode>"
[(set (reg:PTR R0_REGNUM)
(unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
UNSPEC_TLSDESC))
(clobber (reg:DI LR_REGNUM))
(clobber (reg:CC CC_REGNUM))
- (clobber (reg:XI V0_REGNUM))
- (clobber (reg:XI V4_REGNUM))
- (clobber (reg:XI V8_REGNUM))
- (clobber (reg:XI V12_REGNUM))
- (clobber (reg:XI V16_REGNUM))
- (clobber (reg:XI V20_REGNUM))
- (clobber (reg:XI V24_REGNUM))
- (clobber (reg:XI V28_REGNUM))
+ (clobber_high (reg:TI V0_REGNUM))
+ (clobber_high (reg:TI V1_REGNUM))
+ (clobber_high (reg:TI V2_REGNUM))
+ (clobber_high (reg:TI V3_REGNUM))
+ (clobber_high (reg:TI V4_REGNUM))
+ (clobber_high (reg:TI V5_REGNUM))
+ (clobber_high (reg:TI V6_REGNUM))
+ (clobber_high (reg:TI V7_REGNUM))
+ (clobber_high (reg:TI V8_REGNUM))
+ (clobber_high (reg:TI V9_REGNUM))
+ (clobber_high (reg:TI V10_REGNUM))
+ (clobber_high (reg:TI V11_REGNUM))
+ (clobber_high (reg:TI V12_REGNUM))
+ (clobber_high (reg:TI V13_REGNUM))
+ (clobber_high (reg:TI V14_REGNUM))
+ (clobber_high (reg:TI V15_REGNUM))
+ (clobber_high (reg:TI V16_REGNUM))
+ (clobber_high (reg:TI V17_REGNUM))
+ (clobber_high (reg:TI V18_REGNUM))
+ (clobber_high (reg:TI V19_REGNUM))
+ (clobber_high (reg:TI V20_REGNUM))
+ (clobber_high (reg:TI V21_REGNUM))
+ (clobber_high (reg:TI V22_REGNUM))
+ (clobber_high (reg:TI V23_REGNUM))
+ (clobber_high (reg:TI V24_REGNUM))
+ (clobber_high (reg:TI V25_REGNUM))
+ (clobber_high (reg:TI V26_REGNUM))
+ (clobber_high (reg:TI V27_REGNUM))
+ (clobber_high (reg:TI V28_REGNUM))
+ (clobber_high (reg:TI V29_REGNUM))
+ (clobber_high (reg:TI V30_REGNUM))
+ (clobber_high (reg:TI V31_REGNUM))
(clobber (reg:VNx2BI P0_REGNUM))
(clobber (reg:VNx2BI P1_REGNUM))
(clobber (reg:VNx2BI P2_REGNUM))
@@ -6548,12 +6654,134 @@
DONE;
})
+;; Track speculation through conditional branches. We assume that
+;; SPECULATION_TRACKER_REGNUM is reserved for this purpose when necessary.
+(define_insn "speculation_tracker"
+ [(set (reg:DI SPECULATION_TRACKER_REGNUM)
+ (unspec [(reg:DI SPECULATION_TRACKER_REGNUM) (match_operand 0)]
+ UNSPEC_SPECULATION_TRACKER))]
+ ""
+ {
+ operands[1] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
+ output_asm_insn ("csel\\t%1, %1, xzr, %m0", operands);
+ return "";
+ }
+ [(set_attr "type" "csel")]
+)
+
;; Helper for aarch64.c code.
(define_expand "set_clobber_cc"
[(parallel [(set (match_operand 0)
(match_operand 1))
(clobber (reg:CC CC_REGNUM))])])
+;; Hard speculation barrier.
+(define_insn "speculation_barrier"
+ [(unspec_volatile [(const_int 0)] UNSPECV_SPECULATION_BARRIER)]
+ ""
+ "isb\;dsb\\tsy"
+ [(set_attr "length" "8")
+ (set_attr "type" "block")
+ (set_attr "speculation_barrier" "true")]
+)
+
+;; Support for __builtin_speculation_safe_value when we have speculation
+;; tracking enabled. Use the speculation tracker to decide whether to
+;; copy operand 1 to the target, or to copy the fail value (operand 2).
+(define_expand "despeculate_copy<ALLI_TI:mode>"
+ [(set (match_operand:ALLI_TI 0 "register_operand" "=r")
+ (unspec_volatile:ALLI_TI
+ [(match_operand:ALLI_TI 1 "register_operand" "r")
+ (match_operand:ALLI_TI 2 "aarch64_reg_or_zero" "rZ")
+ (use (reg:DI SPECULATION_TRACKER_REGNUM))
+ (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
+ ""
+ "
+ {
+ if (operands[2] == const0_rtx)
+ {
+ rtx tracker;
+ if (<MODE>mode == TImode)
+ tracker = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
+ else
+ tracker = gen_rtx_REG (<MODE>mode, SPECULATION_TRACKER_REGNUM);
+
+ emit_insn (gen_despeculate_simple<mode> (operands[0], operands[1],
+ tracker));
+ DONE;
+ }
+ }
+ "
+)
+
+;; Patterns to match despeculate_copy<mode>. Note that "hint 0x14" is the
+;; encoding for CSDB, but will work in older versions of the assembler.
+(define_insn "*despeculate_copy<ALLI:mode>_insn"
+ [(set (match_operand:ALLI 0 "register_operand" "=r")
+ (unspec_volatile:ALLI
+ [(match_operand:ALLI 1 "register_operand" "r")
+ (match_operand:ALLI 2 "aarch64_reg_or_zero" "rZ")
+ (use (reg:DI SPECULATION_TRACKER_REGNUM))
+ (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
+ ""
+ {
+ operands[3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
+ output_asm_insn ("cmp\\t%3, #0\;csel\\t%<w>0, %<w>1, %<w>2, ne\;hint\t0x14 // csdb",
+ operands);
+ return "";
+ }
+ [(set_attr "length" "12")
+ (set_attr "type" "block")
+ (set_attr "speculation_barrier" "true")]
+)
+
+;; Pattern to match despeculate_copyti
+(define_insn "*despeculate_copyti_insn"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (unspec_volatile:TI
+ [(match_operand:TI 1 "register_operand" "r")
+ (match_operand:TI 2 "aarch64_reg_or_zero" "rZ")
+ (use (reg:DI SPECULATION_TRACKER_REGNUM))
+ (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
+ ""
+ {
+ operands[3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
+ output_asm_insn
+ ("cmp\\t%3, #0\;csel\\t%0, %1, %2, ne\;csel\\t%H0, %H1, %H2, ne\;hint\t0x14 // csdb",
+ operands);
+ return "";
+ }
+ [(set_attr "length" "16")
+ (set_attr "type" "block")
+ (set_attr "speculation_barrier" "true")]
+)
+
+(define_insn "despeculate_simple<ALLI:mode>"
+ [(set (match_operand:ALLI 0 "register_operand" "=r")
+ (unspec_volatile:ALLI
+ [(match_operand:ALLI 1 "register_operand" "r")
+ (use (match_operand:ALLI 2 "register_operand" ""))]
+ UNSPECV_SPECULATION_BARRIER))]
+ ""
+ "and\\t%<w>0, %<w>1, %<w>2\;hint\t0x14 // csdb"
+ [(set_attr "type" "block")
+ (set_attr "length" "8")
+ (set_attr "speculation_barrier" "true")]
+)
+
+(define_insn "despeculate_simpleti"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (unspec_volatile:TI
+ [(match_operand:TI 1 "register_operand" "r")
+ (use (match_operand:DI 2 "register_operand" ""))]
+ UNSPECV_SPECULATION_BARRIER))]
+ ""
+ "and\\t%0, %1, %2\;and\\t%H0, %H1, %2\;hint\t0x14 // csdb"
+ [(set_attr "type" "block")
+ (set_attr "length" "12")
+ (set_attr "speculation_barrier" "true")]
+)
+
;; AdvSIMD Stuff
(include "aarch64-simd.md")
diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
index 1426b45..b2e80cb 100644
--- a/gcc/config/aarch64/aarch64.opt
+++ b/gcc/config/aarch64/aarch64.opt
@@ -117,23 +117,23 @@ Enum(aarch64_tls_size) String(48) Value(48)
march=
Target RejectNegative ToLower Joined Var(aarch64_arch_string)
--march=ARCH Use features of architecture ARCH.
+Use features of architecture ARCH.
mcpu=
Target RejectNegative ToLower Joined Var(aarch64_cpu_string)
--mcpu=CPU Use features of and optimize for CPU.
+Use features of and optimize for CPU.
mtune=
Target RejectNegative ToLower Joined Var(aarch64_tune_string)
--mtune=CPU Optimize for CPU.
+Optimize for CPU.
mabi=
Target RejectNegative Joined Enum(aarch64_abi) Var(aarch64_abi) Init(AARCH64_ABI_DEFAULT)
--mabi=ABI Generate code that conforms to the specified ABI.
+Generate code that conforms to the specified ABI.
moverride=
Target RejectNegative ToLower Joined Var(aarch64_override_tune_string)
--moverride=STRING Power users only! Override CPU optimization parameters.
+-moverride=<string> Power users only! Override CPU optimization parameters.
Enum
Name(aarch64_abi) Type(int)
@@ -167,20 +167,20 @@ EnumValue
Enum(aarch64_ra_sign_scope_t) String(all) Value(AARCH64_FUNCTION_ALL)
mlow-precision-recip-sqrt
-Common Var(flag_mrecip_low_precision_sqrt) Optimization
+Target Var(flag_mrecip_low_precision_sqrt) Optimization
Enable the reciprocal square root approximation. Enabling this reduces
precision of reciprocal square root results to about 16 bits for
single precision and to 32 bits for double precision.
mlow-precision-sqrt
-Common Var(flag_mlow_precision_sqrt) Optimization
+Target Var(flag_mlow_precision_sqrt) Optimization
Enable the square root approximation. Enabling this reduces
precision of square root results to about 16 bits for
single precision and to 32 bits for double precision.
If enabled, it implies -mlow-precision-recip-sqrt.
mlow-precision-div
-Common Var(flag_mlow_precision_div) Optimization
+Target Var(flag_mlow_precision_div) Optimization
Enable the division approximation. Enabling this reduces
precision of division results to about 16 bits for
single precision and to 32 bits for double precision.
@@ -209,8 +209,12 @@ Enum(sve_vector_bits) String(2048) Value(SVE_2048)
msve-vector-bits=
Target RejectNegative Joined Enum(sve_vector_bits) Var(aarch64_sve_vector_bits) Init(SVE_SCALABLE)
--msve-vector-bits=N Set the number of bits in an SVE vector register to N.
+-msve-vector-bits=<number> Set the number of bits in an SVE vector register to N.
mverbose-cost-dump
-Common Undocumented Var(flag_aarch64_verbose_cost)
+Target Undocumented Var(flag_aarch64_verbose_cost)
Enables verbose cost model dumping in the debug dump files.
+
+mtrack-speculation
+Target Var(aarch64_track_speculation)
+Generate code to track when the CPU might be speculating incorrectly.
diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h
index 2d18400..fc734e1 100644
--- a/gcc/config/aarch64/arm_neon.h
+++ b/gcc/config/aarch64/arm_neon.h
@@ -11822,6 +11822,18 @@ vabsq_s64 (int64x2_t __a)
return __builtin_aarch64_absv2di (__a);
}
+/* Try to avoid moving between integer and vector registers.
+ For why the cast to unsigned is needed check the vnegd_s64 intrinsic.
+ There is a testcase related to this issue:
+ gcc.target/aarch64/vabsd_s64.c. */
+
+__extension__ extern __inline int64_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vabsd_s64 (int64_t __a)
+{
+ return __a < 0 ? - (uint64_t) __a : __a;
+}
+
/* vadd */
__extension__ extern __inline int64_t
@@ -22907,6 +22919,25 @@ vneg_s64 (int64x1_t __a)
return -__a;
}
+/* According to the ACLE, the negative of the minimum (signed)
+ value is itself. This leads to a semantics mismatch, as this is
+ undefined behaviour in C. The value range predictor is not
+ aware that the negation of a negative number can still be negative
+ and it may try to fold the expression. See the test in
+ gcc.target/aarch64/vnegd_s64.c for an example.
+
+ The cast below tricks the value range predictor to include
+ INT64_MIN in the range it computes. So for x in the range
+ [INT64_MIN, y] the range prediction after vnegd_s64 (x) will
+ be ~[INT64_MIN + 1, y]. */
+
+__extension__ extern __inline int64_t
+__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
+vnegd_s64 (int64_t __a)
+{
+ return - (uint64_t) __a;
+}
+
__extension__ extern __inline float32x4_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vnegq_f32 (float32x4_t __a)
diff --git a/gcc/config/aarch64/atomics.md b/gcc/config/aarch64/atomics.md
index cd8c44e..bba8e9e 100644
--- a/gcc/config/aarch64/atomics.md
+++ b/gcc/config/aarch64/atomics.md
@@ -20,7 +20,7 @@
;; Instruction patterns.
-(define_expand "atomic_compare_and_swap<mode>"
+(define_expand "@atomic_compare_and_swap<mode>"
[(match_operand:SI 0 "register_operand" "") ;; bool out
(match_operand:ALLI 1 "register_operand" "") ;; val out
(match_operand:ALLI 2 "aarch64_sync_memory_operand" "") ;; memory
@@ -36,7 +36,7 @@
}
)
-(define_insn_and_split "aarch64_compare_and_swap<mode>"
+(define_insn_and_split "@aarch64_compare_and_swap<mode>"
[(set (reg:CC CC_REGNUM) ;; bool out
(unspec_volatile:CC [(const_int 0)] UNSPECV_ATOMIC_CMPSW))
(set (match_operand:SI 0 "register_operand" "=&r") ;; val out
@@ -61,7 +61,7 @@
}
)
-(define_insn_and_split "aarch64_compare_and_swap<mode>"
+(define_insn_and_split "@aarch64_compare_and_swap<mode>"
[(set (reg:CC CC_REGNUM) ;; bool out
(unspec_volatile:CC [(const_int 0)] UNSPECV_ATOMIC_CMPSW))
(set (match_operand:GPI 0 "register_operand" "=&r") ;; val out
@@ -85,7 +85,7 @@
}
)
-(define_insn_and_split "aarch64_compare_and_swap<mode>_lse"
+(define_insn_and_split "@aarch64_compare_and_swap<mode>_lse"
[(set (reg:CC CC_REGNUM) ;; bool out
(unspec_volatile:CC [(const_int 0)] UNSPECV_ATOMIC_CMPSW))
(set (match_operand:SI 0 "register_operand" "=&r") ;; val out
@@ -111,7 +111,7 @@
}
)
-(define_insn_and_split "aarch64_compare_and_swap<mode>_lse"
+(define_insn_and_split "@aarch64_compare_and_swap<mode>_lse"
[(set (reg:CC CC_REGNUM) ;; bool out
(unspec_volatile:CC [(const_int 0)] UNSPECV_ATOMIC_CMPSW))
(set (match_operand:GPI 0 "register_operand" "=&r") ;; val out
@@ -481,9 +481,9 @@
)
(define_insn "atomic_store<mode>"
- [(set (match_operand:ALLI 0 "aarch64_sync_memory_operand" "=Q")
+ [(set (match_operand:ALLI 0 "aarch64_rcpc_memory_operand" "=Q,Ust")
(unspec_volatile:ALLI
- [(match_operand:ALLI 1 "general_operand" "rZ")
+ [(match_operand:ALLI 1 "general_operand" "rZ,rZ")
(match_operand:SI 2 "const_int_operand")] ;; model
UNSPECV_STL))]
""
@@ -491,12 +491,15 @@
enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
if (is_mm_relaxed (model) || is_mm_consume (model) || is_mm_acquire (model))
return "str<atomic_sfx>\t%<w>1, %0";
- else
+ else if (which_alternative == 0)
return "stlr<atomic_sfx>\t%<w>1, %0";
+ else
+ return "stlur<atomic_sfx>\t%<w>1, %0";
}
+ [(set_attr "arch" "*,rcpc8_4")]
)
-(define_insn "aarch64_load_exclusive<mode>"
+(define_insn "@aarch64_load_exclusive<mode>"
[(set (match_operand:SI 0 "register_operand" "=r")
(zero_extend:SI
(unspec_volatile:SHORT
@@ -513,7 +516,7 @@
}
)
-(define_insn "aarch64_load_exclusive<mode>"
+(define_insn "@aarch64_load_exclusive<mode>"
[(set (match_operand:GPI 0 "register_operand" "=r")
(unspec_volatile:GPI
[(match_operand:GPI 1 "aarch64_sync_memory_operand" "Q")
@@ -529,7 +532,7 @@
}
)
-(define_insn "aarch64_store_exclusive<mode>"
+(define_insn "@aarch64_store_exclusive<mode>"
[(set (match_operand:SI 0 "register_operand" "=&r")
(unspec_volatile:SI [(const_int 0)] UNSPECV_SX))
(set (match_operand:ALLI 1 "aarch64_sync_memory_operand" "=Q")
@@ -586,7 +589,7 @@
;; ARMv8.1-A LSE instructions.
;; Atomic swap with memory.
-(define_insn "aarch64_atomic_swp<mode>"
+(define_insn "@aarch64_atomic_swp<mode>"
[(set (match_operand:ALLI 0 "register_operand" "+&r")
(match_operand:ALLI 1 "aarch64_sync_memory_operand" "+Q"))
(set (match_dup 1)
@@ -609,7 +612,7 @@
;; Atomic compare-and-swap: HI and smaller modes.
-(define_insn "aarch64_atomic_cas<mode>"
+(define_insn "@aarch64_atomic_cas<mode>"
[(set (match_operand:SI 0 "register_operand" "+&r") ;; out
(zero_extend:SI
(match_operand:SHORT 1 "aarch64_sync_memory_operand" "+Q"))) ;; memory.
@@ -634,7 +637,7 @@
;; Atomic compare-and-swap: SI and larger modes.
-(define_insn "aarch64_atomic_cas<mode>"
+(define_insn "@aarch64_atomic_cas<mode>"
[(set (match_operand:GPI 0 "register_operand" "+&r") ;; out
(match_operand:GPI 1 "aarch64_sync_memory_operand" "+Q")) ;; memory.
(set (match_dup 1)
@@ -658,7 +661,7 @@
;; Atomic load-op: Load data, operate, store result, keep data.
-(define_insn "aarch64_atomic_load<atomic_ldop><mode>"
+(define_insn "@aarch64_atomic_load<atomic_ldop><mode>"
[(set (match_operand:ALLI 0 "register_operand" "=r")
(match_operand:ALLI 1 "aarch64_sync_memory_operand" "+Q"))
(set (match_dup 1)
diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md
index 72cacda..99dac3b 100644
--- a/gcc/config/aarch64/constraints.md
+++ b/gcc/config/aarch64/constraints.md
@@ -172,6 +172,13 @@
A constraint that matches the immediate constant -1."
(match_test "op == constm1_rtx"))
+(define_constraint "Ulc"
+ "@internal
+ A constraint that matches a constant integer whose bits are consecutive ones
+ from the MSB."
+ (and (match_code "const_int")
+ (match_test "aarch64_high_bits_all_ones_p (ival)")))
+
(define_constraint "Usv"
"@internal
A constraint that matches a VG-based constant that can be loaded by
@@ -218,6 +225,11 @@
(and (match_code "mem")
(match_test "REG_P (XEXP (op, 0))")))
+(define_memory_constraint "Ust"
+ "@internal
+ A memory address with 9bit unscaled offset."
+ (match_operand 0 "aarch64_9bit_offset_memory_operand"))
+
(define_memory_constraint "Ump"
"@internal
A memory address suitable for a load/store pair operation."
diff --git a/gcc/config/aarch64/falkor-tag-collision-avoidance.c b/gcc/config/aarch64/falkor-tag-collision-avoidance.c
new file mode 100644
index 0000000..518954f
--- /dev/null
+++ b/gcc/config/aarch64/falkor-tag-collision-avoidance.c
@@ -0,0 +1,881 @@
+/* Tag Collision Avoidance pass for Falkor.
+ Copyright (C) 2018 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/>. */
+
+#define IN_TARGET_CODE 1
+
+#include "config.h"
+#define INCLUDE_LIST
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "target.h"
+#include "rtl.h"
+#include "tree.h"
+#include "tree-pass.h"
+#include "aarch64-protos.h"
+#include "hash-map.h"
+#include "cfgloop.h"
+#include "cfgrtl.h"
+#include "rtl-iter.h"
+#include "df.h"
+#include "memmodel.h"
+#include "optabs.h"
+#include "regs.h"
+#include "recog.h"
+#include "regrename.h"
+#include "print-rtl.h"
+
+/* The Falkor hardware prefetching system uses the encoding of the registers
+ and offsets of loads to decide which of the multiple hardware prefetchers to
+ assign the load to. This has the positive effect of accelerating prefetches
+ when all related loads with uniform strides are assigned to the same
+ prefetcher unit. The down side is that because of the way the assignment
+ works, multiple unrelated loads may end up on the same prefetch unit, thus
+ causing the unit to bounce between different sets of addresses and never
+ train correctly. The point of this pass is to avoid such collisions so that
+ unrelated loads are spread out to different prefetchers. It also makes a
+ rudimentary attempt to ensure that related loads with the same tags don't
+ get moved out unnecessarily.
+
+ Perhaps a future enhancement would be to make a more concerted attempt to
+ get related loads under the same tag. See the memcpy/memset implementation
+ for falkor in glibc to understand the kind of impact this can have on
+ falkor.
+
+ The assignment of loads is based on a tag that is computed from the encoding
+ of the first destination register (the only destination in case of LDR), the
+ base register and the offset (either the register or the immediate value, as
+ encoded in the instruction). This is what the 14 bit tag looks like:
+
+ |<- 6 bits ->|<- 4b ->|<- 4b ->|
+ --------------------------------
+ | OFFSET | SRC | DST |
+ --------------------------------
+
+ For all cases, the SRC and DST are the 4 LSB of the encoding of the register
+ in the instruction. Offset computation is more involved and is as follows:
+
+ - For register offset addressing: 4 LSB of the offset register with the MSB
+ of the 6 bits set to 1.
+
+ - For immediate offset: 4 LSB of the encoded immediate offset. The encoding
+ depends on the width of the load and is expressed as multiples of the
+ width.
+
+ - For loads with update: 4 LSB of the offset. The encoding here is the
+ exact number by which the base is offset and incremented.
+
+ Based on the above it is clear that registers 0 and 16 will result in
+ collisions, 1 and 17 and so on. This pass detects such collisions within a
+ def/use chain of the source register in a loop and tries to resolve the
+ collision by renaming one of the destination registers. */
+
+/* Get the destination part of the tag. */
+#define TAG_GET_DEST(__tag) ((__tag) & 0xf)
+
+/* Get the tag with the destination part updated. */
+#define TAG_UPDATE_DEST(__tag, __dest) (((__tag) & ~0xf) | (__dest & 0xf))
+
+#define MAX_PREFETCH_STRIDE 2048
+
+/* The instruction information structure. This is used to cache information
+ about the INSN that we derive when traversing through all of the insns in
+ loops. */
+class tag_insn_info
+{
+public:
+ rtx_insn *insn;
+ rtx dest;
+ rtx base;
+ rtx offset;
+ bool writeback;
+ bool ldp;
+
+ tag_insn_info (rtx_insn *i, rtx d, rtx b, rtx o, bool w, bool p)
+ : insn (i), dest (d), base (b), offset (o), writeback (w), ldp (p)
+ {}
+
+ /* Compute the tag based on BASE, DEST and OFFSET of the load. */
+ unsigned tag ()
+ {
+ unsigned int_offset = 0;
+ rtx offset = this->offset;
+ unsigned dest = REGNO (this->dest);
+ unsigned base = REGNO (this->base);
+ machine_mode dest_mode = GET_MODE (this->dest);
+
+ /* Falkor does not support SVE; GET_LOAD_INFO ensures that the
+ destination mode is constant here. */
+ unsigned dest_mode_size = GET_MODE_SIZE (dest_mode).to_constant ();
+
+ /* For loads of larger than 16 bytes, the DEST part of the tag is 0. */
+ if ((dest_mode_size << this->ldp) > 16)
+ dest = 0;
+
+ if (offset && REG_P (offset))
+ int_offset = (1 << 5) | REGNO (offset);
+ else if (offset && CONST_INT_P (offset))
+ {
+ int_offset = INTVAL (offset);
+ int_offset /= dest_mode_size;
+ if (!this->writeback)
+ int_offset >>= 2;
+ }
+ return ((dest & 0xf)
+ | ((base & 0xf) << 4)
+ | ((int_offset & 0x3f) << 8));
+ }
+};
+
+/* Hash map to traverse and process instructions with colliding tags. */
+typedef hash_map <rtx, auto_vec <tag_insn_info *> > tag_map_t;
+
+/* Vector of instructions with colliding tags. */
+typedef auto_vec <tag_insn_info *> insn_info_list_t;
+
+/* Pair of instruction information and unavailable register set to pass to
+ CHECK_COLLIDING_TAGS. */
+typedef std::pair <tag_insn_info *, HARD_REG_SET *> arg_pair_t;
+
+
+/* Callback to free all tag_insn_info objects. */
+bool
+free_insn_info (const rtx &t ATTRIBUTE_UNUSED, insn_info_list_t *v,
+ void *arg ATTRIBUTE_UNUSED)
+{
+ while (v->length () > 0)
+ delete v->pop ();
+
+ return true;
+}
+
+
+/* Add all aliases of the register to the unavailable register set. REG is the
+ smallest register number that can then be used to reference its aliases.
+ UNAVAILABLE is the hard register set to add the ignored register numbers to
+ and MODE is the mode in which the registers would have been used. */
+static void
+ignore_all_aliases (HARD_REG_SET *unavailable, machine_mode mode, unsigned reg)
+{
+ add_to_hard_reg_set (unavailable, mode, reg);
+ add_to_hard_reg_set (unavailable, mode, reg + 16);
+ add_to_hard_reg_set (unavailable, mode, reg + 32);
+ add_to_hard_reg_set (unavailable, mode, reg + 48);
+}
+
+
+/* Callback to check which destination registers are unavailable to us for
+ renaming because of the base and offset colliding. This is a callback that
+ gets called for every name value pair (T, V) in the TAG_MAP. The ARG is an
+ std::pair of the tag_insn_info of the original insn and the hard register
+ set UNAVAILABLE that is used to record hard register numbers that cannot be
+ used for the renaming. This always returns true since we want to traverse
+ through the entire TAG_MAP. */
+bool
+check_colliding_tags (const rtx &t, const insn_info_list_t &v, arg_pair_t *arg)
+{
+ HARD_REG_SET *unavailable = arg->second;
+ unsigned orig_tag = arg->first->tag ();
+ unsigned tag = INTVAL (t);
+ machine_mode mode = GET_MODE (arg->first->dest);
+
+ /* Can't collide with emptiness. */
+ if (v.length () == 0)
+ return true;
+
+ /* Drop all aliased destination registers that result in the same
+ tag. It is not necessary to drop all of them but we do anyway
+ because it is quicker than checking ranges. */
+ if (TAG_UPDATE_DEST (tag, 0) == TAG_UPDATE_DEST (orig_tag, 0))
+ ignore_all_aliases (unavailable, mode, TAG_GET_DEST (tag));
+
+ return true;
+}
+
+
+/* Initialize and build a set of hard register numbers UNAVAILABLE to avoid for
+ renaming. INSN_INFO is the original insn, TAG_MAP is the map of the list of
+ insns indexed by their tags, HEAD is the def/use chain head of the
+ destination register of the original insn. The routine returns the super
+ class of register classes that may be used during the renaming. */
+static enum reg_class
+init_unavailable (tag_insn_info *insn_info, tag_map_t &tag_map, du_head_p head,
+ HARD_REG_SET *unavailable)
+{
+ unsigned dest = head->regno;
+ enum reg_class super_class = NO_REGS;
+ machine_mode mode = GET_MODE (insn_info->dest);
+
+ CLEAR_HARD_REG_SET (*unavailable);
+
+ for (struct du_chain *tmp = head->first; tmp; tmp = tmp->next_use)
+ {
+ if (DEBUG_INSN_P (tmp->insn))
+ continue;
+
+ IOR_COMPL_HARD_REG_SET (*unavailable, reg_class_contents[tmp->cl]);
+ super_class = reg_class_superunion[(int) super_class][(int) tmp->cl];
+ }
+
+ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (fixed_regs[i] || global_regs[i])
+ add_to_hard_reg_set (unavailable, mode, i);
+
+ arg_pair_t arg = arg_pair_t (insn_info, unavailable);
+
+ /* Exclude all registers that would lead to collisions with other loads. */
+ tag_map.traverse <arg_pair_t *, check_colliding_tags> (&arg);
+
+ /* Finally, also ignore all aliases of the current reg. */
+ ignore_all_aliases (unavailable, mode, dest & 0xf);
+
+ return super_class;
+}
+
+
+/* Find a suitable and available register and rename the chain of occurrences
+ of the register defined in the def/use chain headed by HEAD in which INSN
+ exists. CUR_TAG, TAGS and TAG_MAP are used to determine which registers are
+ unavailable due to a potential collision due to the rename. The routine
+ returns the register number in case of a successful rename or -1 to indicate
+ failure. */
+static int
+rename_chain (tag_insn_info *insn_info, tag_map_t &tag_map, du_head_p head)
+{
+ unsigned dest_regno = head->regno;
+
+ if (head->cannot_rename || head->renamed)
+ return -1;
+
+ HARD_REG_SET unavailable;
+
+ enum reg_class super_class = init_unavailable (insn_info, tag_map, head,
+ &unavailable);
+
+ unsigned new_regno = find_rename_reg (head, super_class, &unavailable,
+ dest_regno, false);
+
+ /* Attempt to rename as long as regrename doesn't just throw the same
+ register at us. */
+ if (new_regno != dest_regno && regrename_do_replace (head, new_regno))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "\tInsn %d: Renamed %d to %d\n",
+ INSN_UID (insn_info->insn), dest_regno, new_regno);
+
+ return new_regno;
+ }
+
+ return -1;
+}
+
+
+/* Return true if REGNO is not safe to rename. */
+static bool
+unsafe_rename_p (unsigned regno)
+{
+ /* Avoid renaming registers used for argument passing and return value. In
+ future we could be a little less conservative and walk through the basic
+ blocks to see if there are any call or syscall sites. */
+ if (regno <= R8_REGNUM
+ || (regno >= V0_REGNUM && regno < V8_REGNUM))
+ return true;
+
+ /* Don't attempt to rename registers that may have specific meanings. */
+ switch (regno)
+ {
+ case LR_REGNUM:
+ case HARD_FRAME_POINTER_REGNUM:
+ case FRAME_POINTER_REGNUM:
+ case STACK_POINTER_REGNUM:
+ return true;
+ }
+
+ return false;
+}
+
+
+/* Go through the def/use chains for the register and find the chain for this
+ insn to rename. The function returns the hard register number in case of a
+ successful rename and -1 otherwise. */
+static int
+rename_dest (tag_insn_info *insn_info, tag_map_t &tag_map)
+{
+ struct du_chain *chain = NULL;
+ du_head_p head = NULL;
+ int i;
+
+ unsigned dest_regno = REGNO (insn_info->dest);
+
+ if (unsafe_rename_p (dest_regno))
+ return -1;
+
+ /* Search the chain where this instruction is (one of) the root. */
+ rtx_insn *insn = insn_info->insn;
+ operand_rr_info *dest_op_info = insn_rr[INSN_UID (insn)].op_info;
+
+ for (i = 0; i < dest_op_info->n_chains; i++)
+ {
+ /* The register tracked by this chain does not match the
+ destination register of insn. */
+ if (dest_op_info->heads[i]->regno != dest_regno)
+ continue;
+
+ head = dest_op_info->heads[i];
+ /* The chain was merged in another, find the new head. */
+ if (!head->first)
+ head = regrename_chain_from_id (head->id);
+
+ for (chain = head->first; chain; chain = chain->next_use)
+ /* Found the insn in the chain, so try renaming the register in this
+ chain. */
+ if (chain->insn == insn)
+ return rename_chain (insn_info, tag_map, head);
+ }
+
+ return -1;
+}
+
+
+/* Flag to track if the map has changed. */
+static bool map_changed = false;
+
+/* The actual reallocation logic. For each vector of collisions V, try to
+ resolve the collision by attempting to rename the destination register of
+ all but one of the loads. This is a callback that is invoked for each
+ name-value pair (T, V) in TAG_MAP. The function returns true whenever it
+ returns unchanged and false otherwise to halt traversal. */
+bool
+avoid_collisions_1 (const rtx &t, insn_info_list_t *v, tag_map_t *tag_map)
+{
+ /* We need at least two loads to cause a tag collision, return unchanged. */
+ if (v->length () < 2)
+ return true;
+
+ tag_insn_info *vec_start = v->pop ();
+ tag_insn_info *insn_info = vec_start;
+
+ /* Try to rename at least one register to reduce the collision. If we
+ iterate all the way through, we end up dropping one of the loads from the
+ list. This is fine because we want at most one element to ensure that a
+ subsequent rename attempt does not end up worsening the collision. */
+ do
+ {
+ int new_regno;
+
+ if ((new_regno = rename_dest (insn_info, *tag_map)) != -1)
+ {
+ rtx new_tag = GEN_INT (TAG_UPDATE_DEST (INTVAL (t), new_regno));
+
+ tag_map->get_or_insert (new_tag).safe_push (insn_info);
+ df_set_regs_ever_live (new_regno, true);
+ map_changed = true;
+ return false;
+ }
+
+ v->safe_insert (0, insn_info);
+ insn_info = v->pop ();
+ }
+ while (insn_info != vec_start);
+
+ if (dump_file)
+ fprintf (dump_file, "\t>> Failed to rename destination in insn %d\n\t>>",
+ INSN_UID (insn_info->insn));
+
+ /* Drop the last element and move on to the next tag. */
+ delete insn_info;
+ return true;
+}
+
+
+/* For each set of collisions, attempt to rename the registers or insert a move
+ to avoid the collision. We repeatedly traverse through TAG_MAP using
+ AVOID_COLLISIONS_1 trying to rename registers to avoid collisions until a
+ full traversal results in no change in the map. */
+static void
+avoid_collisions (tag_map_t &tag_map)
+{
+ do
+ {
+ map_changed = false;
+ tag_map.traverse <tag_map_t *, avoid_collisions_1> (&tag_map);
+ }
+ while (map_changed);
+}
+
+
+
+/* Find the use def chain in which INSN exists and then see if there is a
+ definition inside the loop and outside it. We use this as a simple
+ approximation to determine whether the base register is an IV. The basic
+ idea is to find INSN in the use-def chains for its base register and find
+ all definitions that reach it. Of all these definitions, there should be at
+ least one definition that is a simple addition of a constant value, either
+ as a binary operation or a pre or post update.
+
+ The function returns true if the base register is estimated to be an IV. */
+static bool
+iv_p (rtx_insn *insn, rtx reg, struct loop *loop)
+{
+ df_ref ause;
+ unsigned regno = REGNO (reg);
+
+ /* Ignore loads from the stack. */
+ if (regno == SP_REGNUM)
+ return false;
+
+ for (ause = DF_REG_USE_CHAIN (regno); ause; ause = DF_REF_NEXT_REG (ause))
+ {
+ if (!DF_REF_INSN_INFO (ause)
+ || !NONDEBUG_INSN_P (DF_REF_INSN (ause)))
+ continue;
+
+ if (insn != DF_REF_INSN (ause))
+ continue;
+
+ struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+ df_ref def_rec;
+
+ FOR_EACH_INSN_INFO_DEF (def_rec, insn_info)
+ {
+ rtx_insn *insn = DF_REF_INSN (def_rec);
+ basic_block bb = BLOCK_FOR_INSN (insn);
+
+ if (dominated_by_p (CDI_DOMINATORS, bb, loop->header)
+ && bb->loop_father == loop)
+ {
+ if (recog_memoized (insn) < 0)
+ continue;
+
+ rtx pat = PATTERN (insn);
+
+ /* Prefetch or clobber; unlikely to be a constant stride. The
+ falkor software prefetcher tuning is pretty conservative, so
+ its presence indicates that the access pattern is probably
+ strided but most likely with an unknown stride size or a
+ stride size that is quite large. */
+ if (GET_CODE (pat) != SET)
+ continue;
+
+ rtx x = SET_SRC (pat);
+ if (GET_CODE (x) == ZERO_EXTRACT
+ || GET_CODE (x) == ZERO_EXTEND
+ || GET_CODE (x) == SIGN_EXTEND)
+ x = XEXP (x, 0);
+
+ /* Loading the value from memory; unlikely to be a constant
+ stride. */
+ if (MEM_P (x))
+ continue;
+
+ /* An increment or decrement by a constant MODE_SIZE amount or
+ the result of a binary expression is likely to be an IV. */
+ if (GET_CODE (x) == POST_INC
+ || GET_CODE (x) == POST_DEC
+ || GET_CODE (x) == PRE_INC
+ || GET_CODE (x) == PRE_DEC)
+ return true;
+ else if (BINARY_P (x)
+ && (CONST_INT_P (XEXP (x, 0))
+ || CONST_INT_P (XEXP (x, 1))))
+ {
+ rtx stride = (CONST_INT_P (XEXP (x, 0))
+ ? XEXP (x, 0) : XEXP (x, 1));
+
+ /* Don't bother with very long strides because the prefetcher
+ is unable to train on them anyway. */
+ if (INTVAL (stride) < MAX_PREFETCH_STRIDE)
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ return false;
+}
+
+
+/* Return true if SRC is a strided load in the LOOP, false otherwise.
+ If it is a strided load, set the BASE and OFFSET. Also, if this is
+ a pre/post increment load, set PRE_POST to true. */
+static bool
+valid_src_p (rtx src, rtx_insn *insn, struct loop *loop, bool *pre_post,
+ rtx *base, rtx *offset, bool load_pair)
+{
+ subrtx_var_iterator::array_type array;
+ rtx x = NULL_RTX;
+
+ FOR_EACH_SUBRTX_VAR (iter, array, src, NONCONST)
+ if (MEM_P (*iter))
+ {
+ x = *iter;
+ break;
+ }
+
+ if (!x)
+ return false;
+
+ struct aarch64_address_info addr;
+ machine_mode mode = GET_MODE (x);
+
+ if (!aarch64_classify_address (&addr, XEXP (x, 0), mode, true))
+ return false;
+
+ unsigned regno = REGNO (addr.base);
+ if (global_regs[regno] || fixed_regs[regno])
+ return false;
+
+ if (addr.type == ADDRESS_REG_WB)
+ {
+ unsigned code = GET_CODE (XEXP (x, 0));
+
+ *pre_post = true;
+ *base = addr.base;
+
+ if (code == PRE_MODIFY || code == POST_MODIFY)
+ *offset = addr.offset;
+ else
+ {
+ /*Writeback is only supported for fixed-width modes. */
+ unsigned int_offset = GET_MODE_SIZE (mode).to_constant ();
+
+ /* For post-incremented load pairs we would increment the base twice
+ over, so make that adjustment. */
+ if (load_pair && (code == POST_INC || code == POST_DEC))
+ int_offset *= 2;
+
+ *offset = GEN_INT (int_offset);
+ }
+ return true;
+ }
+ else if (addr.type == ADDRESS_REG_IMM || addr.type == ADDRESS_REG_REG)
+ {
+ /* Check if the load is strided. */
+ if (!iv_p (insn, addr.base, loop))
+ return false;
+
+ *base = addr.base;
+ *offset = addr.offset;
+ return true;
+ }
+
+ return false;
+}
+
+
+/* Return true if INSN is a strided load in LOOP. If it is a strided load, set
+ the DEST, BASE and OFFSET. Also, if this is a pre/post increment load, set
+ PRE_POST to true.
+
+ The routine does checks on the destination of the insn and depends on
+ STRIDED_LOAD_P to check the source and fill in the BASE and OFFSET. */
+static bool
+get_load_info (rtx_insn *insn, struct loop *loop, rtx *dest, rtx *base,
+ rtx *offset, bool *pre_post, bool *ldp)
+{
+ if (!INSN_P (insn) || recog_memoized (insn) < 0)
+ return false;
+
+ rtx pat = PATTERN (insn);
+ unsigned code = GET_CODE (pat);
+ bool load_pair = (code == PARALLEL);
+
+ /* For a load pair we need only the first base and destination
+ registers. We however need to ensure that our pre/post increment
+ offset is doubled; we do that in STRIDED_LOAD_P. */
+ if (load_pair)
+ {
+ pat = XVECEXP (pat, 0, 0);
+ code = GET_CODE (pat);
+ }
+
+ if (code != SET)
+ return false;
+
+ rtx dest_rtx = SET_DEST (pat);
+
+ if (!REG_P (dest_rtx))
+ return false;
+
+ unsigned regno = REGNO (dest_rtx);
+ machine_mode mode = GET_MODE (dest_rtx);
+ machine_mode inner_mode = GET_MODE_INNER (mode);
+
+ /* Falkor does not support SVE vectors. */
+ if (!GET_MODE_SIZE (mode).is_constant ())
+ return false;
+
+ /* Ignore vector struct or lane loads. */
+ if (GET_MODE_SIZE (mode).to_constant ()
+ != GET_MODE_SIZE (inner_mode).to_constant ())
+ return false;
+
+ /* The largest width we want to bother with is a load of a pair of
+ quad-words. */
+ if ((GET_MODE_SIZE (mode).to_constant () << load_pair)
+ > GET_MODE_SIZE (OImode))
+ return false;
+
+ /* Ignore loads into the stack pointer because it is unlikely to be a
+ stream. */
+ if (regno == SP_REGNUM)
+ return false;
+
+ if (valid_src_p (SET_SRC (pat), insn, loop, pre_post, base, offset,
+ load_pair))
+ {
+ *dest = dest_rtx;
+ *ldp = load_pair;
+
+ return true;
+ }
+
+ return false;
+}
+
+
+/* Return whether INSN and CAND are in the same def/use chain. */
+static bool
+in_same_chain (rtx_insn *insn, rtx_insn *cand, unsigned regno)
+{
+ struct du_chain *chain = NULL;
+ du_head_p head = NULL;
+ int i;
+
+ /* Search the chain where this instruction is (one of) the root. */
+ operand_rr_info *op_info = insn_rr[INSN_UID (insn)].op_info;
+
+ for (i = 0; i < op_info->n_chains; i++)
+ {
+ /* The register tracked by this chain does not match the
+ dest register of insn. */
+ if (op_info->heads[i]->regno != regno)
+ continue;
+
+ head = op_info->heads[i];
+ /* The chain was merged in another, find the new head. */
+ if (!head->first)
+ head = regrename_chain_from_id (head->id);
+
+ bool found_insn = false, found_cand = false;
+
+ for (chain = head->first; chain; chain = chain->next_use)
+ {
+ rtx *loc = &SET_DEST (PATTERN (chain->insn));
+
+ if (chain->loc != loc)
+ continue;
+
+ if (chain->insn == insn)
+ found_insn = true;
+
+ if (chain->insn == cand)
+ found_cand = true;
+
+ if (found_insn && found_cand)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+/* Callback function to traverse the tag map and drop loads that have the same
+ destination and and in the same chain of occurrence. Routine always returns
+ true to allow traversal through all of TAG_MAP. */
+bool
+single_dest_per_chain (const rtx &t ATTRIBUTE_UNUSED, insn_info_list_t *v,
+ void *arg ATTRIBUTE_UNUSED)
+{
+ for (int i = v->length () - 1; i>= 1; i--)
+ {
+ tag_insn_info *insn_info = (*v)[i];
+
+ for (int j = v->length () - 2; j >= 0; j--)
+ {
+ /* Filter out destinations in the same chain. */
+ if (in_same_chain (insn_info->insn, (*v)[j]->insn,
+ REGNO (insn_info->dest)))
+ {
+ v->ordered_remove (j);
+ i = v->length ();
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+
+/* Callback invoked for each name-value pair (T, INSN_INFO) to dump the insn
+ list INSN_INFO for tag T. */
+bool
+dump_insn_list (const rtx &t, const insn_info_list_t &insn_info,
+ void *unused ATTRIBUTE_UNUSED)
+{
+ gcc_assert (dump_file);
+ fprintf (dump_file, "Tag 0x%lx ::\n", INTVAL (t));
+
+ for (unsigned i = 0; i < insn_info.length (); i++)
+ dump_insn_slim (dump_file, insn_info[i]->insn);
+
+ fprintf (dump_file, "\n");
+
+ return true;
+}
+
+
+/* Record all loads in LOOP into TAG_MAP indexed by the falkor hardware
+ prefetcher memory tags. */
+static void
+record_loads (tag_map_t &tag_map, struct loop *loop)
+{
+ rtx_insn *insn;
+ basic_block *body, bb;
+
+ body = get_loop_body (loop);
+
+ for (unsigned i = 0; i < loop->num_nodes; i++)
+ {
+ bb = body[i];
+ FOR_BB_INSNS (bb, insn)
+ {
+ rtx base = NULL_RTX;
+ rtx dest = NULL_RTX;
+ rtx offset = NULL_RTX;
+ bool writeback = false;
+ bool ldp = false;
+
+ if (!INSN_P (insn) || DEBUG_INSN_P (insn))
+ continue;
+
+ if (get_load_info (insn, loop, &dest, &base, &offset, &writeback,
+ &ldp))
+ {
+ tag_insn_info *i = new tag_insn_info (insn, dest, base, offset,
+ writeback, ldp);
+ rtx tag = GEN_INT (i->tag ());
+ tag_map.get_or_insert (tag).safe_push (i);
+ }
+ }
+ }
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "Loop %d: Tag map generated.\n", loop->num);
+ tag_map.traverse <void *, dump_insn_list> (NULL);
+ }
+
+ /* Try to reduce the dataset before launching into the rename attempt. Drop
+ destinations in the same collision chain that appear in the same def/use
+ chain, all as defs. These chains will move together in a rename so
+ there's no point in keeping both in there. */
+ tag_map.traverse <void *, single_dest_per_chain> (NULL);
+}
+
+
+/* Tag collision avoidance pass for Falkor. The pass runs in two phases for
+ each loop; the first phase collects all loads that we consider as
+ interesting for renaming into a tag-indexed map of lists. The second phase
+ renames the destination register of the loads in an attempt to spread out
+ the loads into different tags. */
+void
+execute_tag_collision_avoidance ()
+{
+ struct loop *loop;
+
+ df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
+ df_chain_add_problem (DF_UD_CHAIN);
+ df_compute_regs_ever_live (true);
+ df_analyze ();
+ df_set_flags (DF_DEFER_INSN_RESCAN);
+
+ regrename_init (true);
+ regrename_analyze (NULL);
+
+ compute_bb_for_insn ();
+ calculate_dominance_info (CDI_DOMINATORS);
+ loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
+
+ FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+ {
+ tag_map_t tag_map (512);
+
+ record_loads (tag_map, loop);
+ avoid_collisions (tag_map);
+ if (dump_file)
+ {
+ fprintf (dump_file, "Loop %d: Completed rename.\n", loop->num);
+ tag_map.traverse <void *, dump_insn_list> (NULL);
+ }
+ tag_map.traverse <void *, free_insn_info> (NULL);
+ }
+
+ loop_optimizer_finalize ();
+ free_dominance_info (CDI_DOMINATORS);
+ regrename_finish ();
+}
+
+
+const pass_data pass_data_tag_collision_avoidance =
+{
+ RTL_PASS, /* type */
+ "tag_collision_avoidance", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_df_finish, /* todo_flags_finish */
+};
+
+
+class pass_tag_collision_avoidance : public rtl_opt_pass
+{
+public:
+ pass_tag_collision_avoidance (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_tag_collision_avoidance, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual bool gate (function *)
+ {
+ return ((aarch64_tune_params.extra_tuning_flags
+ & AARCH64_EXTRA_TUNE_RENAME_LOAD_REGS)
+ && optimize >= 2);
+ }
+
+ virtual unsigned int execute (function *)
+ {
+ execute_tag_collision_avoidance ();
+ return 0;
+ }
+
+}; // class pass_tag_collision_avoidance
+
+
+/* Create a new pass instance. */
+rtl_opt_pass *
+make_pass_tag_collision_avoidance (gcc::context *ctxt)
+{
+ return new pass_tag_collision_avoidance (ctxt);
+}
diff --git a/gcc/config/aarch64/falkor.md b/gcc/config/aarch64/falkor.md
index 5cbc515..45cbff9 100644
--- a/gcc/config/aarch64/falkor.md
+++ b/gcc/config/aarch64/falkor.md
@@ -322,6 +322,12 @@
(eq_attr "type" "neon_from_gp_q"))
"falkor_gtov,falkor_gtov")
+;; DUP does not use vector pipes in Q mode, only gtov+gtov.
+(define_insn_reservation "falkor_am_1_gtov_gtov" 1
+ (and (eq_attr "tune" "falkor")
+ (eq_attr "type" "neon_dup_q"))
+ "falkor_gtov*2")
+
;; neon_to_gp_q is used for 32-bit ARM instructions that move 64-bits of data
;; so no use needed here.
@@ -337,7 +343,7 @@
(define_insn_reservation "falkor_am_1_vxvy_vxvy" 1
(and (eq_attr "tune" "falkor")
- (eq_attr "type" "neon_bsl_q,neon_dup_q,neon_ext_q,neon_move_q,neon_rev_q,neon_tbl1_q,neon_permute_q"))
+ (eq_attr "type" "neon_bsl_q,neon_ext_q,neon_move_q,neon_rev_q,neon_tbl1_q,neon_permute_q"))
"falkor_vxvy+falkor_vxvy")
(define_insn_reservation "falkor_am_2_vxvy" 2
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index d846118..a439560 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -35,6 +35,9 @@
;; Iterator for all integer modes (up to 64-bit)
(define_mode_iterator ALLI [QI HI SI DI])
+;; Iterator for all integer modes (up to 128-bit)
+(define_mode_iterator ALLI_TI [QI HI SI DI TI])
+
;; Iterator for all integer modes that can be extended (up to 64-bit)
(define_mode_iterator ALLX [QI HI SI])
@@ -1534,8 +1537,6 @@
(define_int_iterator FCVT_F2FIXED [UNSPEC_FCVTZS UNSPEC_FCVTZU])
(define_int_iterator FCVT_FIXED2F [UNSPEC_SCVTF UNSPEC_UCVTF])
-(define_int_iterator FRECP [UNSPEC_FRECPE UNSPEC_FRECPX])
-
(define_int_iterator CRC [UNSPEC_CRC32B UNSPEC_CRC32H UNSPEC_CRC32W
UNSPEC_CRC32X UNSPEC_CRC32CB UNSPEC_CRC32CH
UNSPEC_CRC32CW UNSPEC_CRC32CX])
@@ -1785,8 +1786,6 @@
(UNSPEC_UNPACKSLO "BYTES_BIG_ENDIAN")
(UNSPEC_UNPACKULO "BYTES_BIG_ENDIAN")])
-(define_int_attr frecp_suffix [(UNSPEC_FRECPE "e") (UNSPEC_FRECPX "x")])
-
(define_int_attr crc_variant [(UNSPEC_CRC32B "crc32b") (UNSPEC_CRC32H "crc32h")
(UNSPEC_CRC32W "crc32w") (UNSPEC_CRC32X "crc32x")
(UNSPEC_CRC32CB "crc32cb") (UNSPEC_CRC32CH "crc32ch")
diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index d8f377b..5b08b03 100644
--- a/gcc/config/aarch64/predicates.md
+++ b/gcc/config/aarch64/predicates.md
@@ -359,6 +359,36 @@
(and (match_operand 0 "memory_operand")
(match_code "reg" "0")))
+(define_predicate "aarch64_9bit_offset_memory_operand"
+ (and (match_operand 0 "memory_operand")
+ (ior (match_code "reg" "0")
+ (and (match_code "plus" "0")
+ (match_code "reg" "00")
+ (match_code "const_int" "01"))))
+{
+ rtx mem_op = XEXP (op, 0);
+
+ if (REG_P (mem_op))
+ return GET_MODE (mem_op) == DImode;
+
+ rtx plus_op0 = XEXP (mem_op, 0);
+ rtx plus_op1 = XEXP (mem_op, 1);
+
+ if (GET_MODE (plus_op0) != DImode)
+ return false;
+
+ poly_int64 offset;
+ if (!poly_int_rtx_p (plus_op1, &offset))
+ gcc_unreachable ();
+
+ return aarch64_offset_9bit_signed_unscaled_p (mode, offset);
+})
+
+(define_predicate "aarch64_rcpc_memory_operand"
+ (if_then_else (match_test "AARCH64_ISA_RCPC8_4")
+ (match_operand 0 "aarch64_9bit_offset_memory_operand")
+ (match_operand 0 "aarch64_sync_memory_operand")))
+
;; Predicates for parallel expanders based on mode.
(define_special_predicate "vect_par_cnst_hi_half"
(match_code "parallel")
diff --git a/gcc/config/aarch64/t-aarch64 b/gcc/config/aarch64/t-aarch64
index 0be1f0d..1576d05 100644
--- a/gcc/config/aarch64/t-aarch64
+++ b/gcc/config/aarch64/t-aarch64
@@ -67,6 +67,26 @@ cortex-a57-fma-steering.o: $(srcdir)/config/aarch64/cortex-a57-fma-steering.c \
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/aarch64/cortex-a57-fma-steering.c
+aarch64-speculation.o: $(srcdir)/config/aarch64/aarch64-speculation.cc \
+ $(CONFIG_H) \
+ $(SYSTEM_H) \
+ $(TM_H) \
+ $(TARGET_H) \
+ $(RTL_BASE_H) \
+ $(TREE_PASS_H)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_SPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/aarch64/aarch64-speculation.cc
+
+falkor-tag-collision-avoidance.o: \
+ $(srcdir)/config/aarch64/falkor-tag-collision-avoidance.c \
+ $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(REGS_H) insn-config.h $(RTL_BASE_H) \
+ dominance.h cfg.h cfganal.h $(BASIC_BLOCK_H) $(INSN_ATTR_H) $(RECOG_H) \
+ output.h hash-map.h $(DF_H) $(OBSTACK_H) $(TARGET_H) $(RTL_H) \
+ $(CONTEXT_H) $(TREE_PASS_H) regrename.h \
+ $(srcdir)/config/aarch64/aarch64-protos.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/aarch64/falkor-tag-collision-avoidance.c
+
comma=,
MULTILIB_OPTIONS = $(subst $(comma),/, $(patsubst %, mabi=%, $(subst $(comma),$(comma)mabi=,$(TM_MULTILIB_CONFIG))))
MULTILIB_DIRNAMES = $(subst $(comma), ,$(TM_MULTILIB_CONFIG))
diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h
index 6802ef3..aa1de8a 100644
--- a/gcc/config/alpha/alpha.h
+++ b/gcc/config/alpha/alpha.h
@@ -678,7 +678,7 @@ enum reg_class {
#define CONSTANT_ADDRESS_P(X) \
(CONST_INT_P (X) \
- && (unsigned HOST_WIDE_INT) (INTVAL (X) + 0x8000) < 0x10000)
+ && (UINTVAL (X) + 0x8000) < 0x10000)
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
and check its validity for a certain class.
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index c186e02..5443cdd 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -5181,7 +5181,8 @@ static void arc_file_start (void)
TARGET_OPTFPE ? 1 : 0);
if (TARGET_V2)
asm_fprintf (asm_out_file, "\t.arc_attribute Tag_ARC_CPU_variation, %d\n",
- arc_tune == ARC_TUNE_CORE_3 ? 3 : 2);
+ (arc_tune < ARC_TUNE_CORE_3) ? 2 :
+ (arc_tune == ARC_TUNE_CORE_3 ? 3 : 4));
}
/* Implement `TARGET_ASM_FILE_END'. */
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index de09b6b..98fa928 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -1635,7 +1635,7 @@ enum
/* Custom FP instructions used by QuarkSE EM cpu. */
#define TARGET_FPX_QUARK (TARGET_EM && TARGET_SPFP \
&& (arc_fpu_build == FPX_QK))
-/* DBNZ support is available for ARCv2 core3 cpus. */
-#define TARGET_DBNZ (TARGET_V2 && (arc_tune == ARC_TUNE_CORE_3))
+/* DBNZ support is available for ARCv2 core3 and newer cpus. */
+#define TARGET_DBNZ (TARGET_V2 && (arc_tune >= ARC_TUNE_CORE_3))
#endif /* GCC_ARC_H */
diff --git a/gcc/config/arc/linux.h b/gcc/config/arc/linux.h
index 96d548e..62ebe4d 100644
--- a/gcc/config/arc/linux.h
+++ b/gcc/config/arc/linux.h
@@ -98,7 +98,7 @@ along with GCC; see the file COPYING3. If not see
Signalize that because we have fde-glibc, we don't need all C shared libs
linked against -lgcc_s. */
#undef LINK_EH_SPEC
-#define LINK_EH_SPEC "--eh-frame-hdr"
+#define LINK_EH_SPEC "--eh-frame-hdr "
#endif
#undef SUBTARGET_CPP_SPEC
diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c
index 183a7b9..563ca51 100644
--- a/gcc/config/arm/arm-builtins.c
+++ b/gcc/config/arm/arm-builtins.c
@@ -927,6 +927,11 @@ arm_init_simd_builtin_types (void)
(*lang_hooks.types.register_builtin_type) (arm_simd_polyTI_type_node,
"__builtin_neon_poly128");
+ /* Prevent front-ends from transforming poly vectors into string
+ literals. */
+ TYPE_STRING_FLAG (arm_simd_polyQI_type_node) = false;
+ TYPE_STRING_FLAG (arm_simd_polyHI_type_node) = false;
+
/* Init all the element types built by the front-end. */
arm_simd_types[Int8x8_t].eltype = intQI_type_node;
arm_simd_types[Int8x16_t].eltype = intQI_type_node;
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 8537262..0dfb3ac 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -56,6 +56,8 @@ extern void arm_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update
extern rtx arm_simd_vect_par_cnst_half (machine_mode mode, bool high);
extern bool arm_simd_check_vect_par_cnst_half_p (rtx op, machine_mode mode,
bool high);
+extern void arm_emit_speculation_barrier_function (void);
+
#ifdef RTX_CODE
extern void arm_gen_unlikely_cbranch (enum rtx_code, machine_mode cc_mode,
rtx label_ref);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index f5eece4..6332e68 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -2466,8 +2466,9 @@ arm_set_fixed_conv_libfunc (convert_optab optable, machine_mode to,
set_conv_libfunc (optable, to, from, buffer);
}
-/* Set up library functions unique to ARM. */
+static GTY(()) rtx speculation_barrier_libfunc;
+/* Set up library functions unique to ARM. */
static void
arm_init_libfuncs (void)
{
@@ -2753,6 +2754,8 @@ arm_init_libfuncs (void)
if (TARGET_AAPCS_BASED)
synchronize_libfunc = init_one_libfunc ("__sync_synchronize");
+
+ speculation_barrier_libfunc = init_one_libfunc ("__speculation_barrier");
}
/* On AAPCS systems, this is the "struct __va_list". */
@@ -30838,7 +30841,7 @@ arm_insert_attributes (tree fndecl, tree * attributes)
return;
if (TREE_CODE (fndecl) != FUNCTION_DECL || DECL_EXTERNAL(fndecl)
- || DECL_BUILT_IN (fndecl) || DECL_ARTIFICIAL (fndecl))
+ || fndecl_built_in_p (fndecl) || DECL_ARTIFICIAL (fndecl))
return;
/* Nested definitions must inherit mode. */
@@ -31509,8 +31512,8 @@ arm_can_change_mode_class (machine_mode from, machine_mode to,
{
if (TARGET_BIG_END
&& !(GET_MODE_SIZE (from) == 16 && GET_MODE_SIZE (to) == 8)
- && (GET_MODE_UNIT_SIZE (from) > UNITS_PER_WORD
- || GET_MODE_UNIT_SIZE (to) > UNITS_PER_WORD)
+ && (GET_MODE_SIZE (from) > UNITS_PER_WORD
+ || GET_MODE_SIZE (to) > UNITS_PER_WORD)
&& reg_classes_intersect_p (VFP_REGS, rclass))
return false;
return true;
@@ -31528,6 +31531,16 @@ arm_constant_alignment (const_tree exp, HOST_WIDE_INT align)
return align;
}
+/* Emit a speculation barrier on target architectures that do not have
+ DSB/ISB directly. Such systems probably don't need a barrier
+ themselves, but if the code is ever run on a later architecture, it
+ might become a problem. */
+void
+arm_emit_speculation_barrier_function ()
+{
+ emit_library_call (speculation_barrier_libfunc, LCT_NORMAL, VOIDmode);
+}
+
#if CHECKING_P
namespace selftest {
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 361a026..270b8e4 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12012,6 +12012,33 @@
[(set_attr "length" "4")
(set_attr "type" "coproc")])
+(define_expand "speculation_barrier"
+ [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
+ "TARGET_EITHER"
+ "
+ /* For thumb1 (except Armv8 derivatives), and for pre-Armv7 we don't
+ have a usable barrier (and probably don't need one in practice).
+ But to be safe if such code is run on later architectures, call a
+ helper function in libgcc that will do the thing for the active
+ system. */
+ if (!(arm_arch7 || arm_arch8))
+ {
+ arm_emit_speculation_barrier_function ();
+ DONE;
+ }
+ "
+)
+
+;; Generate a hard speculation barrier when we have not enabled speculation
+;; tracking.
+(define_insn "*speculation_barrier_insn"
+ [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
+ "arm_arch7 || arm_arch8"
+ "isb\;dsb\\tsy"
+ [(set_attr "type" "block")
+ (set_attr "length" "8")]
+)
+
;; Vector bits common to IWMMXT and Neon
(include "vec-common.md")
;; Load the Intel Wireless Multimedia Extension patterns
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index 1646b21..5aeee4b 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -25,9 +25,9 @@
(define_insn "*neon_mov<mode>"
[(set (match_operand:VDX 0 "nonimmediate_operand"
- "=w,Un,w, w, ?r,?w,?r,?r, ?Us")
+ "=w,Un,w, w, ?r,?w,?r, ?Us")
(match_operand:VDX 1 "general_operand"
- " w,w, Dn,Uni, w, r, r, Usi,r"))]
+ " w,w, Dn,Uni, w, r, Usi,r"))]
"TARGET_NEON
&& (register_operand (operands[0], <MODE>mode)
|| register_operand (operands[1], <MODE>mode))"
@@ -61,12 +61,12 @@
}
}
[(set_attr "type" "neon_move<q>,neon_store1_1reg,neon_move<q>,\
- neon_load1_1reg, neon_to_gp<q>,neon_from_gp<q>,mov_reg,\
+ neon_load1_1reg, neon_to_gp<q>,neon_from_gp<q>,\
neon_load1_2reg, neon_store1_2reg")
- (set_attr "length" "4,4,4,4,4,4,8,8,8")
- (set_attr "arm_pool_range" "*,*,*,1020,*,*,*,1020,*")
- (set_attr "thumb2_pool_range" "*,*,*,1018,*,*,*,1018,*")
- (set_attr "neg_pool_range" "*,*,*,1004,*,*,*,1004,*")])
+ (set_attr "length" "4,4,4,4,4,4,8,8")
+ (set_attr "arm_pool_range" "*,*,*,1020,*,*,1020,*")
+ (set_attr "thumb2_pool_range" "*,*,*,1018,*,*,1018,*")
+ (set_attr "neg_pool_range" "*,*,*,1004,*,*,1004,*")])
(define_insn "*neon_mov<mode>"
[(set (match_operand:VQXMOV 0 "nonimmediate_operand"
@@ -113,6 +113,13 @@
(set_attr "thumb2_pool_range" "*,*,*,1018,*,*,*,1018,*")
(set_attr "neg_pool_range" "*,*,*,996,*,*,*,996,*")])
+/* We define these mov expanders to match the standard mov$a optab to prevent
+ the mid-end from trying to do a subreg for these modes which is the most
+ inefficient way to expand the move. Also big-endian subreg's aren't
+ allowed for a subset of modes, See TARGET_CAN_CHANGE_MODE_CLASS.
+ Without these RTL generation patterns the mid-end would attempt to take a
+ sub-reg and may ICE if it can't. */
+
(define_expand "movti"
[(set (match_operand:TI 0 "nonimmediate_operand" "")
(match_operand:TI 1 "general_operand" ""))]
@@ -137,33 +144,15 @@
}
})
-(define_expand "movv4hf"
- [(set (match_operand:V4HF 0 "s_register_operand")
- (match_operand:V4HF 1 "s_register_operand"))]
- "TARGET_NEON && TARGET_FP16"
+(define_expand "mov<mode>"
+ [(set (match_operand:VH 0 "s_register_operand")
+ (match_operand:VH 1 "s_register_operand"))]
+ "TARGET_NEON"
{
- /* We need to use force_reg to avoid TARGET_CAN_CHANGE_MODE_CLASS
- causing an ICE on big-endian because it cannot extract subregs in
- this case. */
- if (can_create_pseudo_p ())
- {
- if (!REG_P (operands[0]))
- operands[1] = force_reg (V4HFmode, operands[1]);
- }
-})
-
-(define_expand "movv8hf"
- [(set (match_operand:V8HF 0 "")
- (match_operand:V8HF 1 ""))]
- "TARGET_NEON && TARGET_FP16"
-{
- /* We need to use force_reg to avoid TARGET_CAN_CHANGE_MODE_CLASS
- causing an ICE on big-endian because it cannot extract subregs in
- this case. */
if (can_create_pseudo_p ())
{
if (!REG_P (operands[0]))
- operands[1] = force_reg (V8HFmode, operands[1]);
+ operands[1] = force_reg (<MODE>mode, operands[1]);
}
})
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index b05f85e..1941673 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -168,6 +168,7 @@
VUNSPEC_MCRR2 ; Represent the coprocessor mcrr2 instruction.
VUNSPEC_MRRC ; Represent the coprocessor mrrc instruction.
VUNSPEC_MRRC2 ; Represent the coprocessor mrrc2 instruction.
+ VUNSPEC_SPECULATION_BARRIER ; Represents an unconditional speculation barrier.
])
;; Enumerators for NEON unspecs.
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index 57bd691..c652cb3 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -248,6 +248,9 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;
#undef TARGET_ATOMIC_ALIGN_FOR_MODE
#define TARGET_ATOMIC_ALIGN_FOR_MODE cris_atomic_align_for_mode
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
#undef TARGET_STRUCT_VALUE_RTX
#define TARGET_STRUCT_VALUE_RTX cris_struct_value_rtx
#undef TARGET_SETUP_INCOMING_VARARGS
diff --git a/gcc/config/csky/constraints.md b/gcc/config/csky/constraints.md
new file mode 100644
index 0000000..e08f7f8
--- /dev/null
+++ b/gcc/config/csky/constraints.md
@@ -0,0 +1,174 @@
+;; Constraints for C-SKY.
+;; Copyright (C) 2018 Free Software Foundation, Inc.
+;; Contributed by C-SKY Microsystems and Mentor Graphics.
+;;
+;; 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/>. */
+
+;; Register constraints.
+
+(define_register_constraint "a" "MINI_REGS" "r0 - r7")
+(define_register_constraint "b" "LOW_REGS" "r0 - r15")
+(define_register_constraint "c" "C_REGS" "C register")
+(define_register_constraint "y" "HILO_REGS" "HI and LO registers")
+(define_register_constraint "l" "LO_REGS" "LO register")
+(define_register_constraint "h" "HI_REGS" "HI register")
+(define_register_constraint "v" "V_REGS" "vector registers")
+(define_register_constraint "z" "SP_REGS" "SP register")
+
+
+;; Memory and misc constraints.
+
+(define_memory_constraint "Q"
+ "Memory operands with base register, index register and short displacement for FPUV2"
+ (match_test "csky_valid_fpuv2_mem_operand (op)"))
+
+(define_constraint "R"
+ "Memory operands whose address is a label_ref"
+ (and (match_code "mem")
+ (match_test "GET_CODE (XEXP (op, 0)) == LABEL_REF")))
+
+(define_constraint "S"
+ "Symbol reference with optional offset"
+ (match_test "csky_symbolic_address_p (op)"))
+
+
+;; Constant integer constraints.
+
+(define_constraint "I"
+ "Constant in range [0, 65535]"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_I (ival)")))
+
+(define_constraint "J"
+ "Constant in range [1, 32]"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_J (ival)")))
+
+(define_constraint "K"
+ "Constant in range [0, 31]"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_K (ival)")))
+
+(define_constraint "L"
+ "Constant in range [1, 8]"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_L (ival)")))
+
+(define_constraint "M"
+ "Constant in range [1, 4096]"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_M (ival)")))
+
+(define_constraint "N"
+ "Constant in range [1, 256]"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_N (ival)")))
+
+(define_constraint "O"
+ "Constant in range [0, 4095]"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_O (ival)")))
+
+(define_constraint "P"
+ "Constant in range [4, 508] that is divisible by 4"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_P (ival)")))
+
+(define_constraint "T"
+ "Constant in range [-256, -1]"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_T (ival)")))
+
+(define_constraint "Ua"
+ "Constant 0"
+ (and (match_code "const_int")
+ (match_test "ival == 0")))
+
+(define_constraint "Ub"
+ "Unsigned int that is an exact power of 2"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_Ub (ival)")))
+
+(define_constraint "Uc"
+ "Unsigned int X such that X+1 is an exact power of 2"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_Uc (ival)")))
+
+(define_constraint "Ud"
+ "64-bit int whose high/low words separately satisfy I, Ub, or Uc"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_Ud (ival)")))
+
+(define_constraint "Ug"
+ "Constant in range [-508, -4] that is divisible by 4"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_Ug (ival)")))
+
+(define_constraint "Uh"
+ "Constant in range [-31, 0]"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_Uh (ival)")))
+
+(define_constraint "Uj"
+ "Constant in range [4, 1024] that is divisible by 4"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_Uj (ival)")))
+
+(define_constraint "Uk"
+ "Constant in range [1, 65536]"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_Uk (ival)")))
+
+(define_constraint "Ul"
+ "Constant in range [-1024, -4] that is divisible by 4"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_Ul (ival)")))
+
+(define_constraint "Um"
+ "Constant in range [-4096, -1]"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_Um (ival)")))
+
+(define_constraint "Un"
+ "Constant whose low 16 bits are all zeros"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_MOVIH (ival)")))
+
+(define_constraint "Uo"
+ "Constant that can be synthesized with an extra instruction"
+ (and (match_code "const_int")
+ (match_test "csky_inlinable_constant (ival)")))
+
+(define_constraint "Up"
+ "Constant in range [0, 255]"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_N (ival + 1)")))
+
+(define_constraint "Uq"
+ "Constant in range [0, 1020] that is divisible by 4"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_Uj (ival + 4)")))
+
+(define_constraint "Ur"
+ "Constant in range [-1020, -4] that is divisible by 4"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_Uj (-ival + 4)")))
+
+(define_constraint "Us"
+ "Constant in range [-8, -1]"
+ (and (match_code "const_int")
+ (match_test "CSKY_CONST_OK_FOR_US (ival)")))
diff --git a/gcc/config/csky/csky-elf.h b/gcc/config/csky/csky-elf.h
new file mode 100644
index 0000000..822caed
--- /dev/null
+++ b/gcc/config/csky/csky-elf.h
@@ -0,0 +1,81 @@
+/* Declarations for bare-metal C-SKY targets.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ Contributed by C-SKY Microsystems and Mentor Graphics.
+
+ 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/>. */
+
+
+/******************************************************************
+ * Run-time Target Specification *
+ ******************************************************************/
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "crt0.o%s crti.o%s crtbegin.o%s"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
+
+#undef CC1_SPEC
+#define CC1_SPEC \
+ "%{EB:-EB} \
+ %{EL:-EL} \
+ %{fpic|fPIC:-DPIC} \
+ %{march=ck803s:-march=ck803} \
+ "
+
+#undef ASM_SPEC
+#define ASM_SPEC \
+ "%{mbig-endian:-mbig-endian} \
+ %{EB:-EB} \
+ %{EL:-EL} \
+ %{fpic|fPIC:-pic} \
+ %{mcpu=*:-mcpu=%*} \
+ %{march=*:-march=%*} \
+ %{mhard-float:-mhard-float} \
+ %{melrw:-melrw} \
+ %{mno-elrw:-mno-elrw} \
+ %{mistack:-mistack} \
+ %{mno-istack:-mno-istack} \
+ %{mmp:-mmp} \
+ %{mcp:-mcp} \
+ %{mcache:-mcache} \
+ %{msecurity|mmac:-msecurity} \
+ %{mtrust:-mtrust} \
+ %{mdsp:-mdsp} \
+ %{medsp:-medsp} \
+ %{mvdsp:-mvdsp} \
+ "
+
+#undef LINK_SPEC
+#define LINK_SPEC \
+"%{mbig-endian:-EB} \
+ %{EB:-EB} \
+ %{EL:-EL} -X"
+
+#undef LIB_SPEC
+#define LIB_SPEC \
+ "%{pthread:-lpthread} -lc %{mccrt:-lcc-rt}"
+/* FIXME add this to LIB_SPEC when need */
+/* %{!shared:%{profile:-lc_p}%{!profile:-lc}}" */
+
+
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+
+/* Disable features only for Linux toolchains. */
+#undef TARGET_POSIX_IO
+#define TARGET_CSKY_LINUX 0
diff --git a/gcc/config/csky/csky-linux-elf.h b/gcc/config/csky/csky-linux-elf.h
new file mode 100644
index 0000000..19a553c
--- /dev/null
+++ b/gcc/config/csky/csky-linux-elf.h
@@ -0,0 +1,132 @@
+/* Declarations for C-SKY targets running Linux.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ Contributed by C-SKY Microsystems and Mentor Graphics.
+
+ 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/>. */
+
+/******************************************************************
+ * Run-time Target Specification *
+ ******************************************************************/
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{!shared: %{pie:Scrt1.o%s;:crt1.o%s}} \
+ crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+ "%{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s"
+
+#undef CC1_SPEC
+#define CC1_SPEC \
+ "%{EB:-EB} \
+ %{EL:-EL} \
+ "
+
+#undef ASM_SPEC
+#define ASM_SPEC \
+ "%{mbig-endian:-mbig-endian} \
+ %{EB:-EB} \
+ %{EL:-EL} \
+ %{fpic|fPIC:-pic} \
+ %{mcpu=*:-mcpu=%*} \
+ %{march=*:-march=%*} \
+ %{mhard-float:-mhard-float} \
+ %{melrw:-melrw} \
+ %{mno-elrw:-mno-elrw} \
+ %{mistack:-mistack} \
+ %{mno-istack:-mno-istack} \
+ %{mmp:-mmp} \
+ %{mcp:-mcp} \
+ %{mcache:-mcache} \
+ %{msecurity|mmac:-msecurity} \
+ %{mtrust:-mtrust} \
+ %{mdsp:-mdsp} \
+ %{medsp:-medsp} \
+ %{mvdsp:-mvdsp} \
+ "
+
+#define LINUX_DYNAMIC_LINKER "/lib/ld.so.1"
+
+#define LINUX_TARGET_LINK_SPEC "%{h*} %{version:-v} \
+ %{b} \
+ %{static:-Bstatic} \
+ %{shared:-shared} \
+ %{symbolic:-Bsymbolic} \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!shared:-dynamic-linker " LINUX_DYNAMIC_LINKER "}} \
+ -X \
+ %{mbig-endian:-EB} %{mlittle-endian:-EL} \
+ %{EB:-EB} %{EL:-EL}"
+
+
+#undef LINK_SPEC
+#define LINK_SPEC LINUX_TARGET_LINK_SPEC
+
+
+#undef LIB_SPEC
+#define LIB_SPEC \
+ "%{pthread:-lpthread} -lc %{mccrt:-lcc-rt}"
+/* FIXME add this to LIB_SPEC when need */
+/* %{!shared:%{profile:-lc_p}%{!profile:-lc}}" */
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ GNU_USER_TARGET_OS_CPP_BUILTINS (); \
+ } \
+ while (0)
+
+/* In crtstuff.c to control section in where code resides.
+ We have to write it as asm code. */
+#ifdef __PIC__
+#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
+ asm (SECTION_OP "\n" \
+ "\tgrs\tr3, .Lgetpc_"#FUNC"\n\t" \
+ ".Lgetpc_"#FUNC":\n\t" \
+ "\tlrw\tr2,\t.Lgetpc_"#FUNC"@GOTPC\n\t" \
+ "\taddu\tr3, r2\n\t" \
+ "\tlrw\tr2, "#FUNC"@GOTOFF\n\t" \
+ "\taddu\tr2, r3\n\t" \
+ "\tjsr\tr2\n\t"); \
+ FORCE_CODE_SECTION_ALIGN \
+ asm (TEXT_SECTION_ASM_OP);
+#endif
+
+#undef CPP_SPEC
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
+
+#undef FUNCTION_PROFILER
+#define SAVE_LR \
+ "push\tlr"
+#define FUNCTION_PROFILER(file, labelno) \
+ fprintf (file, "\t%s\n\tjbsr\t_mcount\n", SAVE_LR);
+#define NO_PROFILE_COUNTERS 1
+
+/* Enable features only for Linux toolchains. */
+#define TARGET_CSKY_LINUX 1
+
+/* Clear the instruction cache from `BEG' to `END'. */
+#define CLEAR_INSN_CACHE(BEG, END) \
+ cacheflush (BEG, END-BEG, 3)
+
+/* For __clear_cache in libgcc2.c. The declaration is copied from
+ <sys/cachectl.h>. */
+#ifdef IN_LIBGCC2
+extern int cacheflush (void *__addr, const int __nbytes, const int __op);
+#endif
diff --git a/gcc/config/csky/csky-protos.h b/gcc/config/csky/csky-protos.h
new file mode 100644
index 0000000..c10267a
--- /dev/null
+++ b/gcc/config/csky/csky-protos.h
@@ -0,0 +1,71 @@
+/* Prototype declarations for the C-SKY back end.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ Contributed by C-SKY Microsystems and Mentor Graphics.
+
+ 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_CSKY_PROTOS_H
+#define GCC_CSKY_PROTOS_H
+
+extern bool csky_simple_addr_operand_p (rtx);
+extern bool csky_symbolic_address_p (rtx);
+extern bool csky_legitimate_pic_operand_p (rtx);
+
+extern void csky_cpu_cpp_builtins (cpp_reader *);
+
+extern bool csky_inlinable_constant (HOST_WIDE_INT value);
+extern bool csky_shifted_imm8_constant (unsigned HOST_WIDE_INT,
+ unsigned int *, unsigned int *);
+extern bool csky_valid_fpuv2_mem_operand (rtx);
+
+extern bool csky_minipool_load_p (rtx_insn *);
+extern const char *csky_output_move (rtx insn, rtx *, machine_mode);
+extern const char *csky_output_movedouble (rtx *, machine_mode);
+extern const char *csky_output_ck801_move (rtx, rtx *, machine_mode);
+extern const char *csky_output_ck801_movedouble (rtx *, machine_mode);
+extern char *csky_output_call (rtx *, int);
+extern const char *csky_output_casesi (rtx *);
+
+extern bool csky_split_and (rtx *);
+extern bool csky_split_ior (rtx *);
+extern bool csky_split_xor (rtx *);
+
+#ifdef RTX_CODE
+extern bool csky_emit_compare (enum rtx_code, rtx, rtx);
+extern bool csky_emit_compare_float (enum rtx_code, rtx, rtx);
+#endif /* RTX_CODE */
+
+extern rtx csky_return_addr (int, rtx);
+extern void csky_init_expanders (void);
+extern HOST_WIDE_INT csky_initial_elimination_offset (int, int);
+extern void csky_expand_prologue (void);
+extern void csky_expand_epilogue (void);
+extern const char *csky_output_return_instruction (void);
+extern void csky_set_eh_return_address (rtx, rtx);
+
+extern bool csky_symbol_mentioned_p (rtx);
+extern bool csky_label_mentioned_p (rtx);
+extern rtx csky_legitimize_pic_address (rtx, rtx, bool);
+
+extern bool csky_tls_referenced_p (rtx);
+extern rtx csky_legitimize_tls_address (rtx, rtx);
+
+extern int csky_compute_pushpop_length (rtx *);
+
+extern int csky_default_branch_cost (bool, bool);
+extern bool csky_default_logical_op_non_short_circuit (void);
+#endif /* GCC_CSKY_PROTOS_H */
diff --git a/gcc/config/csky/csky.c b/gcc/config/csky/csky.c
new file mode 100644
index 0000000..a9e196b
--- /dev/null
+++ b/gcc/config/csky/csky.c
@@ -0,0 +1,6795 @@
+/* GCC backend functions for C-SKY targets.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ Contributed by C-SKY Microsystems and Mentor Graphics.
+
+ 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/>. */
+
+#define IN_TARGET_CODE 1
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "memmodel.h"
+#include "backend.h"
+#include "target.h"
+#include "rtl.h"
+#include "tree.h"
+#include "cfghooks.h"
+#include "df.h"
+#include "tm_p.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "optabs.h"
+#include "regs.h"
+#include "emit-rtl.h"
+#include "recog.h"
+#include "cgraph.h"
+#include "c-family/c-common.h"
+#include "cpplib.h"
+#include "diagnostic-core.h"
+#include "alias.h"
+#include "fold-const.h"
+#include "stor-layout.h"
+#include "calls.h"
+#include "varasm.h"
+#include "output.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "reload.h"
+#include "explow.h"
+#include "expr.h"
+#include "cfgrtl.h"
+#include "sched-int.h"
+#include "common/common-target.h"
+#include "langhooks.h"
+#include "intl.h"
+#include "libfuncs.h"
+#include "params.h"
+#include "opts.h"
+#include "dumpfile.h"
+#include "target-globals.h"
+#include "builtins.h"
+#include "tm-constrs.h"
+#include "rtl-iter.h"
+#include "pass_manager.h"
+#include "tree-pass.h"
+#include "context.h"
+
+/* This file should be included last. */
+#include "target-def.h"
+
+/* Stack and register size macros. */
+
+#define CSKY_NUM_WORDS(SIZE) \
+ (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+#define CSKY_NUM_REGS(MODE) \
+ CSKY_NUM_WORDS (GET_MODE_SIZE (MODE))
+#define CSKY_STACK_ALIGN(SIZE) \
+ (CSKY_NUM_WORDS (SIZE) * UNITS_PER_WORD)
+
+/* Offsets and range macros. */
+
+#define CSKY_LD16_MAX_OFFSET(MODE) \
+ (31 * GET_MODE_SIZE (MODE))
+#define CSKY_LD32_MAX_OFFSET(MODE) \
+ (4095 * GET_MODE_SIZE (MODE))
+#define CSKY_LD16_OFFSET_MASK(MODE) \
+ (CSKY_LD16_MAX_OFFSET (MODE) + GET_MODE_SIZE (MODE) - 1)
+
+#define CSKY_ADDI16_MAX_IMM 256
+#define CSKY_SUBI16_MAX_IMM 256
+
+#define CSKY_CONSTPOOL_LABEL_PREFIX "LCP"
+
+/* Array of the smallest class containing reg number REGNO, indexed by
+ REGNO. Used by REGNO_REG_CLASS. */
+enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER] =
+{
+ /* Registers r0-r7. */
+ MINI_REGS, MINI_REGS, MINI_REGS, MINI_REGS,
+ MINI_REGS, MINI_REGS, MINI_REGS, MINI_REGS,
+ /* Registers r8-r15. */
+ LOW_REGS, LOW_REGS, LOW_REGS, LOW_REGS,
+ LOW_REGS, LOW_REGS, SP_REGS, LOW_REGS,
+ /* Registers r16-r31. */
+ GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
+ GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
+ GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
+ GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
+ /* Reserved. */
+ RESERVE_REGS,
+ /* CC,HI,LO registers. */
+ C_REGS, HI_REGS, LO_REGS,
+ /* Reserved. */
+ RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS,
+ RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS,
+ RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS,
+ RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS,
+ /* Vec registers. */
+ V_REGS, V_REGS, V_REGS, V_REGS,
+ V_REGS, V_REGS, V_REGS, V_REGS,
+ V_REGS, V_REGS, V_REGS, V_REGS,
+ V_REGS, V_REGS, V_REGS, V_REGS,
+ /* Reserved. */
+ RESERVE_REGS, RESERVE_REGS,
+ /* Register epc. */
+ OTHER_REGS
+};
+
+/* Arrays that map GCC register numbers to debugger register numbers,
+ '-1' means that is INVALID_REGNUM.
+ TODO: which rules according to here ? */
+const int csky_dbx_regno[FIRST_PSEUDO_REGISTER] =
+{
+ 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,
+ -1, -1, 36, 37, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 71, -1, -1, 72
+};
+
+/* Table of machine attributes. */
+static tree csky_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
+static tree csky_handle_isr_attribute (tree *, tree, tree, int, bool *);
+static const struct attribute_spec csky_attribute_table[] =
+{
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+ affects_type_identity, handler, exclude } */
+ { "naked", 0, 0, true, false, false, false, csky_handle_fndecl_attribute, NULL },
+ /* Interrupt Service Routines have special prologue and epilogue requirements. */
+ { "interrupt", 0, 1, false, false, false, false, csky_handle_isr_attribute, NULL },
+ { "isr", 0, 1, false, false, false, false, csky_handle_isr_attribute, NULL },
+ { NULL, 0, 0, false, false, false, false, NULL, NULL }
+};
+
+/* A C structure for machine-specific, per-function data.
+ This is added to the cfun structure. */
+typedef struct GTY(()) machine_function
+{
+ /* Records if LR has to be saved for far jumps. */
+ int far_jump_used;
+ /* Records the type of the current function. */
+ unsigned long func_type;
+ /* Record if the function has a variable argument list. */
+ int uses_anonymous_args;
+
+ /* Stack frame layout information. If frame_init_p is true,
+ these fields have been initialized and don't need to be
+ recomputed. */
+ unsigned int reg_mask; /* non-volatile reg saves */
+ int arg_size; /* stdarg spills (bytes) */
+ int reg_size; /* non-volatile reg saves (bytes) */
+ int local_size; /* locals */
+ int outbound_size; /* arg overflow on calls out */
+ int frame_size; /* total static size of stack frame */
+ int local_offset;
+ int reg_offset;
+ int arg_offset;
+ int frame_init_p;
+
+} machine_function;
+
+/* These macros are for the func_type values above. */
+#define CSKY_FT_TYPE_MASK ((1 << 3) - 1)
+#define CSKY_FT_UNKNOWN 0 /* Type not been determined */
+#define CSKY_FT_NORMAL 1 /* Normal function */
+#define CSKY_FT_ISR 4 /* Interrupt service routine */
+#define CSKY_FT_FIQ 5 /* Fast interrupt service routine */
+#define CSKY_FT_EXCEPTION 6 /* Exception handler */
+#define CSKY_FT_INTERRUPT (1 << 2) /* overlap CSKY_FT_ISR */
+#define CSKY_FT_NAKED (1 << 3) /* No prologue and epilogue */
+#define CSKY_FUNCTION_TYPE(t) ((t) & CSKY_FT_TYPE_MASK)
+#define CSKY_FUNCTION_IS_INTERRUPT(t) ((t) & CSKY_FT_INTERRUPT)
+#define CSKY_FUNCTION_IS_NAKED(t) ((t) & CSKY_FT_NAKED)
+
+struct csky_processors
+{
+ const char *const name;
+ enum csky_processor_type core;
+ const char *arch;
+ enum csky_base_architecture base_arch;
+ enum csky_isa_feature isa_bits[CSKY_ISA_FEATURE_GET (max)];
+};
+
+static struct csky_processors all_cores[] =
+{
+#undef CSKY_CORE
+#define CSKY_CORE(NAME, CORE, X, ARCH, ISA) \
+ {NAME, TARGET_CPU_##CORE, #ARCH, CSKY_BASE_ARCH_##ARCH, \
+ {ISA CSKY_ISA_FEATURE_GET (none)}},
+#include "csky_cores.def"
+#undef CSKY_CORE
+ {NULL, TARGET_CPU_csky_none, NULL, CSKY_BASE_ARCH_NONE, \
+ {CSKY_ISA_FEATURE_GET (none)}}
+};
+
+static struct csky_processors all_architectures[] =
+{
+#undef CSKY_ARCH
+#define CSKY_ARCH(NAME, CORE, ARCH, ISA) \
+ {NAME, TARGET_CPU_##CORE, #ARCH, CSKY_BASE_ARCH_##ARCH, \
+ {ISA CSKY_ISA_FEATURE_GET (none)}},
+#include "csky_cores.def"
+#undef CSKY_ARCH
+ {NULL, TARGET_CPU_csky_none, NULL, CSKY_BASE_ARCH_NONE, \
+ {CSKY_ISA_FEATURE_GET (none)}}
+};
+
+struct csky_fpu_desc
+{
+ const char *name;
+ enum csky_isa_feature isa_bits[CSKY_ISA_FEATURE_GET (max)];
+};
+
+static const struct csky_fpu_desc all_fpus[] =
+{
+#undef CSKY_FPU
+#define CSKY_FPU(NAME, CNAME, ISA) \
+ {NAME, {ISA CSKY_ISA_FEATURE_GET (none)}},
+#include "csky_cores.def"
+#undef CSKY_FPU
+};
+
+/* Active target architecture. */
+struct csky_build_target
+{
+ /* Name of the target CPU, if known, or NULL if the target CPU was not
+ specified by the user (and inferred from the -march option). */
+ const char *core_name;
+ /* Name of the target ARCH. NULL if there is a selected CPU. */
+ const char *arch_name;
+ /* Preprocessor substring (never NULL). */
+ const char *arch_pp_name;
+ /* CPU identifier for the core we're compiling for (architecturally). */
+ enum csky_processor_type arch_core;
+ /* The base architecture value. */
+ enum csky_base_architecture base_arch;
+ /* Bitmap encapsulating the isa_bits for the target environment. */
+ sbitmap isa;
+};
+
+struct csky_build_target csky_active_target;
+
+/* The following are used in the .md file as equivalents to bits. */
+int csky_arch_isa_features[CSKY_ISA_FEATURE_GET (max)] = {0};
+
+/* The highest CSKY architecture version supported by the target. */
+enum csky_base_architecture csky_base_arch = CSKY_TARGET_ARCH_GET (NONE);
+
+/* Forward definitions of types. */
+typedef struct minipool_node Mnode;
+typedef struct minipool_fixup Mfix;
+
+static GTY(()) int tls_labelno;
+
+
+/* Maximum constant offset that can be added/subtracted from SP in a
+ single instruction. For ck801, this is for addsp/subsp, otherwise
+ it is the range of addi/subi. */
+#define CSKY_MAX_SP_ADJUST \
+ (CSKY_TARGET_ARCH (CK801) ? 508 : 4096)
+
+
+/* Implement TARGET_CPU_CPP_BUILTINS. */
+
+#define builtin_define(MACRO) cpp_define (pfile, MACRO)
+
+void
+csky_cpu_cpp_builtins (cpp_reader *pfile)
+{
+ const char *arch_name = csky_active_target.arch_pp_name;
+ char *pp_name = (char *) alloca (1 + strlen (arch_name) + 4);
+ sprintf (pp_name, "__%s__", arch_name);
+ builtin_define (pp_name);
+
+ builtin_define ("__csky__=2");
+ builtin_define ("__CSKY__=2");
+ builtin_define ("__ckcore__=2");
+ builtin_define ("__CKCORE__=2");
+
+ builtin_define ("__CSKYABIV2__");
+ builtin_define ("__cskyabiv2__");
+ builtin_define ("__CSKYABI__=2");
+ builtin_define ("__cskyabi__=2");
+
+ if (TARGET_BIG_ENDIAN)
+ {
+ builtin_define ("__ckcoreBE__");
+ builtin_define ("__cskyBE__");
+ builtin_define ("__cskybe__");
+ builtin_define ("__CSKYBE__");
+ }
+ else
+ {
+ builtin_define ("__ckcoreLE__");
+ builtin_define ("__cskyLE__");
+ builtin_define ("__cskyle__");
+ builtin_define ("__CSKYLE__");
+ }
+
+ if (TARGET_HARD_FLOAT)
+ {
+ builtin_define ("__csky_hard_float__");
+ builtin_define ("__CSKY_HARD_FLOAT__");
+ }
+ else
+ {
+ builtin_define ("__csky_soft_float__");
+ builtin_define ("__CSKY_SOFT_FLOAT__");
+ }
+
+ if (CSKY_ISA_FEATURE (fpv2_sf))
+ {
+ builtin_define ("__csky_fpuv2__");
+ builtin_define ("__CSKY_FPUV2__");
+ }
+
+ if (TARGET_ELRW)
+ {
+ builtin_define ("__csky_elrw__");
+ builtin_define ("__CSKY_ELRW__");
+ }
+ if (TARGET_ISTACK)
+ {
+ builtin_define ("__csky_istack__");
+ builtin_define ("__CSKY_ISTACK__");
+ }
+ if (TARGET_MP)
+ {
+ builtin_define ("__csky_mp__");
+ builtin_define ("__CSKY_MP__");
+ }
+ if (TARGET_CP)
+ {
+ builtin_define ("__csky_cp__");
+ builtin_define ("__CSKY_CP__");
+ }
+ if (TARGET_CACHE)
+ {
+ builtin_define ("__csky_cache__");
+ builtin_define ("__CSKY_CACHE__");
+ }
+ if (TARGET_SECURITY)
+ {
+ builtin_define ("__csky_security__");
+ builtin_define ("__CSKY_SECURITY__");
+ }
+ if (TARGET_TRUST)
+ {
+ builtin_define ("__csky_trust__");
+ builtin_define ("__CSKY_TRUST__");
+ }
+ if (TARGET_DSP)
+ {
+ builtin_define ("__csky_dsp__");
+ builtin_define ("__CSKY_DSP__");
+ }
+ if (TARGET_EDSP)
+ {
+ builtin_define ("__csky_edsp__");
+ builtin_define ("__CSKY_EDSP__");
+ }
+ if (TARGET_VDSP)
+ {
+ builtin_define ("__csky_vdsp__");
+ builtin_define ("__CSKY_VDSP__");
+ }
+}
+
+
+/******************************************************************
+ * Storage Layout *
+ ******************************************************************/
+
+
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE \
+ default_promote_function_mode_always_promote
+
+#undef TARGET_CONSTANT_ALIGNMENT
+#define TARGET_CONSTANT_ALIGNMENT csky_constant_alignment
+
+
+/******************************************************************
+ * Stack Layout and Calling Conventions *
+ ******************************************************************/
+
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE csky_can_eliminate
+
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG csky_function_arg
+
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE csky_function_arg_advance
+
+#undef TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE csky_function_value
+
+#undef TARGET_LIBCALL_VALUE
+#define TARGET_LIBCALL_VALUE csky_libcall_value
+
+#undef TARGET_FUNCTION_VALUE_REGNO_P
+#define TARGET_FUNCTION_VALUE_REGNO_P csky_function_value_regno_p
+
+#undef TARGET_SPLIT_COMPLEX_ARG
+#define TARGET_SPLIT_COMPLEX_ARG hook_bool_const_tree_true
+
+#undef TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
+
+#undef TARGET_MUST_PASS_IN_STACK
+#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
+
+#undef TARGET_ARG_PARTIAL_BYTES
+#define TARGET_ARG_PARTIAL_BYTES csky_arg_partial_bytes
+
+#undef TARGET_PASS_BY_REFERENCE
+#define TARGET_PASS_BY_REFERENCE hook_pass_by_reference_must_pass_in_stack
+
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK csky_output_mi_thunk
+
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
+ hook_bool_const_tree_hwi_hwi_const_tree_true
+
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE csky_output_function_prologue
+
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE csky_output_function_epilogue
+
+#undef TARGET_WARN_FUNC_RETURN
+#define TARGET_WARN_FUNC_RETURN csky_warn_func_return
+
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY csky_return_in_memory
+
+
+/******************************************************************
+ * Implementing the Varargs Macros *
+ ******************************************************************/
+
+
+#undef TARGET_SETUP_INCOMING_VARARGS
+#define TARGET_SETUP_INCOMING_VARARGS csky_setup_incoming_varargs
+
+
+/******************************************************************
+ * Implicit Calls to Library Routines *
+ ******************************************************************/
+
+
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS csky_init_libfuncs
+
+
+/******************************************************************
+ * Dividing the Output into Sections (Texts, Data, . . . ) *
+ ******************************************************************/
+
+
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS TARGET_CSKY_LINUX
+
+
+/******************************************************************
+ * Defining target-specific uses of __attribute__ *
+ ******************************************************************/
+
+
+#undef TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE csky_attribute_table
+
+#undef TARGET_OPTION_OVERRIDE
+#define TARGET_OPTION_OVERRIDE csky_option_override
+
+
+/* Implement the BRANCH_COST target macro. */
+
+int
+csky_default_branch_cost (bool speed_p ATTRIBUTE_UNUSED,
+ bool predictable_p ATTRIBUTE_UNUSED)
+{
+ return csky_branch_cost;
+}
+
+bool
+csky_default_logical_op_non_short_circuit (void)
+{
+ return BRANCH_COST (optimize_function_for_speed_p (cfun), false) >= 2;
+}
+
+/******************************************************************
+ * Register Usage *
+ ******************************************************************/
+
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS csky_hard_regno_nregs
+
+#undef TARGET_HARD_REGNO_MODE_OK
+#define TARGET_HARD_REGNO_MODE_OK csky_hard_regno_mode_ok
+
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P csky_modes_tieable_p
+
+#undef TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS csky_can_change_mode_class
+
+#undef TARGET_CONDITIONAL_REGISTER_USAGE
+#define TARGET_CONDITIONAL_REGISTER_USAGE csky_conditional_register_usage
+
+#undef TARGET_CLASS_LIKELY_SPILLED_P
+#define TARGET_CLASS_LIKELY_SPILLED_P csky_class_likely_spilled_p
+
+#undef TARGET_PREFERRED_RELOAD_CLASS
+#define TARGET_PREFERRED_RELOAD_CLASS csky_preferred_reload_class
+
+#undef TARGET_CLASS_MAX_NREGS
+#define TARGET_CLASS_MAX_NREGS csky_class_max_nregs
+
+#undef TARGET_SECONDARY_RELOAD
+#define TARGET_SECONDARY_RELOAD csky_secondary_reload
+
+#undef TARGET_SPILL_CLASS
+#define TARGET_SPILL_CLASS csky_spill_class
+
+
+/******************************************************************
+ * Addressing Modes *
+ ******************************************************************/
+
+
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM csky_cannot_force_const_mem
+
+#undef TARGET_LEGITIMATE_CONSTANT_P
+#define TARGET_LEGITIMATE_CONSTANT_P csky_legitimate_constant_p
+
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS csky_legitimize_address
+
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P csky_legitimate_address_p
+
+
+/******************************************************************
+ * Others *
+ ******************************************************************/
+
+
+#undef TARGET_CANNOT_COPY_INSN_P
+#define TARGET_CANNOT_COPY_INSN_P csky_cannot_copy_insn_p
+
+
+/******************************************************************
+ * Assembler Format *
+ ******************************************************************/
+
+
+#undef TARGET_PRINT_OPERAND
+#define TARGET_PRINT_OPERAND csky_print_operand
+
+#undef TARGET_PRINT_OPERAND_ADDRESS
+#define TARGET_PRINT_OPERAND_ADDRESS csky_print_operand_address
+
+#undef TARGET_ASM_UNALIGNED_HI_OP
+#define TARGET_ASM_UNALIGNED_HI_OP "\t.short\t"
+
+#undef TARGET_ASM_UNALIGNED_SI_OP
+#define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
+
+#undef TARGET_DWARF_REGISTER_SPAN
+#define TARGET_DWARF_REGISTER_SPAN csky_dwarf_register_span
+
+
+/******************************************************************
+ * Miscellaneous Parameters *
+ ******************************************************************/
+
+
+#undef TARGET_MACHINE_DEPENDENT_REORG
+#define TARGET_MACHINE_DEPENDENT_REORG csky_reorg
+
+#undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
+#define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS csky_allocate_stack_slots_for_args
+
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
+
+/******************************************************************
+ * Trampolines for Nested Functions *
+ ******************************************************************/
+
+
+#undef TARGET_ASM_TRAMPOLINE_TEMPLATE
+#define TARGET_ASM_TRAMPOLINE_TEMPLATE csky_asm_trampoline_template
+#undef TARGET_TRAMPOLINE_INIT
+#define TARGET_TRAMPOLINE_INIT csky_trampoline_init
+
+/* The low bit is ignored by jsr and jmp instructions so is safe to use. */
+#undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
+#define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 1
+
+/******************************************************************
+ * Describing Relative Costs of Operations *
+ ******************************************************************/
+
+
+#undef TARGET_REGISTER_MOVE_COST
+#define TARGET_REGISTER_MOVE_COST csky_register_move_cost
+
+#undef TARGET_MEMORY_MOVE_COST
+#define TARGET_MEMORY_MOVE_COST csky_memory_move_cost
+
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS csky_rtx_costs
+
+#undef TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST csky_address_cost
+
+
+/******************************************************************
+ * Anchor address *
+ ******************************************************************/
+
+
+/* FIXME: the max offset is related to mode size, the following is
+ defined according to SImode. How to deal with HImode and
+ QImode, and should the min offset be defined? */
+#undef TARGET_MAX_ANCHOR_OFFSET
+#define TARGET_MAX_ANCHOR_OFFSET \
+ ((TARGET_MINI_REGISTERS && optimize_size) ? 127 : 4095)
+
+
+/******************************************************************
+ * Condition Code Status *
+ ******************************************************************/
+
+
+#undef TARGET_FIXED_CONDITION_CODE_REGS
+#define TARGET_FIXED_CONDITION_CODE_REGS csky_fixed_condition_code_regs
+
+
+/******************************************************************
+ * Adjusting the Instruction Scheduler *
+ ******************************************************************/
+
+
+#undef TARGET_SCHED_ISSUE_RATE
+#define TARGET_SCHED_ISSUE_RATE csky_sched_issue_rate
+
+#undef TARGET_SCHED_ADJUST_COST
+#define TARGET_SCHED_ADJUST_COST csky_sched_adjust_cost
+
+
+/* The declaration of functions. */
+static void push_csky_minipool_fix (rtx_insn *, HOST_WIDE_INT, rtx *,
+ machine_mode, rtx);
+static void csky_print_operand (FILE *stream, rtx x, int code);
+
+
+/* Define a table to map ISR attribute arguments onto function type
+ modifiers. */
+
+typedef struct
+{
+ const char *const arg;
+ const unsigned long return_value;
+} isr_attribute_entry;
+
+static const isr_attribute_entry isr_attribute_map[] =
+{
+ {"irq", CSKY_FT_ISR },
+ {"IRQ", CSKY_FT_ISR },
+ {"fiq", CSKY_FT_FIQ },
+ {"FIQ", CSKY_FT_FIQ },
+ {NULL, CSKY_FT_NORMAL }
+};
+
+
+/* Return the function type of the current function, if it has not been
+ determined, return CSKY_FT_UNKNOWN. */
+
+static unsigned long
+get_csky_isr_type (tree argument)
+{
+ const isr_attribute_entry *ptr;
+ const char *arg;
+
+ /* if argument is NULL, set default value ISR. */
+ if (argument == NULL_TREE)
+ return CSKY_FT_ISR;
+
+ if (TREE_VALUE (argument) == NULL_TREE
+ || TREE_CODE (TREE_VALUE (argument)) != STRING_CST)
+ return CSKY_FT_UNKNOWN;
+
+ arg = TREE_STRING_POINTER (TREE_VALUE (argument));
+
+ for (ptr = isr_attribute_map; ptr->arg != NULL; ptr++)
+ if (strcmp (arg, ptr->arg) == 0)
+ return ptr->return_value;
+
+ return CSKY_FT_UNKNOWN;
+}
+
+/* Classify cfun as a normal function or some sort of interrupt
+ handler, and set the corresponding bits in cfun->machine->func_type. */
+
+static unsigned long
+get_csky_current_func_type (void)
+{
+ if (CSKY_FUNCTION_TYPE (cfun->machine->func_type) == CSKY_FT_UNKNOWN)
+ {
+ unsigned long type = CSKY_FT_UNKNOWN;
+ tree a;
+ tree attr;
+
+ gcc_assert (TREE_CODE (current_function_decl) == FUNCTION_DECL);
+
+ attr = DECL_ATTRIBUTES (current_function_decl);
+ a = lookup_attribute ("naked", attr);
+ if (a != NULL_TREE)
+ type |= CSKY_FT_NAKED;
+ a = lookup_attribute ("isr", attr);
+ if (a == NULL_TREE)
+ a = lookup_attribute ("interrupt", attr);
+ if (a == NULL_TREE)
+ type |= CSKY_FT_NORMAL;
+ else
+ type |= get_csky_isr_type (TREE_VALUE (a));
+
+ cfun->machine->func_type = type;
+ }
+
+ return cfun->machine->func_type;
+}
+
+/* These typedefs are located at the start of this file, so that
+ they can be used in the prototypes there. This comment is to
+ remind readers of that fact so that the following structures
+ can be understood more easily.
+
+ typedef struct minipool_node Mnode;
+ typedef struct minipool_fixup Mfix; */
+
+struct minipool_node
+{
+ /* Doubly linked chain of entries. */
+ Mnode *next;
+ Mnode *prev;
+ /* The maximum offset into the code that this entry can be placed. While
+ pushing fixes for forward references, all entries are sorted in order
+ of increasing max_address. */
+ HOST_WIDE_INT max_address;
+ /* Similarly for an entry inserted for a backwards ref. */
+ HOST_WIDE_INT min_address;
+ /* The number of fixes referencing this entry. This can become zero
+ if we "unpush" an entry. In this case we ignore the entry when we
+ come to emit the code. */
+ int refcount;
+ /* The offset from the start of the minipool. */
+ HOST_WIDE_INT offset;
+ /* The value in table. */
+ rtx value;
+ /* The mode of value. */
+ machine_mode mode;
+ /* The size of the value. */
+ int fix_size;
+};
+
+struct minipool_fixup
+{
+ Mfix *next;
+ rtx_insn *insn;
+ HOST_WIDE_INT address;
+ rtx *loc;
+ machine_mode mode;
+ int fix_size;
+ rtx value;
+ Mnode *minipool;
+ HOST_WIDE_INT forwards;
+ HOST_WIDE_INT backwards;
+};
+
+static Mnode *minipool_vector_head;
+static Mnode *minipool_vector_tail;
+static rtx minipool_vector_label;
+static HOST_WIDE_INT constpool_label_no = 0;
+
+/* Obstack for minipool constant handling. */
+static struct obstack minipool_obstack;
+static char *minipool_startobj;
+/* The linked list of all minipool fixes required for this function. */
+Mfix *minipool_fix_head;
+Mfix *minipool_fix_tail;
+/* The fix entry for the current minipool, once it has been placed. */
+Mfix *minipool_barrier;
+
+/* Allow GC scanning of the minipool obstack. */
+static void
+csky_add_gc_roots (void)
+{
+ gcc_obstack_init (&minipool_obstack);
+ minipool_startobj = (char *) obstack_alloc (&minipool_obstack, 0);
+}
+
+/* Implement TARGET_CONSTANT_ALIGNMENT.
+ Make strings word-aligned so strcpy from constants will be faster. */
+static HOST_WIDE_INT
+csky_constant_alignment (const_tree exp, HOST_WIDE_INT align)
+{
+ if (TREE_CODE (exp) == STRING_CST
+ && !optimize_size
+ && align < BITS_PER_WORD)
+ return BITS_PER_WORD;
+ return align;
+}
+
+/* Record that there is a natural barrier in the insn stream at
+ ADDRESS. */
+
+static void
+push_csky_minipool_barrier (rtx_insn *insn, HOST_WIDE_INT address)
+{
+ Mfix *fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (*fix));
+
+ fix->insn = insn;
+ fix->address = address;
+
+ fix->next = NULL;
+ if (minipool_fix_head != NULL)
+ minipool_fix_tail->next = fix;
+ else
+ minipool_fix_head = fix;
+
+ minipool_fix_tail = fix;
+}
+
+/* Compute the size of a vector jump table. */
+
+static HOST_WIDE_INT
+get_csky_jump_table_size (rtx insn)
+{
+ /* ADDR_VECs only take room if read-only data does into the text
+ section. */
+ if (JUMP_TABLES_IN_TEXT_SECTION || readonly_data_section == text_section)
+ {
+ rtx body = PATTERN (insn);
+ int elt = GET_CODE (body) == ADDR_DIFF_VEC ? 1 : 0;
+ HOST_WIDE_INT size;
+ HOST_WIDE_INT modesize;
+
+ modesize = GET_MODE_SIZE (GET_MODE (body));
+ size = modesize * XVECLEN (body, elt);
+ switch (modesize)
+ {
+ case 1:
+ /* Round up size of TBB table to a halfword boundary. */
+ size = (size + 1) & ~(HOST_WIDE_INT)1;
+ break;
+ case 2:
+ /* No padding necessary for TBH. */
+ break;
+ case 4:
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ return size;
+ }
+
+ return 0;
+}
+
+
+/* Scan INSN and note any of its operands that need fixing.
+ If DO_PUSHES is false we do not actually push any of the fixups
+ needed. The function returns TRUE if any fixups were needed/pushed. */
+
+static bool
+note_csky_invalid_constants (rtx_insn *insn, HOST_WIDE_INT address,
+ int do_pushes)
+{
+ bool result = false;
+ int opno;
+
+ extract_constrain_insn (insn);
+
+ if (recog_data.n_alternatives == 0)
+ return false;
+
+ /* Fill in recog_op_alt with information about the constraints of
+ this insn. */
+ preprocess_constraints (insn);
+
+ const operand_alternative *op_alt = which_op_alt ();
+ for (opno = 0; opno < recog_data.n_operands; opno++)
+ {
+ /* Things we need to fix can only occur in inputs. */
+ if (recog_data.operand_type[opno] != OP_IN)
+ continue;
+
+ /* If this alternative is a memory reference, then any mention
+ of constants in this alternative is really to fool reload
+ into allowing us to accept one there. We need to fix them up
+ now so that we output the right code. */
+ if (op_alt[opno].memory_ok)
+ {
+ rtx op = recog_data.operand[opno];
+
+ if (CONSTANT_P (op))
+ {
+ if (do_pushes)
+ push_csky_minipool_fix (insn, address,
+ recog_data.operand_loc[opno],
+ recog_data.operand_mode[opno], op);
+ result = true;
+ }
+ }
+ }
+
+ return result;
+}
+
+
+/* Add a constant to the minipool for a forward reference. Returns the
+ node added or NULL if the constant will not fit in this pool. */
+
+static Mnode *
+add_csky_minipool_forward_ref (Mfix *fix)
+{
+ /* If set, max_mp is the first pool_entry that has a lower
+ constraint than the one we are trying to add. */
+ Mnode *max_mp = NULL;
+ HOST_WIDE_INT max_address = fix->address + fix->forwards;
+ Mnode *mp;
+
+ /* If the minipool starts before the end of FIX->INSN then this FIX
+ can not be placed into the current pool. Furthermore, adding the
+ new constant pool entry may cause the pool to start FIX_SIZE bytes
+ earlier. */
+ if (minipool_vector_head
+ && (fix->address + get_attr_length (fix->insn)
+ >= minipool_vector_head->max_address - fix->fix_size))
+ return NULL;
+
+ /* Scan the pool to see if a constant with the same value has
+ already been added. While we are doing this, also note the
+ location where we must insert the constant if it doesn't already
+ exist. */
+ for (mp = minipool_vector_head; mp != NULL; mp = mp->next)
+ {
+ if (GET_CODE (fix->value) == GET_CODE (mp->value)
+ && fix->mode == mp->mode
+ && (GET_CODE (fix->value) != CODE_LABEL
+ || (CODE_LABEL_NUMBER (fix->value)
+ == CODE_LABEL_NUMBER (mp->value)))
+ && rtx_equal_p (fix->value, mp->value))
+ {
+ /* More than one fix references this entry. */
+ mp->refcount++;
+ return mp;
+ }
+
+ /* Note the insertion point if necessary. */
+ if (max_mp == NULL && mp->max_address > max_address)
+ max_mp = mp;
+ }
+
+ /* The value is not currently in the minipool, so we need to create
+ a new entry for it. If MAX_MP is NULL, the entry will be put on
+ the end of the list since the placement is less constrained than
+ any existing entry. Otherwise, we insert the new fix before
+ MAX_MP and, if necessary, adjust the constraints on the other
+ entries. */
+ mp = XNEW (Mnode);
+ mp->fix_size = fix->fix_size;
+ mp->mode = fix->mode;
+ mp->value = fix->value;
+ mp->refcount = 1;
+ /* Not yet required for a backwards ref. */
+ mp->min_address = -65536;
+
+ if (max_mp == NULL)
+ {
+ mp->max_address = max_address;
+ mp->next = NULL;
+ mp->prev = minipool_vector_tail;
+
+ if (mp->prev == NULL)
+ {
+ minipool_vector_head = mp;
+ minipool_vector_label
+ = gen_csky_constpool_label (gen_rtx_CONST_INT (VOIDmode,
+ constpool_label_no++));
+ }
+ else
+ mp->prev->next = mp;
+
+ minipool_vector_tail = mp;
+ }
+ else
+ {
+ if (max_address > max_mp->max_address - mp->fix_size)
+ mp->max_address = max_mp->max_address - mp->fix_size;
+ else
+ mp->max_address = max_address;
+
+ mp->next = max_mp;
+ mp->prev = max_mp->prev;
+ max_mp->prev = mp;
+ if (mp->prev != NULL)
+ mp->prev->next = mp;
+ else
+ minipool_vector_head = mp;
+ }
+
+ /* Save the new entry. */
+ max_mp = mp;
+
+ /* Scan over the preceding entries and adjust their addresses as
+ required. */
+ while (mp->prev != NULL
+ && mp->prev->max_address > mp->max_address - mp->prev->fix_size)
+ {
+ mp->prev->max_address = mp->max_address - mp->prev->fix_size;
+ mp = mp->prev;
+ }
+
+ return max_mp;
+}
+
+
+/* Return the cost of forcibly inserting a barrier after INSN. */
+
+static int
+get_csky_barrier_cost (rtx_insn *insn)
+{
+ /* Basing the location of the pool on the loop depth is preferable,
+ but at the moment, the basic block information seems to be
+ corrupt by this stage of the compilation. */
+ int base_cost = 50;
+ rtx next = next_nonnote_insn (insn);
+
+ if (next != NULL && GET_CODE (next) == CODE_LABEL)
+ base_cost -= 20;
+
+ switch (GET_CODE (insn))
+ {
+ case CODE_LABEL:
+ /* It will always be better to place the table before the label, rather
+ than after it. */
+ return 50;
+
+ case INSN:
+ case CALL_INSN:
+ return base_cost;
+
+ case JUMP_INSN:
+ return base_cost - 10;
+
+ default:
+ return base_cost + 10;
+ }
+}
+
+
+/* Find the best place in the insn stream in the range
+ (FIX->address,MAX_ADDRESS) to forcibly insert a minipool barrier.
+ Create the barrier by inserting a jump and add a new fix entry for
+ it. */
+static Mfix *
+create_csky_fix_barrier (Mfix *fix, Mfix *fix_next,
+ HOST_WIDE_INT max_address)
+{
+ rtx_barrier *barrier;
+ rtx_insn *from = (fix ? fix->insn : get_insns ());
+ /* The instruction after which we will insert the jump. */
+ rtx_insn *selected = NULL;
+ int selected_cost;
+ /* The address at which the jump instruction will be placed. */
+ HOST_WIDE_INT selected_address = 0;
+ Mfix *new_fix;
+ HOST_WIDE_INT count = (fix ? fix->address : 0);
+ HOST_WIDE_INT max_count = max_address;
+ rtx_code_label *label = gen_label_rtx ();
+
+ selected_cost = get_csky_barrier_cost (from);
+
+ while (from && count < max_count)
+ {
+ int new_cost;
+ rtx_jump_table_data *table;
+
+ /* Count the length of this insn. */
+ count += get_attr_length (from);
+
+ /* If there is a jump table, add its length. */
+ if (tablejump_p (from, NULL, &table))
+ {
+ count += get_csky_jump_table_size (table);
+
+ /* Jump tables aren't in a basic block, so base the cost on
+ the dispatch insn. If we select this location, we will
+ still put the pool after the table. */
+ new_cost = get_csky_barrier_cost (from);
+
+ if (count < max_count
+ && (!selected || new_cost <= selected_cost))
+ {
+ selected = table;
+ selected_cost = new_cost;
+ selected_address = count;
+ }
+
+ /* Continue after the dispatch table. */
+ from = NEXT_INSN (table);
+ continue;
+ }
+
+ new_cost = get_csky_barrier_cost (from);
+
+ if (count < max_count
+ && (!selected || new_cost <= selected_cost))
+ {
+ selected = from;
+ selected_cost = new_cost;
+ selected_address = count;
+ }
+
+ from = NEXT_INSN (from);
+ }
+
+ /* Make sure that we found a place to insert the jump. */
+ gcc_assert (selected);
+
+ /* Create a new JUMP_INSN that branches around a barrier. */
+ from = emit_jump_insn_after (gen_jump (label), selected);
+ JUMP_LABEL (from) = label;
+ barrier = emit_barrier_after (from);
+ emit_label_after (label, barrier);
+
+ /* Create a minipool barrier entry for the new barrier. */
+ new_fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (* new_fix));
+ new_fix->insn = barrier;
+ new_fix->address = selected_address;
+ if (fix)
+ {
+ new_fix->next = fix->next;
+ fix->next = new_fix;
+ }
+ else
+ new_fix->next = fix_next;
+
+ return new_fix;
+}
+
+
+/* Print a symbolic form of the constant X to the dump file F.
+ This is used for dump output for -mconstpool in the target-dependent
+ reorg pass. */
+
+static void
+print_csky_value (FILE *f, rtx x)
+{
+ switch (GET_CODE (x))
+ {
+ case CONST_INT:
+ fprintf (f, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
+ return;
+
+ case CONST_DOUBLE:
+ fprintf (f, "<0x%lx,0x%lx>", (long)XWINT (x, 2), (long)XWINT (x, 3));
+ return;
+
+ case CONST_VECTOR:
+ {
+ int i;
+
+ fprintf (f, "<");
+ for (i = 0; i < CONST_VECTOR_NUNITS (x); i++)
+ {
+ fprintf (f, HOST_WIDE_INT_PRINT_HEX,
+ INTVAL (CONST_VECTOR_ELT (x, i)));
+ if (i < (CONST_VECTOR_NUNITS (x) - 1))
+ fputc (',', f);
+ }
+ fprintf (f, ">");
+ }
+ return;
+
+ case CONST_STRING:
+ fprintf (f, "\"%s\"", XSTR (x, 0));
+ return;
+
+ case SYMBOL_REF:
+ fprintf (f, "`%s'", XSTR (x, 0));
+ return;
+
+ case LABEL_REF:
+ fprintf (f, "L%d", INSN_UID (XEXP (x, 0)));
+ return;
+
+ case CONST:
+ print_csky_value (f, XEXP (x, 0));
+ return;
+
+ case PLUS:
+ print_csky_value (f, XEXP (x, 0));
+ fprintf (f, "+");
+ print_csky_value (f, XEXP (x, 1));
+ return;
+
+ case PC:
+ fprintf (f, "pc");
+ return;
+
+ default:
+ fprintf (f, "????");
+ return;
+ }
+}
+
+
+/* Record INSN, which will need fixing up to load a value from the
+ minipool. ADDRESS is the offset of the insn since the start of the
+ function; LOC is a pointer to the part of the insn which requires
+ fixing; VALUE is the constant that must be loaded, which is of type
+ MODE. */
+
+static void
+push_csky_minipool_fix (rtx_insn *insn, HOST_WIDE_INT address, rtx *loc,
+ machine_mode mode, rtx value)
+{
+ #define CSKY_ELRW16_RANGE 1400
+ #define CSKY_LRW16_RANGE 700
+ #define CSKY_CONSTANT_POOL_RANGE (TARGET_ELRW ? CSKY_ELRW16_RANGE \
+ : CSKY_LRW16_RANGE)
+
+ /* Fixes less than a word need padding out to a word boundary. */
+ #define CSKY_MINIPOOL_FIX_SIZE(mode) \
+ (GET_MODE_SIZE ((mode)) >= 4 ? GET_MODE_SIZE ((mode)) : 4)
+
+ Mfix *fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (*fix));
+
+ fix->insn = insn;
+ fix->address = address;
+ fix->loc = loc;
+ fix->mode = mode;
+ fix->fix_size = CSKY_MINIPOOL_FIX_SIZE (mode);
+ fix->value = value;
+ fix->forwards = CSKY_CONSTANT_POOL_RANGE;
+ fix->backwards = 0;
+ fix->minipool = NULL;
+
+ /* If an insn doesn't have a range defined for it, then it isn't
+ expecting to be reworked by this code. Better to stop now than
+ to generate duff assembly code. */
+ gcc_assert (fix->forwards || fix->backwards);
+
+ if (dump_file)
+ {
+ fprintf (dump_file,
+ ";; %smode fixup for i%d; addr %lu, range (%ld,%ld): ",
+ GET_MODE_NAME (mode),
+ INSN_UID (insn), (unsigned long) address,
+ -1 * (long)fix->backwards, (long)fix->forwards);
+ print_csky_value (dump_file, fix->value);
+ fprintf (dump_file, "\n");
+ }
+
+ /* Add it to the chain of fixes. */
+ fix->next = NULL;
+
+ if (minipool_fix_head != NULL)
+ minipool_fix_tail->next = fix;
+ else
+ minipool_fix_head = fix;
+
+ minipool_fix_tail = fix;
+}
+
+
+/* Fill in the offsets for minipool entries. */
+
+static void
+assign_csky_minipool_offsets (Mfix *barrier)
+{
+ HOST_WIDE_INT offset = 0;
+ Mnode *mp;
+
+ minipool_barrier = barrier;
+
+ for (mp = minipool_vector_head; mp != NULL; mp = mp->next)
+ {
+ mp->offset = offset;
+
+ if (mp->refcount > 0)
+ offset += mp->fix_size;
+ }
+}
+
+
+/* Output the literal table. */
+
+static HOST_WIDE_INT
+dump_csky_minipool (rtx_insn *scan)
+{
+ Mnode *mp;
+ Mnode *nmp;
+ HOST_WIDE_INT pool_length = 0;
+
+ if (dump_file)
+ fprintf (dump_file,
+ ";; Emitting minipool after insn %u;\
+ address %ld; align %d (bytes)\n",
+ INSN_UID (scan), (unsigned long) minipool_barrier->address, 4);
+
+ scan = emit_insn_after (gen_align_4 (), scan);
+ scan = emit_insn_after (minipool_vector_label, scan);
+
+ for (mp = minipool_vector_head; mp != NULL; mp = nmp)
+ {
+ if (mp->refcount > 0)
+ {
+ if (dump_file)
+ {
+ fprintf (dump_file, ";; Offset %u, min %ld, max %ld ",
+ (unsigned) mp->offset, (unsigned long) mp->min_address,
+ (unsigned long) mp->max_address);
+ print_csky_value (dump_file, mp->value);
+ fputc ('\n', dump_file);
+ }
+
+ switch (mp->fix_size)
+ {
+ case 4:
+ scan = emit_insn_after (gen_consttable_4 (mp->value), scan);
+ pool_length += 4;
+ break;
+ case 8:
+ scan = emit_insn_after (gen_consttable_8 (mp->value), scan);
+ pool_length += 8;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ nmp = mp->next;
+ free (mp);
+ }
+
+ minipool_vector_head = minipool_vector_tail = NULL;
+ scan = emit_barrier_after (scan);
+
+ return pool_length;
+}
+
+/* Return true if INSN is a minipool load or instruction that will be
+ converted to one. It is assumed that INSN has type attribute "load". */
+
+bool
+csky_minipool_load_p (rtx_insn *insn)
+{
+ rtx op1, addr;
+
+ extract_insn_cached (insn);
+
+ op1 = recog_data.operand[1];
+
+ /* This is a constant that has not yet been turned into
+ a minipool load. */
+ if (CONSTANT_P (op1))
+ return true;
+
+ /* Constant pool loads are label_refs. */
+ if (GET_CODE (op1) == ZERO_EXTEND || GET_CODE (op1) == SIGN_EXTEND)
+ op1 = XEXP (op1, 0);
+ if (GET_CODE (op1) != MEM)
+ return false;
+ addr = XEXP (op1, 0);
+ if (GET_CODE (addr) == PLUS && CONST_INT_P (XEXP (addr, 1)))
+ addr = XEXP (addr, 0);
+ return GET_CODE (addr) == LABEL_REF;
+}
+
+
+/* Compute the attribute "length" of push or pop insn, according to
+ the registers it uses. */
+
+int
+csky_compute_pushpop_length (rtx *operands)
+{
+ rtx parallel_op = operands[2];
+ /* Initialize to elements number of PARALLEL. */
+ unsigned indx = XVECLEN (parallel_op, 0) - 1;
+ unsigned first_indx = 0;
+ unsigned regno = REGNO (operands[1]);
+
+ if (regno > CSKY_LR_REGNUM)
+ return 4;
+
+ /* Check each register in the list. */
+ for (; indx > first_indx; indx--)
+ {
+ regno = REGNO (XEXP (XVECEXP (parallel_op, 0, indx), 0));
+ /* If a register number higher than 15 is included, a 32-bit insn
+ is used. */
+ if (regno > CSKY_LR_REGNUM)
+ return 4;
+ }
+
+ return 2;
+}
+
+/* Emit constant pools for -mconstpool. */
+static void
+csky_emit_constant_pools (void)
+{
+ rtx_insn *insn;
+ HOST_WIDE_INT address = 0;
+ Mfix *fix;
+
+ minipool_fix_head = minipool_fix_tail = NULL;
+
+ /* The first insn must always be a note, or the code below won't
+ scan it properly. */
+ insn = get_insns ();
+ gcc_assert (NOTE_P (insn));
+
+ /* Scan the insns and record the operands that need fixing. */
+ for (insn = next_nonnote_insn (insn); insn;
+ insn = next_nonnote_insn (insn))
+ {
+ if (BARRIER_P (insn))
+ push_csky_minipool_barrier (insn, address);
+ else if (INSN_P (insn))
+ {
+ rtx_jump_table_data *table;
+
+ note_csky_invalid_constants (insn, address, true);
+ address += get_attr_length (insn);
+
+ /* If the insn is a vector jump, add the size of the table
+ and skip the table. */
+ if (tablejump_p (insn, NULL, &table))
+ {
+ address += get_csky_jump_table_size (table);
+ insn = table;
+ }
+ }
+ }
+
+ fix = minipool_fix_head;
+
+ /* Now scan the fixups and perform the required changes. */
+ while (fix)
+ {
+ Mfix *ftmp;
+ Mfix *last_added_fix;
+ Mfix *last_barrier = NULL;
+ Mfix *this_fix;
+ Mnode *mp;
+ bool has_pending_const = false;
+
+ /* Check if there is any pending constant not processed. */
+ for (mp = minipool_vector_head; mp; mp = mp->next)
+ if (mp->refcount > 0)
+ {
+ has_pending_const = true;
+ break;
+ }
+
+ /* If no pending constant, skip over barrier insns. */
+ if (has_pending_const == false)
+ {
+ while (fix && BARRIER_P (fix->insn))
+ fix = fix->next;
+ if (fix == NULL)
+ break;
+ }
+
+ last_added_fix = NULL;
+
+ for (ftmp = fix; ftmp; ftmp = ftmp->next)
+ {
+ if (BARRIER_P (ftmp->insn))
+ {
+ if (minipool_vector_head
+ && ftmp->address >= minipool_vector_head->max_address)
+ break;
+
+ last_barrier = ftmp;
+ }
+ else
+ {
+ ftmp->minipool = add_csky_minipool_forward_ref (ftmp);
+ if (ftmp->minipool == NULL)
+ break;
+ }
+ last_added_fix = ftmp; /* Keep track of the last fix added. */
+ }
+
+ /* If the last added fix is a barrier, dump minipool after it. */
+ if (last_added_fix && BARRIER_P (last_added_fix->insn))
+ ftmp = last_barrier;
+ else
+ {
+ /* ftmp is first fix that we can't fit into this pool.
+ Insert a new barrier in the code somewhere between the previous
+ fix and this one, and arrange to jump around it. */
+ HOST_WIDE_INT max_address;
+
+ /* The last item on the list of fixes must be a barrier, so
+ we can never run off the end of the list of fixes without
+ last_barrier being set. */
+ gcc_assert (ftmp);
+
+ /* Check that there isn't another fix that is in range that
+ we couldn't fit into this pool because the pool was
+ already too large: we need to put the pool before such an
+ instruction. The pool itself may come just after the
+ fix because create_csky_fix_barrier also allows space for a
+ jump instruction. */
+ max_address = minipool_vector_head->max_address;
+ if (ftmp->address < max_address)
+ max_address = ftmp->address + 1;
+ last_barrier = create_csky_fix_barrier (last_added_fix, ftmp,
+ max_address);
+ }
+
+ assign_csky_minipool_offsets (last_barrier);
+
+ /* Scan over the fixes we have identified for this pool, fixing them
+ up and adding the constants to the pool itself. */
+ for (this_fix = fix; this_fix && ftmp != this_fix;
+ this_fix = this_fix->next)
+ {
+ if (GET_CODE (this_fix->insn) != BARRIER)
+ {
+ rtx addr
+ = plus_constant (Pmode,
+ gen_rtx_LABEL_REF (VOIDmode,
+ minipool_vector_label),
+ this_fix->minipool->offset);
+ rtx insn_body = PATTERN (this_fix->insn);
+ rtx src = XEXP (insn_body, 1);
+ *this_fix->loc = gen_rtx_MEM (this_fix->mode, addr);
+ if (GET_CODE (this_fix->value) == SYMBOL_REF)
+ emit_insn_after (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
+ gen_rtvec (1, src),
+ VUNSPEC_SYMBOL_REF),
+ this_fix->insn);
+ }
+ }
+ dump_csky_minipool (last_barrier->insn);
+ fix = ftmp;
+ if (fix->next == NULL)
+ break;
+ }
+
+ /* Free the minipool memory. */
+ obstack_free (&minipool_obstack, minipool_startobj);
+}
+
+
+/* Implement TARGET_MACHINE_DEPENDENT_REORG. This handles
+ -mconstpool output. */
+
+static void
+csky_reorg (void)
+{
+ if (TARGET_CONSTANT_POOL)
+ csky_emit_constant_pools ();
+}
+
+
+/* Check to see if the current function contains a branch insn with the
+ far jump attribute set. Such a function uses the LR register. */
+
+static bool
+csky_far_jump_used_p (void)
+{
+ rtx_insn *insn;
+ if (cfun->machine->far_jump_used)
+ return true;
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == JUMP_INSN
+ /* Ignore tablejump patterns. */
+ && GET_CODE (PATTERN (insn)) != ADDR_VEC
+ && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
+ && get_attr_far_jump (insn) == FAR_JUMP_YES)
+ {
+ cfun->machine->far_jump_used = 1;
+ return true;
+ }
+ return false;
+}
+
+
+/* Return the mask of registers used by the current function. Set
+ COUNT to the number of registers used. */
+
+static unsigned int
+get_csky_live_regs (int *count)
+{
+ int reg;
+ unsigned int live_regs_mask = 0;
+
+ *count = 0;
+ for (reg = 0; reg < CSKY_NGPR_REGS; reg++)
+ {
+ bool save = false;
+
+ /* Ignore unsupported registers. */
+ if (CSKY_TARGET_ARCH (CK801) && reg > 8 && reg < 13)
+ continue;
+ if ((CSKY_TARGET_ARCH (CK801)
+ || CSKY_TARGET_ARCH (CK802)
+ || CSKY_TARGET_ARCH (CK803))
+ && reg > 15)
+ break;
+
+ /* Caller-saved registers marked as used. */
+ if (df_regs_ever_live_p (reg) && !call_really_used_regs[reg])
+ save = true;
+
+ /* Frame pointer marked used. */
+ else if (frame_pointer_needed && reg == FRAME_POINTER_REGNUM)
+ save = true;
+
+ /* This is required for CK801/802 where FP is a fixed reg, otherwise
+ we end up with no FP value available to the DWARF-2 unwinder. */
+ else if (crtl->calls_eh_return && reg == FRAME_POINTER_REGNUM)
+ save = true;
+
+ /* CK801/802 also need special handling for LR because it's clobbered
+ by far jumps. */
+ else if ((CSKY_TARGET_ARCH (CK801) || CSKY_TARGET_ARCH (CK802))
+ && reg == CSKY_LR_REGNUM
+ && (!crtl->is_leaf || csky_far_jump_used_p ()))
+ save = true;
+
+ /* Register is used for EH data return. */
+ else if (crtl->calls_eh_return
+ && reg >= CSKY_FIRST_EH_RETDATA_REGNUM
+ && reg <= CSKY_LAST_EH_RETDATA_REGNUM)
+ save = true;
+
+ /* We need a temporary reg to hold the offset for adjusting the SP
+ for a large stack frame. */
+ if (reg == CSKY_STACKADJUST_REGNUM
+ && cfun->machine->reg_offset > CSKY_MAX_SP_ADJUST * 2)
+ save = true;
+
+ /* Add reg to the mask. */
+ if (save)
+ {
+ (*count)++;
+ live_regs_mask |= (1 << reg);
+ }
+ }
+ return live_regs_mask;
+}
+
+/* Compute the stack frame layout, storing sizes of the various pieces
+ in cfun->machine.
+
+ Stack frames constructed in the prologue look like:
+ ... caller's frame ...
+ incoming SP -> caller's outbound argument overflow
+ argument spill
+ optional FP -> register save
+ local variables
+ alloca() space
+ adjusted SP -> outbound argument overflow
+
+ with SP/FP pointing at the base (low address) of the respective area,
+ and each area aligned to a word boundary. */
+
+static void
+csky_layout_stack_frame (void)
+{
+ machine_function *infp = cfun->machine;
+ int reg_count;
+
+ if (infp->frame_init_p)
+ return;
+
+ /* Get sizes of local variables & outbound arguments. */
+ infp->outbound_size = CSKY_STACK_ALIGN (crtl->outgoing_args_size);
+ infp->local_offset = infp->outbound_size;
+ infp->local_size = CSKY_STACK_ALIGN (get_frame_size ());
+ infp->reg_offset = infp->local_offset + infp->local_size;
+
+ /* Now compute size of argument spill + saved regs. These do not
+ need explicit alignment since they are already word-sized. */
+ infp->reg_mask = get_csky_live_regs (&reg_count);
+ infp->reg_size = reg_count * UNITS_PER_WORD;
+ infp->arg_offset = infp->reg_offset + infp->reg_size;
+ infp->arg_size = crtl->args.pretend_args_size;
+ infp->frame_size = infp->arg_offset + infp->arg_size;
+ infp->frame_init_p = reload_completed;
+}
+
+/* Implement TARGET_CAN_ELIMINATE. */
+static bool
+csky_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+ if (to == STACK_POINTER_REGNUM)
+ return !frame_pointer_needed;
+ return true;
+}
+
+/* Worker function for INITIAL_ELIMINATION_OFFSET macro.
+ Define the offset between two registers, one to be eliminated, and
+ the other its replacement, at the start of a routine. */
+
+HOST_WIDE_INT
+csky_initial_elimination_offset (int from, int to)
+{
+ int offset;
+
+ csky_layout_stack_frame ();
+
+ /* Set OFFSET to the offset to the initial stack pointer. */
+ switch (from)
+ {
+ case FRAME_POINTER_REGNUM:
+ offset = cfun->machine->reg_offset;
+ break;
+
+ case ARG_POINTER_REGNUM:
+ offset = cfun->machine->arg_offset;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* If we are asked for the offset to the frame pointer instead,
+ then subtract the difference between the frame pointer and stack
+ pointer. */
+ if (to == FRAME_POINTER_REGNUM)
+ offset -= cfun->machine->reg_offset;
+ return offset;
+}
+
+
+/* Determine where to put an argument to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis). */
+static rtx
+csky_function_arg (cumulative_args_t pcum_v, machine_mode mode,
+ const_tree type ATTRIBUTE_UNUSED,
+ bool named ATTRIBUTE_UNUSED)
+{
+ CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v);
+
+ if (*pcum < CSKY_NPARM_REGS)
+ return gen_rtx_REG (mode, CSKY_FIRST_PARM_REGNUM + *pcum);
+
+ return NULL_RTX;
+}
+
+
+/* Return the number of registers (words) needed to pass an argument of
+ MODE and TYPE. */
+
+static int
+csky_num_arg_regs (machine_mode mode, const_tree type)
+{
+ int size;
+
+ if (type && mode == BLKmode)
+ size = int_size_in_bytes (type);
+ else
+ size = GET_MODE_SIZE (mode);
+
+ return CSKY_NUM_WORDS (size);
+}
+
+
+/* Implement TARGET_FUNCTION_ARG_ADVANCE. */
+
+static void
+csky_function_arg_advance (cumulative_args_t pcum_v, machine_mode mode,
+ const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+ CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v);
+ int param_size = csky_num_arg_regs (mode, type);
+
+ if (*pcum + param_size > CSKY_NPARM_REGS)
+ *pcum = CSKY_NPARM_REGS;
+ else
+ *pcum += param_size;
+}
+
+
+/* Implement TARGET_FUNCTION_VALUE. */
+static rtx
+csky_function_value (const_tree type, const_tree func,
+ bool outgoing ATTRIBUTE_UNUSED)
+{
+ machine_mode mode;
+ int unsignedp ATTRIBUTE_UNUSED;
+ int size;
+
+ mode = TYPE_MODE (type);
+ size = int_size_in_bytes (type);
+
+ /* Since we promote return types, we must promote the mode here too. */
+ if (INTEGRAL_TYPE_P (type))
+ {
+ mode = promote_function_mode (type, mode, &unsignedp, func, 1);
+ return gen_rtx_REG (mode, CSKY_FIRST_RET_REGNUM);
+ }
+
+ if (mode == BLKmode && size > UNITS_PER_WORD
+ && size <= UNITS_PER_WORD * 2)
+ {
+ rtx ret_regs[2];
+ ret_regs[0] = gen_rtx_EXPR_LIST (SImode,
+ gen_rtx_REG (SImode,
+ CSKY_FIRST_RET_REGNUM),
+ GEN_INT (0 * UNITS_PER_WORD));
+ ret_regs[1] = gen_rtx_EXPR_LIST (SImode,
+ gen_rtx_REG (SImode,
+ CSKY_FIRST_RET_REGNUM + 1),
+ GEN_INT (1 * UNITS_PER_WORD));
+
+ rtvec vec = gen_rtvec (2, ret_regs[0], ret_regs[1]);
+
+ return gen_rtx_PARALLEL (mode, vec);
+ }
+
+ return gen_rtx_REG (mode, CSKY_FIRST_RET_REGNUM);
+}
+
+
+/* Implement TARGET_LIBCALL_VALUE. */
+static rtx
+csky_libcall_value (machine_mode mode,
+ const_rtx libcall ATTRIBUTE_UNUSED)
+{
+ return gen_rtx_REG (mode, CSKY_FIRST_RET_REGNUM);
+}
+
+
+/* Implement TARGET_FUNCTION_VALUE_REGNO_P.
+ On C-SKY, only r0 can return results. */
+
+static bool
+csky_function_value_regno_p (const unsigned int regno)
+{
+ return (regno == CSKY_FIRST_RET_REGNUM);
+}
+
+
+/* Return an RTX indicating where the return address to the
+ calling function can be found. */
+rtx
+csky_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
+{
+ if (count != 0)
+ return NULL_RTX;
+
+ return get_hard_reg_initial_val (Pmode, CSKY_LR_REGNUM);
+}
+
+
+/* Implement TARGET_ARG_PARTIAL_BYTES.
+ Return the number of bytes at the beginning of an argument
+ that must be put in registers. The value must be zero for arguments
+ that are passed entirely in registers or
+ that are entirely pushed on the stack. */
+static int
+csky_arg_partial_bytes (cumulative_args_t pcum_v, machine_mode mode,
+ tree type, bool named ATTRIBUTE_UNUSED)
+{
+ CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v);
+ int param_size = csky_num_arg_regs (mode, type);
+
+ if (*pcum < CSKY_NPARM_REGS
+ && *pcum + param_size > CSKY_NPARM_REGS)
+ return (CSKY_NPARM_REGS - *pcum) * UNITS_PER_WORD;
+
+ return 0;
+}
+
+
+/* Implement TARGET_SETUP_INCOMING_VARARGS.
+ On C-Sky the copy from the argument registers to the stack is emitted
+ by the prologue hooks, so here we just have to note how much stack space
+ to save. */
+
+static void
+csky_setup_incoming_varargs (cumulative_args_t pcum_v,
+ machine_mode mode,
+ tree type,
+ int *pretend_size,
+ int second_time ATTRIBUTE_UNUSED)
+{
+ CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v);
+ CUMULATIVE_ARGS local_cum;
+ cumulative_args_t local_cum_v = pack_cumulative_args (&local_cum);
+ int regs_to_push;
+
+ cfun->machine->uses_anonymous_args = 1;
+ local_cum = *pcum;
+ csky_function_arg_advance (local_cum_v, mode, type, true);
+ regs_to_push = CSKY_NPARM_REGS - local_cum;
+ if (regs_to_push)
+ *pretend_size = regs_to_push * UNITS_PER_WORD;
+}
+
+
+/* Implement TARGET_ASM_OUTPUT_MI_THUNK.
+ Output code to add DELTA to the first argument, and then jump
+ to FUNCTION. Used for C++ multiple inheritance. */
+
+static void
+csky_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
+ HOST_WIDE_INT delta,
+ HOST_WIDE_INT vcall_offset,
+ tree function)
+{
+ const char *thiz = "a0";
+ const char *reg0 = "t0";
+ const char *reg1 = "t1";
+ int maxoff = 4096; /* Constant range for addi/subi. */
+
+ final_start_function (emit_barrier (), file, 1);
+
+ rtx fnaddr = XEXP (DECL_RTL (function), 0);
+
+ if (CSKY_TARGET_ARCH (CK801))
+ {
+ /* CK801 can't use t registers and has only 16-bit addi/subi. */
+ reg0 = "l0";
+ reg1 = "l1";
+ maxoff = 256;
+ if (vcall_offset > maxoff || vcall_offset < -maxoff)
+ fprintf (file, "\tpush\tl0, l1\n");
+ else if (delta > maxoff || delta < -maxoff)
+ fprintf (file, "\tpush\tl0\n");
+ }
+
+ if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
+ thiz = "a1";
+
+ /* Add delta to this_rtx. */
+ if (delta != 0)
+ {
+ if (delta > maxoff || delta < -maxoff)
+ {
+ fprintf (file, "\tlrw\t%s, %ld\n", reg0, (long)delta);
+ fprintf (file, "\taddu\t%s, %s, %s\n", thiz, thiz, reg0);
+ }
+ else
+ fprintf (file, "\t%s\t%s, %s, %ld\n",
+ (delta > 0 ? "addi" : "subi"), thiz, thiz,
+ (long)(delta > 0 ? delta : -delta));
+ }
+
+ /* If needed, add *(*this_rtx + vcall_offset) to this_rtx. */
+ if (vcall_offset != 0)
+ {
+ fprintf (file, "\tld.w\t%s, (%s, 0)\n", reg0, thiz);
+
+ if (vcall_offset > maxoff || vcall_offset < -maxoff)
+ {
+ fprintf (file, "\tlrw\t%s, %ld\n", reg1, (long)vcall_offset);
+ fprintf (file, "\taddu\t%s, %s, %s\n", reg0, reg0, reg1);
+ }
+ else
+ fprintf (file, "\t%s\t%s, %s, %ld\n",
+ (vcall_offset > 0 ? "addi" : "subi"), reg0, reg0,
+ (long)(vcall_offset > 0 ? vcall_offset : -vcall_offset));
+
+ /* Load the offset and add it to this_rtx */
+ fprintf (file, "\tld.w\t%s, (%s, 0)\n", reg0, reg0);
+ fprintf (file, "\taddu\t%s, %s, %s\n", thiz, thiz, reg0);
+ }
+
+ /* We must pop the scratch regs individually instead of using the
+ "pop" insn, which also does a return. */
+ if (CSKY_TARGET_ARCH (CK801))
+ {
+ if (vcall_offset > maxoff || vcall_offset < -maxoff)
+ {
+ fprintf (file, "\tld.w\tl0, (sp, 0)\n");
+ fprintf (file, "\tld.w\tl1, (sp, 4)\n");
+ fprintf (file, "\taddi\t sp, sp, 8\n");
+ }
+ else if (delta > maxoff || delta < -maxoff)
+ {
+ fprintf (file, "\tld.w\tl0, (sp, 0)\n");
+ fprintf (file, "\taddi\tsp, sp, 4\n");
+ }
+ }
+
+ fprintf (file, "\tjbr\t");
+ output_addr_const (file, fnaddr);
+ fprintf (file, "\n");
+
+ final_end_function ();
+}
+
+
+/* Implement TARGET_CONDITIONAL_REGISTER_USAGE.
+ Conditionally modify five variables fixed_regs, call_used_regs, global_regs,
+ reg_names, and reg_class_contents, to take into account any dependence of
+ these register sets on target flags.
+
+ CK801 has registers r0-r8 and r13-r15. CK802 and CK803 have registers
+ r0-r15 (the "low" registers). Other cpus use registers r0-r31 with
+ -mhigh-registers, otherwise also only r0-r15.
+
+ CK801 only has 16-bit instructions, most of which can only reference
+ r0-r7 (the "mini" registers). So we mark regs outside that range as
+ fixed. -msmart can be used on other arch variants to force the same
+ behavior because it results in smaller code size.
+
+ TODO: investigate whether it's beneficial to use r8-r13 as a spill
+ class when TARGET_MINI_REGISTERS instead of making them unusable by
+ the register allocator. */
+
+static void
+csky_conditional_register_usage (void)
+{
+ /* Only use mini registers in smart mode or 801. */
+ if (TARGET_MINI_REGISTERS)
+ {
+ int i;
+
+ for (i = (CSKY_LAST_MINI_REGNUM + 1); i < 32; i++)
+ {
+ fixed_regs[i] = 1;
+ call_used_regs[i] = 1;
+ call_really_used_regs[i] = 1;
+ }
+ }
+ /* For some targets, the high registers are not supported.
+ CPUs other than ck801/ck802/ck803 use high registers
+ depending on -mhigh-registers option. */
+ else if (CSKY_TARGET_ARCH (CK802)
+ || CSKY_TARGET_ARCH (CK803)
+ || !TARGET_HIGH_REGISTERS)
+ {
+ int i;
+
+ for (i = CSKY_FIRST_HIGH_REGNUM; i <= CSKY_LAST_HIGH_REGNUM; i++)
+ {
+ fixed_regs[i] = 1;
+ call_used_regs[i] = 1;
+ call_really_used_regs[i] = 1;
+ }
+ }
+
+ /* On CK801/CK802 we must mark lr as a fixed register because it is
+ used to implement far jumps.
+ FIXME: perhaps there should be a command-line option controlling
+ use of lr for far jumps on ck802 when !TARGET_MINI_REGS, when
+ you really want lr to be available to the register allocator and
+ you know there are no far jumps in the code. */
+ if (CSKY_TARGET_ARCH (CK801) || CSKY_TARGET_ARCH (CK802))
+ {
+ fixed_regs[CSKY_LR_REGNUM] = 1;
+ call_used_regs[CSKY_LR_REGNUM] = 1;
+ call_really_used_regs[CSKY_LR_REGNUM] = 0;
+ }
+
+ /* The hi/lo registers are only supported in dsp mode. */
+ if (!TARGET_DSP)
+ {
+ fixed_regs[CSKY_HI_REGNUM] = 1;
+ call_used_regs[CSKY_HI_REGNUM] = 1;
+ call_really_used_regs[CSKY_HI_REGNUM] = 1;
+
+ fixed_regs[CSKY_LO_REGNUM] = 1;
+ call_used_regs[CSKY_LO_REGNUM] = 1;
+ call_really_used_regs[CSKY_LO_REGNUM] = 1;
+ }
+
+ /* The V_REGS are only supported in hard float mode. */
+ if (!TARGET_HARD_FLOAT)
+ {
+ int regno;
+
+ for (regno = CSKY_FIRST_VFP_REGNUM;
+ regno <= CSKY_LAST_VFP_REGNUM; regno++)
+ {
+ fixed_regs[regno] = 1;
+ call_used_regs[regno] = 1;
+ call_really_used_regs[regno] = 1;
+ }
+ }
+
+ /* In pic mode, the gb register is not available for register
+ allocation. Since gb is not clobbered by function
+ calls, set its call_really_used_regs to 0. */
+ if (flag_pic)
+ {
+ fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
+ call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
+ call_really_used_regs[PIC_OFFSET_TABLE_REGNUM] = 0;
+ }
+}
+
+/* Implement TARGET_HARD_REGNO_NREGS. */
+static unsigned int
+csky_hard_regno_nregs (unsigned int regno, machine_mode mode)
+{
+ if (regno >= CSKY_FIRST_VFP_REGNUM && !CSKY_TARGET_ARCH (CK803))
+ return 1;
+ else
+ return CSKY_NUM_REGS (mode);
+}
+
+/* Implement TARGET_HARD_REGNO_MODE_OK. Return true if REGNO is a
+ valid register for holding a quantity of type MODE. */
+
+static bool
+csky_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
+{
+ int nregs = CSKY_NUM_REGS (mode);
+
+ /* We can't handle more than doubleword sizes for any register. */
+ if (nregs > 2)
+ return false;
+
+ /* For general registers, return true if mode is one word size.
+ When the size is larger than one word size, there should
+ be two successive hard registers to put the data. */
+ if (regno < CSKY_NGPR_REGS)
+ {
+ if (nregs < 2)
+ return true;
+ else if (TARGET_MINI_REGISTERS)
+ return (regno < CSKY_LAST_MINI_REGNUM);
+ else if (CSKY_TARGET_ARCH (CK802)
+ || CSKY_TARGET_ARCH (CK803)
+ || !TARGET_HIGH_REGISTERS)
+ /* Without high register, r15 cannot hold doubleword data. */
+ return (regno < (CSKY_SP_REGNUM - 1));
+ else
+ return (regno < (CSKY_SP_REGNUM - 1)
+ || (regno >= CSKY_LR_REGNUM
+ && regno < CSKY_LAST_HIGH_UNFIXED_REGNUM));
+ }
+ else if (regno == CSKY_CC_REGNUM)
+ return (mode == CCmode);
+ else if (regno == CSKY_HI_REGNUM || regno == CSKY_LO_REGNUM)
+ {
+ /* Don't allocate hi,lo register for float data even
+ if in dsp mode, because it will cause high cost
+ to reload data from hi,lo register. */
+ if (!TARGET_DSP || mode == SFmode || mode == DFmode)
+ return false;
+ else if (nregs == 2)
+ return (regno == CSKY_HI_REGNUM);
+ else
+ return true;
+ }
+ else if (CSKY_VREG_P (regno) && TARGET_HARD_FLOAT)
+ return true;
+
+ return false;
+}
+
+/* Implement TARGET_MODES_TIEABLE_P. We can't tie DFmode with other modes
+ when V_REGs might be in use because those registers mess with the stored
+ bits. */
+static bool
+csky_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+ return !(TARGET_HARD_FLOAT
+ && mode1 != mode2
+ && (mode1 == DFmode || mode2 == DFmode));
+}
+
+/* Implement TARGET_CAN_CHANGE_MODE_CLASS.
+ V_REG registers can't do subreg as all values are reformatted to
+ internal precision. */
+static bool
+csky_can_change_mode_class (machine_mode from,
+ machine_mode to,
+ reg_class_t rclass)
+{
+ return (GET_MODE_SIZE (from) == GET_MODE_SIZE (to)
+ || !reg_classes_intersect_p (V_REGS, rclass));
+}
+
+/* Implement TARGET_CLASS_LIKELY_SPILLED_P.
+ We need to define this for MINI_REGS when we only use r0 - r7.
+ Otherwise we can end up using r0-r4 for function arguments, and don't
+ have enough left over to do doubleword arithmetic. */
+
+static bool
+csky_class_likely_spilled_p (reg_class_t rclass)
+{
+ if ((TARGET_MINI_REGISTERS && rclass == MINI_REGS)
+ || rclass == C_REGS)
+ return true;
+
+ return false;
+}
+
+
+/* Implement TARGET_PREFERRED_RELOAD_CLASS.
+ Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
+ In general this is just CLASS. */
+
+static reg_class_t
+csky_preferred_reload_class (rtx x, reg_class_t rclass)
+{
+ if (TARGET_HARD_FLOAT
+ && CONST_DOUBLE_P (x)
+ && (GET_MODE (x) == DFmode || GET_MODE (x) == SFmode)
+ && rclass == NO_REGS)
+ return GENERAL_REGS;
+ return rclass;
+}
+
+
+/* Implement TARGET_CLASS_MAX_NREGS.
+ Return the maximum number of consecutive registers of class rclass needed
+ to hold a value of mode mode.
+ On the csky, this is the size of MODE in words,
+ except in the FP regs, where a single reg is always enough. */
+
+static unsigned char
+csky_class_max_nregs (reg_class_t rclass, machine_mode mode)
+{
+ if (rclass == V_REGS)
+ return 1;
+ else
+ return CSKY_NUM_REGS (mode);
+}
+
+
+/* Implement TARGET_SECONDARY_RELOAD.
+ If copying a register of RCLASS from/to X requires an intermediate
+ register, the hook should return the REGISTER_CLASS required for this
+ intermediate register.
+ If no intermediate register is required, it should return NO_REGS.
+ If more than one intermediate register is required, describe the one
+ that is closest in the copy chain to the reload register. */
+
+reg_class_t
+csky_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
+ reg_class_t rclass,
+ machine_mode mode,
+ secondary_reload_info *sri ATTRIBUTE_UNUSED)
+{
+ int regno = -1;
+
+ /* Extract the real regno from X. */
+ if (GET_CODE (x) == SIGN_EXTEND)
+ {
+ int off = 0;
+
+ x = XEXP (x, 0);
+
+ if (reg_renumber)
+ regno = true_regnum (x);
+ else
+ {
+ while (GET_CODE (x) == SUBREG)
+ {
+ off += subreg_regno_offset (REGNO (SUBREG_REG (x)),
+ GET_MODE (SUBREG_REG (x)),
+ SUBREG_BYTE (x), GET_MODE (x));
+ x = SUBREG_REG (x);
+ }
+
+ if (GET_CODE (x) == REG)
+ regno = REGNO (x) + off;
+ }
+ }
+ else if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
+ regno = true_regnum (x);
+
+ /* We always require a general register when copying anything to
+ HI/LO_REGNUM, except when copying an SImode value from HI/LO_REGNUM
+ to a general register, or when copying from register 0. */
+ if ((rclass == HILO_REGS || rclass == LO_REGS || rclass == HI_REGS)
+ && !CSKY_GENERAL_REGNO_P (regno))
+ return GENERAL_REGS;
+
+ if (rclass == V_REGS && !CSKY_GENERAL_REGNO_P (regno))
+ {
+ /* Reload between vector reg and memory does not need an
+ intermediate register. */
+ if (MEM_P (x) && (mode == SFmode || mode == DFmode))
+ return NO_REGS;
+ else
+ return GENERAL_REGS;
+ }
+
+ return NO_REGS;
+}
+
+/* Implement TARGET_SPILL_CLASS.
+ Try spilling to a larger register class before spilling to memory. */
+
+static reg_class_t
+csky_spill_class (reg_class_t rclass, machine_mode mode ATTRIBUTE_UNUSED)
+{
+ if ((rclass == MINI_REGS && !TARGET_MINI_REGISTERS)
+ || (rclass == LOW_REGS && TARGET_HIGH_REGISTERS))
+ return GENERAL_REGS;
+ return NO_REGS;
+}
+
+/* Convert a static initializer array of feature bits to sbitmap
+ representation. */
+static void
+csky_initialize_isa (sbitmap isa, const enum csky_isa_feature *isa_bits)
+{
+ bitmap_clear (isa);
+ while (*isa_bits != CSKY_ISA_FEATURE_GET (none))
+ bitmap_set_bit (isa, *(isa_bits++));
+}
+
+
+/* Configure a build target TARGET from the user-specified options OPTS and
+ OPTS_SET. */
+static void
+csky_configure_build_target (struct csky_build_target *target,
+ struct cl_target_option *opts,
+ struct gcc_options *opts_set)
+{
+ const struct csky_processors *csky_selected_tune = NULL;
+ struct csky_processors *csky_selected_cpu = NULL;
+ struct csky_processors *csky_selected_arch = NULL;
+ sbitmap all_sbits = sbitmap_alloc (CSKY_ISA_FEATURE_GET (max));
+ bitmap_clear (all_sbits);
+
+ bitmap_clear (target->isa);
+ target->core_name = NULL;
+ target->arch_name = NULL;
+
+ if (opts_set->x_csky_arch_option)
+ csky_selected_arch = &all_architectures[opts->x_csky_arch_option];
+
+ if (opts_set->x_csky_cpu_option)
+ {
+ csky_selected_cpu = &all_cores[opts->x_csky_cpu_option];
+ csky_selected_tune = &all_cores[opts->x_csky_cpu_option];
+ }
+
+ if (csky_selected_cpu)
+ {
+ /* TODO: support combination of features
+ between different cpu & arch, should based on arch. */
+ if (csky_selected_arch
+ && (csky_selected_cpu->base_arch != csky_selected_arch->base_arch))
+ warning (0, "cpu %s is not based on arch %s, ignoring the arch",
+ csky_selected_cpu->name, csky_selected_arch->name);
+ if (!csky_selected_arch)
+ csky_selected_arch = &all_architectures[csky_selected_cpu->base_arch];
+ csky_initialize_isa (all_sbits, csky_selected_arch->isa_bits);
+ target->core_name = csky_selected_cpu->name;
+ }
+ else if (csky_selected_arch)
+ {
+ csky_selected_cpu = csky_selected_arch;
+ target->arch_name = csky_selected_arch->name;
+ }
+ else /* If the user did not specify a processor, choose one for them. */
+ {
+ csky_selected_cpu = &all_cores[TARGET_CPU_DEFAULT];
+ csky_selected_arch = &all_architectures[csky_selected_cpu->base_arch];
+ csky_initialize_isa (all_sbits, csky_selected_arch->isa_bits);
+ target->core_name = csky_selected_cpu->name;
+ }
+
+ /* The selected cpu may be an architecture, so lookup tuning by core ID. */
+ if (!csky_selected_tune)
+ csky_selected_tune = &all_cores[csky_selected_cpu->core];
+ gcc_assert (csky_selected_tune);
+
+ gcc_assert (csky_selected_arch);
+ gcc_assert (csky_selected_cpu);
+ csky_initialize_isa (target->isa, csky_selected_cpu->isa_bits);
+ bitmap_ior (target->isa, target->isa, all_sbits);
+
+ /* Finish initializing the target structure. */
+ target->arch_pp_name = csky_selected_cpu->arch;
+ target->base_arch = csky_selected_cpu->base_arch;
+ target->arch_core = csky_selected_cpu->core;
+
+ sbitmap_free (all_sbits);
+}
+
+
+/* Implement TARGET_OPTION_OVERRIDE. */
+
+static void
+csky_option_override (void)
+{
+ csky_active_target.isa = sbitmap_alloc (CSKY_ISA_FEATURE_GET (max));
+
+ /* Create the default target_options structure. We need this early
+ to configure the overall build target. */
+ target_option_default_node = target_option_current_node
+ = build_target_option_node (&global_options);
+
+ csky_configure_build_target (&csky_active_target,
+ TREE_TARGET_OPTION (target_option_default_node),
+ &global_options_set);
+
+#ifdef SUBTARGET_OVERRIDE_OPTIONS
+ SUBTARGET_OVERRIDE_OPTIONS;
+#endif
+
+ csky_base_arch = csky_active_target.base_arch;
+
+ if (flag_pic && !(CSKY_TARGET_ARCH (CK810) || CSKY_TARGET_ARCH (CK807)))
+ {
+ flag_pic = 0;
+ warning (0, "%qs is not supported by arch %s",
+ "-fPIC", csky_active_target.arch_pp_name);
+ }
+
+ /* Check floating-point options for consistency. */
+ if (TARGET_HARD_FLOAT)
+ {
+ const struct csky_fpu_desc *csky_selected_fpu = NULL;
+
+ if (csky_fpu_index == TARGET_FPU_auto)
+ {
+ const char *target_fpu_name;
+ bool ok;
+ int fpu_index;
+
+#ifdef CSKY_FPUTYPE_DEFAULT
+ target_fpu_name = CSKY_FPUTYPE_DEFAULT;
+#else
+ target_fpu_name = "fpv2";
+#endif
+
+ if (csky_active_target.core_name != NULL
+ && !strchr (csky_active_target.core_name, 'f'))
+ target_fpu_name = "auto";
+ else if (CSKY_TARGET_ARCH (CK803) || !TARGET_DOUBLE_FLOAT)
+ target_fpu_name = "fpv2_sf";
+ else if (TARGET_DOUBLE_FLOAT && TARGET_FDIVDU)
+ target_fpu_name = "fpv2_divd";
+
+ ok = opt_enum_arg_to_value (OPT_mfpu_, target_fpu_name, &fpu_index,
+ CL_TARGET);
+ gcc_assert (ok);
+ csky_fpu_index = (enum csky_fpu_type) fpu_index;
+ }
+
+ if (CSKY_TARGET_ARCH (CK801) || CSKY_TARGET_ARCH (CK802))
+ error ("%qs is not supported by arch %s",
+ "-mhard-float", csky_active_target.arch_pp_name);
+ else if (csky_fpu_index == TARGET_FPU_auto)
+ error ("%<-mhard-float%> is not supported by the selected CPU");
+ else
+ {
+ csky_selected_fpu = &all_fpus[csky_fpu_index];
+ sbitmap fpu_bits = sbitmap_alloc (CSKY_ISA_FEATURE_GET (max));
+ csky_initialize_isa (fpu_bits, csky_selected_fpu->isa_bits);
+
+ bitmap_ior (csky_active_target.isa, csky_active_target.isa,
+ fpu_bits);
+
+ sbitmap_free (fpu_bits);
+ }
+ }
+ else
+ {
+ if (TARGET_DOUBLE_FLOAT > 0)
+ warning (0, "%<-mdouble-float%> ignored without %<-mhard-float%>");
+ TARGET_DOUBLE_FLOAT = 0;
+ if (TARGET_FDIVDU > 0)
+ warning (0, "%<-mfdivdu%> ignored without %<-mhard-float%>");
+ TARGET_FDIVDU = 0;
+ }
+
+ /* Extended LRW instructions are enabled by default on CK801, disabled
+ otherwise. */
+ if (TARGET_ELRW == -1)
+ TARGET_ELRW = CSKY_TARGET_ARCH (CK801);
+
+ /* DSP is enabled either by the processor feature or -mdsp
+ command-line option. There is no -mno-dsp option as the assembler
+ doesn't take one. */
+ if (!TARGET_DSP)
+ TARGET_DSP = CSKY_ISA_FEATURE (dsp);
+
+ /* There's both -mdiv and -mno-div. Take default from processor if
+ neither is specified explicitly. */
+ if (TARGET_DIV == -1)
+ TARGET_DIV = CSKY_ISA_FEATURE (div);
+
+ /* TARGET_CONSTANT_POOL is mandatory for CK801 and CK802 and optional
+ for other CPUs.
+ The reason why the compiler has to generate constant pools for CK801/2
+ instead of deferring to the assembler is that these cores don't have a
+ long branch instruction other than jbsr, which clobbers lr. So for
+ the compiler to correctly save/restore lr it has to know whether there
+ are long branches, which depends on having accurate branch length
+ counts, which in turn depends on having control over where constant
+ pools are placed. */
+ if ((CSKY_TARGET_ARCH (CK801) || CSKY_TARGET_ARCH (CK802))
+ && !TARGET_CONSTANT_POOL)
+ error ("%qs is not supported by arch %s",
+ "-mno-constpool", csky_active_target.arch_pp_name);
+ else if (TARGET_CONSTANT_POOL == -1)
+ TARGET_CONSTANT_POOL = (CSKY_TARGET_ARCH (CK801)
+ || CSKY_TARGET_ARCH (CK802));
+
+ /* TARGET_MINI_REGISTERS is mandatory for CK801, the default for CK802,
+ and optional for other CPUs. TARGET_HIGH_REGISTERS is incompatible
+ with TARGET_MINI_REGISTERS, is not supported by CK801/802/803,
+ and is the default for other processors.
+ See csky_conditional_register_usage. */
+ if (TARGET_MINI_REGISTERS > 0 && TARGET_HIGH_REGISTERS > 0)
+ error ("%<-msmart%> is incompatible with %<-mhigh-registers%>");
+ else if (CSKY_TARGET_ARCH (CK801)
+ || CSKY_TARGET_ARCH (CK802)
+ || CSKY_TARGET_ARCH (CK803))
+ {
+ if (CSKY_TARGET_ARCH (CK801)
+ || (CSKY_TARGET_ARCH (CK802) && TARGET_MINI_REGISTERS == -1))
+ TARGET_MINI_REGISTERS = 1;
+ else if (TARGET_MINI_REGISTERS == -1)
+ TARGET_MINI_REGISTERS = 0;
+ if (TARGET_HIGH_REGISTERS > 0)
+ warning (0, "%qs is not supported by arch %s",
+ "-mhigh-registers", csky_active_target.arch_pp_name);
+ TARGET_HIGH_REGISTERS = 0;
+ }
+ else
+ {
+ if (TARGET_MINI_REGISTERS == -1)
+ TARGET_MINI_REGISTERS = 0;
+ if (TARGET_HIGH_REGISTERS == -1)
+ TARGET_HIGH_REGISTERS = !TARGET_MINI_REGISTERS;
+ }
+
+ /* -mmultiple-stld is the default for everything but CK801, which
+ doesn't support it. */
+ if (CSKY_TARGET_ARCH (CK801))
+ {
+ if (TARGET_MULTIPLE_STLD > 0)
+ warning (0, "%qs is not supported by arch %s",
+ "-mmultiple-stld", csky_active_target.arch_pp_name);
+ TARGET_MULTIPLE_STLD = 0;
+ }
+
+ /* Initialize boolean versions of the architectural flags, for use
+ in the .md file. */
+
+#undef CSKY_ISA
+#define CSKY_ISA(IDENT, DESC) \
+ { \
+ csky_arch_isa_features[CSKY_ISA_FEATURE_GET (IDENT)] = \
+ bitmap_bit_p (csky_active_target.isa, CSKY_ISA_FEATURE_GET (IDENT)); \
+ }
+#include "csky_isa.def"
+#undef CSKY_ISA
+
+ /* TODO */
+
+ /* Resynchronize the saved target options. */
+ cl_target_option_save (TREE_TARGET_OPTION (target_option_default_node),
+ &global_options);
+
+#ifdef ENABLE_TPF_DEBUG
+ /* Don't emit DWARF4 unless specifically selected. The TPF
+ debuggers do not yet support DWARF 3/4. */
+ if (!global_options_set.x_dwarf_strict)
+ dwarf_strict = 1;
+ if (!global_options_set.x_dwarf_version)
+ dwarf_version = 3;
+#endif
+
+ /* Don't run the scheduler before reload by default,
+ since it tends to increase register pressure. */
+ if (!global_options_set.x_flag_schedule_insns)
+ flag_schedule_insns = 0;
+
+ csky_add_gc_roots ();
+}
+
+
+/* Return TRUE if X contains any references to TLS symbols. */
+
+bool
+csky_tls_referenced_p (rtx x)
+{
+ if (!TARGET_TLS)
+ return false;
+
+ subrtx_iterator::array_type array;
+ FOR_EACH_SUBRTX (iter, array, x, ALL)
+ {
+ const_rtx x = *iter;
+ if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0)
+ return true;
+
+ /* Don't recurse into UNSPEC_TLS looking for TLS symbols; these are
+ TLS offsets, not real symbol references. */
+ if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS)
+ iter.skip_subrtxes ();
+ }
+ return false;
+}
+
+
+/* Implement TARGET_CANNOT_FORCE_CONST_MEM.
+ Determine if it's legal to put X into the constant pool. This
+ is not possible for the address of thread-local symbols, which
+ is checked above. */
+
+static bool
+csky_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED,
+ rtx x)
+{
+ return csky_tls_referenced_p (x);
+}
+
+
+/* Implement TARGET_LEGITIMATE_CONSTANT_P. Returns nonzero if the
+ constant value X is a legitimate general operand.
+ It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
+
+static bool
+csky_legitimate_constant_p (machine_mode mode, rtx x)
+{
+ return (!csky_cannot_force_const_mem (mode, x)
+ && CONSTANT_P (x));
+}
+
+
+/* Return true if X is valid as an CSKY addressing register. */
+
+static bool
+is_csky_address_register_rtx_p (rtx x, int strict_p)
+{
+ int regno;
+
+ if (!x)
+ return false;
+ if (!REG_P (x))
+ return false;
+
+ regno = REGNO (x);
+
+ if (strict_p)
+ return (CSKY_GENERAL_REGNO_P (regno)
+ || CSKY_GENERAL_REGNO_P (reg_renumber[regno]));
+ else
+ return CSKY_GENERAL_REGNO_P (regno) || regno >= FIRST_PSEUDO_REGISTER;
+}
+
+
+/* Return TRUE if X is a thread-local symbol. */
+
+static bool
+csky_tls_symbol_p (rtx x)
+{
+ if (!TARGET_TLS)
+ return false;
+
+ if (GET_CODE (x) != SYMBOL_REF)
+ return false;
+
+ return SYMBOL_REF_TLS_MODEL (x) != 0;
+}
+
+
+/* Handle lazy initialization of __tls_get_addr libfunc. */
+static GTY(()) rtx tls_get_addr_libfunc;
+
+static rtx
+get_tls_get_addr (void)
+{
+ if (!tls_get_addr_libfunc)
+ tls_get_addr_libfunc = init_one_libfunc ("__tls_get_addr");
+ return tls_get_addr_libfunc;
+}
+
+
+/* Emit a call to __tls_get_addr. */
+
+static rtx_insn *
+csky_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc)
+{
+ rtx label, labelno, unspec, tmp;
+ rtx_insn *insns;
+
+ start_sequence ();
+
+ labelno = GEN_INT (tls_labelno++);
+ label = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_TLS_LABEL);
+ unspec = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (3, x, GEN_INT (reloc), label),
+ UNSPEC_TLS);
+ tmp = gen_reg_rtx (SImode);
+ emit_move_insn (reg, unspec);
+ emit_move_insn (tmp, label);
+ emit_insn (gen_addsi3 (reg, reg, tmp));
+ *valuep = emit_library_call_value (get_tls_get_addr (),
+ NULL_RTX, LCT_PURE, /* LCT_CONST? */
+ Pmode, reg, Pmode);
+ insns = get_insns ();
+ end_sequence ();
+ return insns;
+}
+
+/* Helper function for csky_legitimize_address, to handle the TLS cases.
+ REG is a scratch register and may be null. */
+
+rtx
+csky_legitimize_tls_address (rtx x, rtx reg)
+{
+ rtx dest, tp, label, labelno, unspec, ret, eqv, addend, tmp;
+ rtx_insn *insns;
+ unsigned int model = SYMBOL_REF_TLS_MODEL (x);
+
+ if (!reg)
+ reg = gen_reg_rtx (SImode);
+
+ switch (model)
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ insns = csky_call_tls_get_addr (x, reg, &ret, TLS_GD32);
+ dest = gen_reg_rtx (Pmode);
+ emit_libcall_block (insns, dest, ret, x);
+ return dest;
+
+ case TLS_MODEL_LOCAL_DYNAMIC:
+ insns = csky_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)),
+ UNSPEC_TLS);
+ addend = force_reg (SImode, addend);
+ return gen_rtx_PLUS (Pmode, dest, addend);
+
+ case TLS_MODEL_INITIAL_EXEC:
+ labelno = GEN_INT (tls_labelno++);
+ label = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_TLS_LABEL);
+ unspec = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (3, x, GEN_INT (TLS_IE32), label),
+ UNSPEC_TLS);
+ tmp = gen_reg_rtx (SImode);
+ emit_move_insn (reg, unspec);
+ emit_move_insn (tmp, label);
+ emit_insn (gen_addsi3 (reg, reg, tmp));
+ emit_move_insn (reg, gen_const_mem (Pmode, reg));
+ tp = gen_rtx_REG (SImode, CSKY_TLS_REGNUM);
+ return gen_rtx_PLUS (Pmode, tp, reg);
+
+ case TLS_MODEL_LOCAL_EXEC:
+ unspec = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (2, x, GEN_INT (TLS_LE32)),
+ UNSPEC_TLS);
+ emit_move_insn (reg, unspec);
+ tp = gen_rtx_REG (SImode, CSKY_TLS_REGNUM);
+ return gen_rtx_PLUS (Pmode, tp, reg);
+
+ default:
+ abort ();
+ }
+}
+
+
+/* Implement TARGET_LEGITIMIZE_ADDRESS. */
+
+static rtx
+csky_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED,
+ machine_mode mode)
+{
+ if (csky_tls_symbol_p (x))
+ return csky_legitimize_tls_address (x, NULL_RTX);
+
+ if (GET_CODE (x) == PLUS)
+ {
+ rtx xop0 = XEXP (x, 0);
+ rtx xop1 = XEXP (x, 1);
+
+ if (is_csky_address_register_rtx_p (xop0, 0)
+ && CONST_INT_P (xop1))
+ {
+ HOST_WIDE_INT offset = INTVAL (xop1);
+
+ /* Try to replace ld32 rx,(ry, offset), to addi16 rz, oimm8
+ and ld16 rx,(rz, new_ld_offset) to avoid emitting a
+ 32-bit ld, but this addi has a range limitation. */
+ if (optimize_size
+ && offset > CSKY_LD16_MAX_OFFSET (mode)
+ && offset <= (CSKY_ADDI16_MAX_IMM
+ + CSKY_LD16_MAX_OFFSET (mode)))
+ {
+ HOST_WIDE_INT new_ld_offset
+ = offset & CSKY_LD16_OFFSET_MASK (mode);
+
+ xop0 = force_operand (plus_constant (Pmode, xop0,
+ offset - new_ld_offset),
+ NULL_RTX);
+ x = plus_constant (Pmode, xop0, new_ld_offset);
+ }
+ else if (offset < 0 && offset >= (-CSKY_SUBI16_MAX_IMM))
+ x = force_operand (x, NULL_RTX);
+ else if (offset > CSKY_LD16_MAX_OFFSET (mode)
+ || offset < 0)
+ {
+ /* For the remaining cases, force the constant into a
+ register. */
+ xop1 = force_reg (SImode, xop1);
+ x = gen_rtx_PLUS (SImode, xop0, xop1);
+ }
+ }
+
+ /* If the index is store in register, force the
+ base to register. */
+ if (is_csky_address_register_rtx_p (xop1, 0)
+ && !is_csky_address_register_rtx_p (xop0, 0))
+ {
+ xop0 = force_operand (xop0, NULL_RTX);
+ x = gen_rtx_PLUS (SImode, xop0, xop1);
+ }
+ }
+ /* Make sure to take full advantage of the pre-indexed addressing mode
+ with absolute addresses which often allows for the base register to
+ be factorized for multiple adjacent memory references, and it might
+ even allows for the mini pool to be avoided entirely. */
+ else if (CONST_INT_P (x) && optimize > 0)
+ {
+ HOST_WIDE_INT mask, base, index;
+ rtx base_reg;
+
+ mask = CSKY_LD16_OFFSET_MASK (mode);
+ base = INTVAL (x) & ~mask;
+ index = INTVAL (x) & mask;
+ base_reg = force_reg (SImode, GEN_INT (base));
+ x = plus_constant (Pmode, base_reg, index);
+ }
+
+ return x;
+}
+
+
+/* Return nonzero if INDEX is valid for an address index operand.
+ ck801 use 16 bits ld
+ ck802 use 16 and 32 bits ld
+ others use ld and ldr. */
+
+static int
+ck801_legitimate_index_p (machine_mode mode, rtx index,
+ int strict_p ATTRIBUTE_UNUSED)
+{
+ enum rtx_code code = GET_CODE (index);
+
+ /* When the mode size is larger than 4, we may use two ld instruction
+ to get data, the index and (index+1) should be valid. */
+ if (GET_MODE_SIZE (mode) >= 8)
+ return (code == CONST_INT
+ && INTVAL (index) < CSKY_LD16_MAX_OFFSET (SImode)
+ && INTVAL (index) >= 0 && (INTVAL (index) & 3) == 0);
+
+ if (code == CONST_INT && GET_MODE_SIZE (mode) > 0
+ && INTVAL (index) <= CSKY_LD16_MAX_OFFSET (mode)
+ && INTVAL (index) >= 0)
+ return ((INTVAL (index) % GET_MODE_SIZE (mode)) == 0);
+
+ return 0;
+}
+
+
+static int
+ck802_legitimate_index_p (machine_mode mode, rtx index,
+ int strict_p ATTRIBUTE_UNUSED)
+{
+ enum rtx_code code = GET_CODE (index);
+
+ /* When the mode size is larger than 4, we may use two ld instruction
+ to get data, the index and (index+1) should be valid. */
+ if (GET_MODE_SIZE (mode) >= 8)
+ return (code == CONST_INT
+ && INTVAL (index) < CSKY_LD32_MAX_OFFSET (SImode)
+ && INTVAL (index) >= 0 && (INTVAL (index) & 3) == 0);
+
+ if (code == CONST_INT && GET_MODE_SIZE (mode) > 0
+ && INTVAL (index) <= CSKY_LD32_MAX_OFFSET (mode)
+ && INTVAL (index) >= 0)
+ return ((INTVAL (index) % GET_MODE_SIZE (mode)) == 0);
+
+ return 0;
+}
+
+
+/* The instruction ldr rz, (rx, ry << i), i can be 0,1,2,3.
+ Check that SHIFT is valid, that the code is MULT, and that
+ the shift is a power of 2. */
+
+static bool
+is_ldr_shift_p (HOST_WIDE_INT shift, enum rtx_code code)
+{
+ if (code == ASHIFT)
+ return (shift >= 0 && shift <= 3);
+ else if (code == MULT)
+ return (shift == 1
+ || shift == 2
+ || shift == 4
+ || shift == 8);
+ else
+ return false;
+}
+
+
+static int
+ck810_legitimate_index_p (machine_mode mode, rtx index, int strict_p)
+{
+ enum rtx_code code = GET_CODE (index);
+
+ if (TARGET_HARD_FLOAT
+ && (mode == SFmode || mode == DFmode))
+ return (code == CONST_INT && INTVAL (index) < 1024
+ && INTVAL (index) >= 0
+ && (INTVAL (index) & 3) == 0);
+
+ if (code == CONST_INT)
+ {
+ /* When the mode size is larger than 4, we may use two ld instruction
+ to get data, the index and (index+1) should be valid. */
+ if (GET_MODE_SIZE (mode) >= 8)
+ return (INTVAL (index) < CSKY_LD32_MAX_OFFSET (SImode)
+ && INTVAL (index) >= 0 && (INTVAL (index) & 3) == 0);
+
+ if (GET_MODE_SIZE (mode) > 0
+ && INTVAL (index) <= CSKY_LD32_MAX_OFFSET (mode)
+ && INTVAL (index) >= 0)
+ return ((INTVAL (index) % GET_MODE_SIZE (mode)) == 0);
+ }
+ /* Allow ld.w rx, (gb, sym@got) when -fpic specially. */
+ else if (code == UNSPEC)
+ return (flag_pic == 1
+ && (XINT (index, 1) == UNSPEC_PIC_SYMBOL_PLT
+ || XINT (index, 1) == UNSPEC_PIC_SYMBOL_GOT));
+ /* The follow index is for ldr instruction, the ldr cannot
+ load dword data, so the mode size should not be larger than
+ 4. */
+ else if (GET_MODE_SIZE (mode) <= 4)
+ {
+ if (is_csky_address_register_rtx_p (index, strict_p))
+ return 1;
+ else if (code == MULT || code == ASHIFT)
+ {
+ rtx xiop0 = XEXP (index, 0);
+ rtx xiop1 = XEXP (index, 1);
+
+ /* FIXME can the xiop1 be the reg and xiop0 be the int when mult? */
+ return (is_csky_address_register_rtx_p (xiop0, strict_p)
+ && CONST_INT_P (xiop1)
+ && is_ldr_shift_p (INTVAL (xiop1), code));
+ }
+ }
+
+ return 0;
+}
+
+
+static int
+csky_legitimate_index_p (machine_mode mode, rtx index, int strict_p)
+{
+ if (CSKY_TARGET_ARCH (CK801))
+ return ck801_legitimate_index_p (mode, index, strict_p);
+ else if (CSKY_TARGET_ARCH (CK802))
+ return ck802_legitimate_index_p (mode, index, strict_p);
+ else
+ return ck810_legitimate_index_p (mode, index, strict_p);
+}
+
+
+/* Implement TARGET_LEGITIMATE_ADDRESS_P.
+ Recognizes RTL expressions that are valid memory addresses for an
+ instruction. The MODE argument is the machine mode for the MEM
+ expression that wants to use this address.
+
+ It only recognizes address in canonical form. LEGITIMIZE_ADDRESS should
+ convert common non-canonical forms to canonical form so that they will
+ be recognized. */
+
+static bool
+csky_legitimate_address_p (machine_mode mode, rtx addr, bool strict_p)
+{
+ enum rtx_code code = GET_CODE (addr);
+
+ /* Match the RTX form emitted for constant pool references.
+ After reload constants split into minipools will have addresses
+ from a LABEL_REF. */
+ if (reload_completed
+ && ((code == LABEL_REF)
+ || (code == CONST
+ && GET_CODE (XEXP (addr, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
+ && CONST_INT_P (XEXP (XEXP (addr, 0), 1)))))
+ return 1;
+
+ if (is_csky_address_register_rtx_p (addr, strict_p))
+ return 1;
+ /* It is a pc-relative load, may be generated for constpool. */
+ else if (GET_CODE (addr) == LABEL_REF)
+ return 1;
+
+ if (code == PLUS)
+ {
+ rtx xop0 = XEXP (addr, 0);
+ rtx xop1 = XEXP (addr, 1);
+
+ return ((is_csky_address_register_rtx_p (xop0, strict_p)
+ && csky_legitimate_index_p (mode, xop1, strict_p))
+ || (is_csky_address_register_rtx_p (xop1, strict_p)
+ && csky_legitimate_index_p (mode, xop0, strict_p)));
+ }
+
+ return 0;
+}
+
+
+/* Functions to save and restore machine-specific function data. */
+
+static struct machine_function *
+csky_init_machine_status (void)
+{
+ struct machine_function *machine;
+
+ machine = ggc_cleared_alloc<machine_function> ();
+
+#if CSKY_FT_UNKNOWN != 0
+ machine->func_type = CSKY_FT_UNKNOWN;
+#endif
+ return machine;
+}
+
+
+/* Implement INIT_EXPANDERS. */
+
+void
+csky_init_expanders (void)
+{
+ /* Arrange to initialize and mark the machine per-function status. */
+ init_machine_status = csky_init_machine_status;
+}
+
+
+/* Implement TARGET_CANNOT_COPY_INSN_P.
+ We must not copy any rtx that uses a pc-relative address. */
+
+static bool
+csky_cannot_copy_insn_p (rtx_insn *insn)
+{
+ subrtx_iterator::array_type array;
+ FOR_EACH_SUBRTX (iter, array, PATTERN (insn), ALL)
+ {
+ const_rtx x = *iter;
+ if (GET_CODE (x) == UNSPEC
+ && (XINT (x, 1) == UNSPEC_TLS_LABEL
+ || XINT (x, 1) == UNSPEC_PIC_SYMBOL_GOTPC_GRS))
+ return true;
+ }
+ return false;
+}
+
+
+/* Extract the parts of an RTL expression that is a valid memory address
+ for an instruction. Return FALSE if it is a invalid memory address. */
+
+struct csky_address
+{
+ rtx base, index, symbol, label, disp;
+ HOST_WIDE_INT scale;
+};
+
+static bool
+decompose_csky_address (rtx addr, struct csky_address *out)
+{
+ rtx base = NULL_RTX, index = NULL_RTX, disp = NULL_RTX;
+ HOST_WIDE_INT scale = 1;
+ rtx scale_rtx = NULL_RTX;
+ int i;
+
+ out->base = out->index = out->symbol = out->label = out->disp = NULL_RTX;
+ out->scale = 0;
+
+ if (REG_P (addr))
+ {
+ out->base = addr;
+ return true;
+ }
+
+ if (GET_CODE (addr) == LABEL_REF)
+ {
+ out->label = addr;
+ return true;
+ }
+
+ if (GET_CODE (addr) == CONST)
+ addr = XEXP (addr, 0);
+
+ if (GET_CODE (addr) == PLUS)
+ {
+ rtx addends[2], op;
+
+ addends[0] = XEXP (addr, 0);
+ addends[1] = XEXP (addr, 1);
+
+ if (GET_CODE (addends[0]) == LABEL_REF && CONST_INT_P (addends[1]))
+ {
+ out->label = addends[0];
+ out->disp = addends[1];
+ return true;
+ }
+
+ if (!REG_P (addends[0]))
+ std::swap (addends[0], addends[1]);
+
+ for (i = 0; i < 2; ++i)
+ {
+ op = addends[i];
+ switch (GET_CODE (op))
+ {
+ case REG:
+ if (!base)
+ base = op;
+ else if (!index)
+ index = op;
+ else
+ return false;
+ break;
+ case CONST_INT:
+ case UNSPEC:
+ if (disp)
+ return false;
+ disp = op;
+ break;
+ case MULT:
+ if (index)
+ return false;
+ index = XEXP (op, 0);
+ scale_rtx = XEXP (op, 1);
+ if (!CONST_INT_P (index) && !CONST_INT_P (scale_rtx))
+ return false;
+ else if (CONST_INT_P (index))
+ std::swap (index, scale_rtx);
+ scale = INTVAL (scale_rtx);
+ break;
+ case ASHIFT:
+ if (index)
+ return false;
+ index = XEXP (op, 0);
+ scale_rtx = XEXP (op, 1);
+ if (!CONST_INT_P (scale_rtx))
+ return false;
+ scale = scale << INTVAL (scale_rtx);
+ break;
+ default:
+ return false;
+ }
+ }
+ }
+
+ if (!base)
+ return false;
+
+ out->base = base;
+ out->index = index;
+ out->disp = disp;
+ out->scale = scale;
+
+ return true;
+}
+
+/* Helper function for the csky_simple_mem_operand predicate. Returns
+ true if OP is an address of the form reg + displacement. */
+
+bool
+csky_simple_addr_operand_p (rtx op)
+{
+ struct csky_address addr;
+
+ if (!decompose_csky_address (op, &addr))
+ return false;
+
+ /* FIXME The PIC related code.
+ Check if load the symbol address from got table. */
+ if (addr.disp && GET_CODE (addr.disp) == UNSPEC)
+ return false;
+ if (!addr.index && !addr.symbol)
+ return true;
+ return false;
+}
+
+
+/* Print the UNSPEC operand in X to the STREAM. */
+
+static void
+csky_output_pic_addr_const (FILE *stream, rtx x, int code)
+{
+
+ if (GET_CODE (x) != UNSPEC)
+ return;
+
+ if (UNSPEC_TLS == XINT (x, 1))
+ {
+ /* FIXME It is not reached */
+ return;
+ }
+
+ csky_print_operand (stream, XVECEXP (x, 0, 0), code);
+
+ switch (XINT (x, 1))
+ {
+ case UNSPEC_PIC_SYMBOL_GOTOFF:
+ fputs ("@GOTOFF", stream);
+ break;
+ case UNSPEC_PIC_SYMBOL_PLT:
+ fputs ("@PLT", stream);
+ break;
+ case UNSPEC_PIC_SYMBOL_GOT:
+ fputs ("@GOT", stream);
+ break;
+ case UNSPEC_PIC_SYMBOL_GOTPC:
+ fputs ("@GOTPC", stream);
+ break;
+ case UNSPEC_PIC_SYMBOL_BSR:
+ break;
+ default:
+ break;
+ }
+}
+
+
+/* Output the constpool label according to the rtx expression X. */
+
+static void
+csky_output_constpool_label (FILE *stream, rtx x)
+{
+ char buf[15];
+
+ gcc_assert (GET_CODE (x) == LABEL_REF);
+ x = XEXP (x, 0);
+
+ if (GET_CODE (x) == UNSPEC_VOLATILE && XINT (x, 1) == VUNSPEC_POOL_LABEL)
+ {
+ ASM_GENERATE_INTERNAL_LABEL (buf, CSKY_CONSTPOOL_LABEL_PREFIX,
+ INTVAL (XVECEXP (x, 0, 0)));
+ assemble_name (stream, buf);
+ }
+}
+
+
+/* Implement TARGET_PRINT_OPERAND_ADDRESS. */
+
+static void
+csky_print_operand_address (FILE *stream,
+ machine_mode mode ATTRIBUTE_UNUSED,
+ rtx x)
+{
+
+ struct csky_address addr;
+
+ decompose_csky_address (x, &addr);
+
+ if (addr.label && addr.disp && GET_CODE (addr.disp) == CONST_INT)
+ {
+ fprintf (stream, "[");
+ csky_output_constpool_label (stream, addr.label);
+ fprintf (stream, "+%d]", (int) INTVAL (addr.disp));
+ }
+ else if (addr.label)
+ {
+ fprintf (stream, "[");
+ csky_output_constpool_label (stream, addr.label);
+ fprintf (stream, "]");
+ }
+ else if (addr.symbol && addr.disp && GET_CODE (addr.disp) == CONST_INT)
+ {
+ fprintf (stream, "[");
+ output_addr_const (stream, addr.symbol);
+ fprintf (stream, "+%d]", (int) INTVAL (addr.disp));
+ }
+ else if (addr.symbol)
+ {
+ fprintf (stream, "[");
+ output_addr_const (stream, addr.symbol);
+ fprintf (stream, "]");
+ }
+ else if (addr.disp && GET_CODE (addr.disp) == CONST_INT)
+ fprintf (stream, "(%s, %d)",
+ reg_names[REGNO (addr.base)], (int) INTVAL (addr.disp));
+ else if (addr.disp && GET_CODE (addr.disp) == UNSPEC)
+ {
+ if (REGNO (addr.base) != CSKY_GB_REGNUM)
+ fprintf (stream, "(%s, ", reg_names[REGNO (addr.base)]);
+ else
+ fprintf (stream, "[");
+ csky_output_pic_addr_const (stream, addr.disp, 0);
+ fprintf (stream, "%s", (REGNO (addr.base) != CSKY_GB_REGNUM)
+ ? ")" : "]");
+ }
+ else if (addr.index)
+ fprintf (stream, "(%s, %s << %d)",
+ reg_names[REGNO (addr.base)], reg_names[REGNO (addr.index)],
+ exact_log2 ((int) (addr.scale)));
+ else
+ fprintf (stream, "(%s, 0)", reg_names[REGNO (addr.base)]);
+}
+
+
+/* Implement TARGET_PRINT_OPERAND.
+ Print operand X (an rtx) in assembler syntax to file STREAM
+ according to modifier CODE.
+
+ 'N' print the log2(X+1), mainly used for bmaski
+ 'P' print the log2(X)
+ 'Q' print the log2(~X)
+ 'O' print a decimal number
+ 'M' print a decimal number as its negative
+ 'R' print the next register or memory location along, i.e. the lsw in
+ a double word value
+ 'H' print the high 16 bits of a constant. */
+
+static void
+csky_print_operand (FILE *stream, rtx x, int code)
+{
+ switch (code)
+ {
+ case 'N':
+ if ((INTVAL (x) & 0xffffffff) == 0xffffffff)
+ fprintf (stream, "0");
+ else
+ fprintf (stream, "%d",
+ (int) exact_log2 ((INTVAL (x) & 0xffffffff) + 1) % 32);
+ break;
+ case 'P':
+ fprintf (stream, "%d",
+ (int) exact_log2 (INTVAL (x) & 0xffffffff));
+ break;
+ case 'Q':
+ fprintf (stream, "%d",
+ (int) exact_log2 (~INTVAL (x) & 0xffffffff));
+ break;
+ case 'O':
+ fprintf (stream, "%d", (int) INTVAL (x));
+ break;
+ case 'M':
+ fprintf (stream, "%d", (int) (-INTVAL (x)));
+ break;
+ case 'R':
+ /* Next location along in memory or register. */
+ switch (GET_CODE (x))
+ {
+ case REG:
+ fputs (reg_names[REGNO (x) + 1], stream);
+ break;
+ case MEM:
+ csky_print_operand_address
+ (stream, GET_MODE (x), XEXP (adjust_address (x, SImode, 4), 0));
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ break;
+ case 'H':
+ fprintf (stream, "%ld", (long)((INTVAL (x) & 0xFFFF0000) >> 16));
+ break;
+ default:
+ switch (GET_CODE (x))
+ {
+ case REG:
+ fputs (reg_names[REGNO (x)], stream);
+ break;
+ case MEM:
+ output_address (GET_MODE (x), XEXP (x, 0));
+ break;
+ case UNSPEC:
+ csky_output_pic_addr_const (stream, x, code);
+ break;
+ default:
+ output_addr_const (stream, x);
+ break;
+ }
+ break;
+ }
+}
+
+
+
+/* Implement TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS. */
+
+static bool
+csky_allocate_stack_slots_for_args (void)
+{
+ /* Naked functions should not allocate stack slots for arguments. */
+ return !CSKY_FUNCTION_IS_NAKED (get_csky_current_func_type ());
+}
+
+
+/* Can we generate a constant with a single instruction, without using
+ lrw? */
+
+static int
+const_ok_for_cskyv2 (HOST_WIDE_INT value)
+{
+ /* Try exact power of two. It can be generated by bgeni. */
+ if (CSKY_CONST_OK_FOR_Ub (value))
+ return 1;
+
+ /* Try exact power of two - 1. It can be generated by bmaski. */
+ if (CSKY_CONST_OK_FOR_Uc (value) && value != -1)
+ return 1;
+
+ /* Try if it can be generated by movi. */
+ if (CSKY_CONST_OK_FOR_I (value))
+ return 1;
+
+ /* The constant can be generated by movih.
+ Notice that movih is a 32-bit instruction. */
+ if (CSKY_CONST_OK_FOR_MOVIH (value))
+ return 1;
+
+ return 0;
+}
+
+
+/* Tricks for synthesizing constants from values that can be directly
+ manipulated by machine instructions. */
+
+enum csky_inline_const_type
+{
+ IC_UNINLINABLE = 0, /* Not inlineable */
+ IC_SINGLE, /* Single instruction */
+ IC_APPEND_NOT, /* Single instruction followed by a not */
+ IC_APPEND_ADDI, /* Single insn followed by an addi */
+ IC_APPEND_SUBI, /* Single insn followed by a subi */
+ IC_BGENI_ADDI, /* Single insn(bgeni) followed by an addi */
+ IC_BGENI_SUBI, /* Single insn(bgeni) followed by a subi */
+ IC_APPEND_BSETI, /* Single insn followed by bseti */
+ IC_APPEND_MOVI, /* Single insn followed by movi */
+ IC_APPEND_BCLRI, /* Single insn followed by bclri */
+ IC_APPEND_ROTLI, /* Single insn followed by rotli */
+ IC_APPEND_LSLI, /* Single insn followed by lsli */
+ IC_APPEND_IXH, /* Single insn followed by ixh */
+ IC_APPEND_IXW /* Single insn followed by ixw */
+};
+
+
+/* Try tricks to load a constant inline and return the trick number if
+ success, or IC_UNINLINABLE. */
+
+static enum csky_inline_const_type
+try_csky_constant_tricks (HOST_WIDE_INT value, HOST_WIDE_INT *x,
+ HOST_WIDE_INT *y)
+{
+ HOST_WIDE_INT i, value_invert;
+ unsigned HOST_WIDE_INT bit, shf, rot, lobits, hibits;
+
+ value &= 0xffffffff;
+ value_invert = ~value & 0xffffffff;
+
+ if (const_ok_for_cskyv2 (value))
+ {
+ *x = value;
+ return IC_SINGLE;
+ }
+
+ /* Since movih is 32 bits, do not use it here, better code may
+ be generated later. */
+ if (const_ok_for_cskyv2 (value_invert)
+ && !CSKY_CONST_OK_FOR_MOVIH (value_invert))
+ {
+ *x = value_invert;
+ return IC_APPEND_NOT;
+ }
+
+ /* One immediate generate instruction, and one 16-bit subi or addi. */
+ for (i = 1; i <= 32; i++)
+ {
+ if (const_ok_for_cskyv2 (value - i)
+ && !CSKY_CONST_OK_FOR_MOVIH (value - i))
+ {
+ *x = value - i;
+ *y = i;
+ return IC_APPEND_ADDI;
+ }
+
+ if (const_ok_for_cskyv2 (value + i)
+ && !CSKY_CONST_OK_FOR_MOVIH (value - i))
+ {
+ *x = value + i;
+ *y = i;
+ return IC_APPEND_SUBI;
+ }
+ }
+
+ /* Generate bgeni + addi. */
+ if (CSKY_CONST_OK_FOR_Ub (value & 0xfffff000))
+ {
+ *x = (value & 0xfffff000);
+ *y = (value & 0xfff);
+ return IC_BGENI_ADDI;
+ }
+
+ /* Generate bgeni + subi. */
+ lobits = value & 0xfff;
+ hibits = (unsigned HOST_WIDE_INT)(value & 0xfffff000) + (1 << 12);
+ if (exact_log2 (hibits) >= 1
+ && exact_log2 (hibits) <= 30
+ && lobits != 0)
+ {
+ *x = hibits;
+ *y = (0x1000 - lobits);
+ return IC_BGENI_SUBI;
+ }
+
+ /* One immediate generate instruction, and one bseti or bclri. */
+ bit = 0x80000000ULL;
+ for (i = 0; i <= 31; i++)
+ {
+ if (const_ok_for_cskyv2 (value & ~bit)
+ && !CSKY_CONST_OK_FOR_MOVIH (value & ~bit))
+ {
+ *y = bit;
+ *x = (value & ~bit);
+ return IC_APPEND_BSETI;
+ }
+
+ if (const_ok_for_cskyv2 (value | bit)
+ && !CSKY_CONST_OK_FOR_MOVIH (value | bit))
+ {
+ *y = ~bit & 0xffffffff;
+ *x = value | bit;
+ return IC_APPEND_BCLRI;
+ }
+
+ bit >>= 1;
+ }
+
+ /* One immediate generate instruction, and one rotli or lsli. */
+ shf = value;
+ rot = value;
+ for (i = 1; i < 31; i++)
+ {
+ int c;
+
+ /* Rotate left. */
+ c = rot << 31;
+ rot >>= 1;
+ rot &= 0x7FFFFFFF;
+ rot |= c;
+
+ if (const_ok_for_cskyv2 (rot) && !CSKY_CONST_OK_FOR_MOVIH (rot))
+ {
+ *y = i;
+ *x = rot;
+ return IC_APPEND_ROTLI;
+ }
+
+ /* Can't use logical shift when low order bit is one. */
+ if (shf & 1)
+ shf = 0;
+ else
+ shf >>= 1;
+
+ if (shf != 0 && const_ok_for_cskyv2 (shf)
+ && !CSKY_CONST_OK_FOR_MOVIH (shf))
+ {
+ *y = i;
+ *x = shf;
+ return IC_APPEND_LSLI;
+ }
+ }
+
+ /* One immediate generate instruction, and one ixh. */
+ if (CSKY_ISA_FEATURE (E2)
+ && (value % 3) == 0
+ && const_ok_for_cskyv2 (value / 3)
+ && !CSKY_CONST_OK_FOR_MOVIH (value / 3))
+ {
+ *x = value / 3;
+ return IC_APPEND_IXH;
+ }
+
+ /* One immediate generate instruction, and one ixw. */
+ if (CSKY_ISA_FEATURE (E2)
+ && (value % 5) == 0
+ && const_ok_for_cskyv2 (value / 5)
+ && !CSKY_CONST_OK_FOR_MOVIH (value / 5))
+ {
+ *x = value / 5;
+ return IC_APPEND_IXW;
+ }
+
+ /* Generate movih + bseti. */
+ if (CSKY_CONST_OK_FOR_Ub (value & 0xffff))
+ {
+ *x = value & 0xffff0000;
+ *y = value & 0xffff;
+ return IC_APPEND_BSETI;
+ }
+
+ /* Generate movih + not. */
+ if (CSKY_CONST_OK_FOR_MOVIH (value_invert))
+ {
+ *x = value_invert;
+ return IC_APPEND_NOT;
+ }
+
+ /* One movih, and one 16bits addi or subi. */
+ for (i = 1; i <= 32; i++)
+ {
+ if (CSKY_CONST_OK_FOR_MOVIH (value - i))
+ {
+ *x = value - i;
+ *y = i;
+ return IC_APPEND_ADDI;
+ }
+
+ if (CSKY_CONST_OK_FOR_MOVIH (value + i))
+ {
+ *x = value + i;
+ *y = i;
+ return IC_APPEND_SUBI;
+ }
+ }
+
+ /* One movih, and one bseti or bclri. */
+ bit = 0x80000000ULL;
+ for (i = 0; i <= 31; i++)
+ {
+ if (CSKY_CONST_OK_FOR_MOVIH (value & ~bit))
+ {
+ *y = bit;
+ *x = value & ~bit;
+ return IC_APPEND_BSETI;
+ }
+
+ if (CSKY_CONST_OK_FOR_MOVIH (value | bit))
+ {
+ *y = ~bit & 0xffffffff;
+ *x = value | bit;
+ return IC_APPEND_BCLRI;
+ }
+
+ bit >>= 1;
+ }
+
+ /* One movih, and one rotli or lsli. */
+ shf = value;
+ rot = value;
+ for (i = 1; i < 31; i++)
+ {
+ int c;
+
+ /* Rotate left. */
+ c = rot << 31;
+ rot >>= 1;
+ rot &= 0x7FFFFFFF;
+ rot |= c;
+
+ if (CSKY_CONST_OK_FOR_MOVIH (rot))
+ {
+ *y = i;
+ *x = rot;
+ return IC_APPEND_ROTLI;
+ }
+
+ /* Can't use logical shift when low order bit is one. */
+ if (shf & 1)
+ shf = 0;
+ else
+ shf >>= 1;
+
+ if (shf != 0 && CSKY_CONST_OK_FOR_MOVIH (shf))
+ {
+ *y = i;
+ *x = shf;
+ return IC_APPEND_LSLI;
+ }
+ }
+
+ return IC_UNINLINABLE;
+}
+
+
+/* Actually output a constant using a trick.
+ FIXME: I think this would be better handled by a splitter than at the
+ asm output level. */
+
+static const char *
+csky_output_inline_const (machine_mode mode, rtx operands[])
+{
+ HOST_WIDE_INT x = 0, y = 0;
+ enum csky_inline_const_type trick_type;
+ rtx out_operands[3];
+ char buf[256];
+ char load_op[128];
+ const char *dst_fmt;
+ HOST_WIDE_INT value = INTVAL (operands[1]);
+ int ivalue = (int) value;
+ unsigned int uvalue = (unsigned int) value;
+
+ trick_type = try_csky_constant_tricks (value, &x, &y);
+ /* lrw's are handled separately: Large inlinable constants never get
+ turned into lrw's. Our caller uses try_csky_constant_tricks to back
+ off to an lrw rather than calling this routine. */
+ gcc_assert (trick_type != IC_UNINLINABLE);
+
+ /* Operands: 0 = dst, 1 = load immedate., 2 = adjust immedate. */
+ out_operands[0] = operands[0];
+ out_operands[1] = GEN_INT (x);
+ if (trick_type != IC_SINGLE && trick_type != IC_APPEND_NOT)
+ out_operands[2] = GEN_INT (y);
+
+ /* Select dst format based on mode. */
+ if (mode == DImode && TARGET_BIG_ENDIAN)
+ dst_fmt = "%R0";
+ else
+ dst_fmt = "%0";
+
+ /* Try movi16: 0~31,movi32: 0~65535. */
+ if (CSKY_CONST_OK_FOR_I (x))
+ sprintf (load_op, "movi\t%s, %%1", dst_fmt);
+ /* Try exact power of two - 1. */
+ else if (CSKY_CONST_OK_FOR_Uc (x))
+ sprintf (load_op, "bmaski\t%s, %%N1", dst_fmt);
+ /* Try movih. */
+ else if (CSKY_CONST_OK_FOR_MOVIH (x))
+ sprintf (load_op, "movih\t%s, %%H1", dst_fmt);
+ else
+ {
+ sprintf (load_op, "BADMOVI-inline_const %s, %%1", dst_fmt);
+ gcc_unreachable ();
+ }
+
+ switch (trick_type)
+ {
+ case IC_SINGLE:
+ strcpy (buf, load_op);
+ break;
+ /* Add instruction 'not'. */
+ case IC_APPEND_NOT:
+ sprintf (buf, "%s\n\tnot\t%s, %s\t// %d 0x%x", load_op, dst_fmt,
+ dst_fmt, ivalue, uvalue);
+ break;
+ /* Add instruction 'addi'. */
+ case IC_APPEND_ADDI:
+ sprintf (buf, "%s\n\taddi\t%s, %s, %%2\t// %d 0x%x", load_op,
+ dst_fmt, dst_fmt, ivalue, uvalue);
+ break;
+ /* Add instruction 'subi'. */
+ case IC_APPEND_SUBI:
+ sprintf (buf, "%s\n\tsubi\t%s, %s, %%2\t// %d 0x%x", load_op,
+ dst_fmt, dst_fmt, ivalue, uvalue);
+ break;
+ /* Add instruction 'addi', the last instruction is bgeni. */
+ case IC_BGENI_ADDI:
+ sprintf (buf, "%s\n\taddi\t%s, %s, %%2\t// %d 0x%x", load_op,
+ dst_fmt, dst_fmt, ivalue, uvalue);
+ break;
+ /* Add instruction 'subi', the last instruction is bgeni. */
+ case IC_BGENI_SUBI:
+ sprintf (buf, "%s\n\tsubi\t%s, %s, %%2\t// %d 0x%x", load_op,
+ dst_fmt, dst_fmt, ivalue, uvalue);
+ break;
+ /* Add instruction 'bseti'. */
+ case IC_APPEND_BSETI:
+ sprintf (buf, "%s\n\tbseti\t%s, %s, %%P2\t// %d 0x%x", load_op,
+ dst_fmt, dst_fmt, ivalue, uvalue);
+ break;
+ /* Add instruction 'movi'. */
+ case IC_APPEND_MOVI:
+ sprintf (buf, "%s\n\tmovi\t%s, %%2\t// %d 0x%x", load_op, dst_fmt,
+ ivalue, uvalue);
+ break;
+ /* Add instruction 'bclri'. */
+ case IC_APPEND_BCLRI:
+ sprintf (buf, "%s\n\tbclri\t%s, %s, %%Q2\t// %d 0x%x", load_op,
+ dst_fmt, dst_fmt, ivalue, uvalue);
+ break;
+ /* Add instruction 'rotli'. */
+ case IC_APPEND_ROTLI:
+ sprintf (buf, "%s\n\trotli\t%s, %s, %%2\t// %d 0x%x", load_op,
+ dst_fmt, dst_fmt, ivalue, uvalue);
+ break;
+ /* Add instruction 'lsli'. */
+ case IC_APPEND_LSLI:
+ sprintf (buf, "%s\n\tlsli\t%s, %s, %%2\t// %d 0x%x", load_op,
+ dst_fmt, dst_fmt, ivalue, uvalue);
+ break;
+ /* Add instruction 'ixh'. */
+ case IC_APPEND_IXH:
+ sprintf (buf, "%s\n\tixh\t%s, %s, %s\t// %d 0x%x", load_op,
+ dst_fmt, dst_fmt, dst_fmt, ivalue, uvalue);
+ break;
+ /* Add instruction 'ixw'. */
+ case IC_APPEND_IXW:
+ sprintf (buf, "%s\n\tixw\t%s, %s, %s\t// %d 0x%x", load_op,
+ dst_fmt, dst_fmt, dst_fmt, ivalue, uvalue);
+ break;
+ default:
+ return "";
+ }
+
+ output_asm_insn (buf, out_operands);
+
+ return "";
+}
+
+/* This is a helper function for the Uo constraint for movsi patterns. */
+
+bool
+csky_inlinable_constant (HOST_WIDE_INT value)
+{
+ HOST_WIDE_INT x, y;
+ return (!(CSKY_TARGET_ARCH (CK802) || CSKY_TARGET_ARCH (CK801))
+ && try_csky_constant_tricks (value, &x, &y));
+}
+
+
+/* Return true if the constant VAL can be expressed by an 8-bit constant
+ with a shift value, filling in *BASE and *SHIFT. */
+
+bool
+csky_shifted_imm8_constant (unsigned HOST_WIDE_INT val,
+ unsigned int *base, unsigned int *shift)
+{
+ unsigned HOST_WIDE_INT mask = 0xff;
+ int i;
+ val = val & (unsigned HOST_WIDE_INT) 0xffffffffu;
+ if (val == 0)
+ return 0;
+
+ for (i = 0; i < 25; i++)
+ if ((val & (mask << i)) == val)
+ {
+ if (base)
+ *base = (unsigned int) (val >> i);
+ if (shift)
+ *shift = (unsigned int) i;
+ return true;
+ }
+
+ return false;
+}
+
+
+/* Output a move of a word or less value. */
+
+const char *
+csky_output_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[],
+ machine_mode mode ATTRIBUTE_UNUSED)
+{
+ rtx dst = operands[0];
+ rtx src = operands[1];
+ struct csky_address op0, op1;
+
+ if (REG_P (dst))
+ {
+ /* The situation mov reg to reg. */
+ if (REG_P (src))
+ {
+ int dstreg = REGNO (dst);
+ int srcreg = REGNO (src);
+
+ /* hilo registers exchange their places,
+ and their order of Dimode as same as other
+ general registers in LITTLE_ENDIAN mode. */
+ if (TARGET_BIG_ENDIAN)
+ {
+ if (dstreg == CSKY_HI_REGNUM)
+ return "mthi\t%1";
+ else if (dstreg == CSKY_LO_REGNUM)
+ return "mtlo\t%1";
+ else if (srcreg == CSKY_HI_REGNUM)
+ return "mfhi\t%0";
+ else if (srcreg == CSKY_LO_REGNUM)
+ return "mflo\t%0";
+ }
+ else
+ {
+ if (dstreg == CSKY_HI_REGNUM)
+ return "mtlo\t%1";
+ else if (dstreg == CSKY_LO_REGNUM)
+ return "mthi\t%1";
+ else if (srcreg == CSKY_HI_REGNUM)
+ return "mflo\t%0";
+ else if (srcreg == CSKY_LO_REGNUM)
+ return "mfhi\t%0";
+ }
+
+ if (CSKY_VREG_P (dstreg) && CSKY_VREG_P (srcreg))
+ return "fmovs\t%0, %1";
+ if (CSKY_VREG_P (dstreg))
+ return "fmtvrl\t%0, %1";
+ if (CSKY_VREG_P (srcreg))
+ return "fmfvrl\t%0, %1";
+
+ if (REGNO (src) == CSKY_CC_REGNUM)
+ return "mvc\t%0";
+ else
+ return "mov\t%0, %1";
+ }
+ /* The situation mov memory to reg. */
+ else if (GET_CODE (src) == MEM)
+ {
+ decompose_csky_address (XEXP (src, 0), &op1);
+
+ if (op1.index)
+ switch (GET_MODE (src))
+ {
+ case E_HImode:
+ return "ldr.h\t%0, %1";
+ case E_QImode:
+ return "ldr.b\t%0, %1";
+ case E_SImode:
+ case E_SFmode:
+ if (CSKY_VREG_P (REGNO (dst)))
+ return "fldrs\t%0, %1";
+ else
+ return "ldr.w\t%0, %1";
+ default:
+ gcc_unreachable ();
+ }
+ /* Generate lrw rx, [LABEL]. This happens when the compiler
+ generates constant pool references and uses lrw to get the
+ constant into memory. */
+ else if (op1.label)
+ return "lrw\t%0, %1";
+ /* Generate lrs.w rx, [symbol@GOT/PLT]. */
+ else if (flag_pic == 1 && op1.disp && GET_CODE (op1.disp) == UNSPEC)
+ return "lrs.w\t%0, %1";
+ else
+ switch (GET_MODE (src))
+ {
+ case E_HImode:
+ return "ld.h\t%0, %1";
+ case E_QImode:
+ return "ld.b\t%0, %1";
+ case E_SFmode:
+ case E_SImode:
+ if (CSKY_VREG_P (REGNO (dst)))
+ return "flds\t%0, %1";
+ else
+ return "ld.w\t%0, %1";
+ default:
+ gcc_unreachable ();
+ }
+ }
+ /* The situation mov integer to reg. */
+ else if (GET_CODE (src) == CONST_INT ||
+ (GET_CODE (src) == CONST_DOUBLE && GET_MODE (src) == SFmode))
+ {
+ HOST_WIDE_INT x, y;
+ const REAL_VALUE_TYPE *d;
+ long l;
+
+ if (GET_CODE (src) == CONST_DOUBLE && GET_MODE (src) == SFmode)
+ {
+ d = CONST_DOUBLE_REAL_VALUE (src);
+ REAL_VALUE_TO_TARGET_SINGLE (*d, l);
+ operands[1] = GEN_INT (l);
+ src = operands[1];
+ }
+
+ if (try_csky_constant_tricks (INTVAL (src), &x, &y))
+ return csky_output_inline_const (SImode, operands);
+ /* Return '#' to split it. */
+ else if (CSKY_CONST_OK_FOR_T (INTVAL (src)))
+ return "#";
+ else
+ return "lrw\t%0, %x1\t";
+ }
+ else if (TARGET_ANCHOR && GET_CODE (src) == SYMBOL_REF)
+ {
+ if (SYMBOL_REF_FUNCTION_P (src))
+ return "lrw\t%0, %1@BTEXT";
+ else
+ return "lrw\t%0, %1@BDATA";
+ }
+ else if (GET_CODE (src) == UNSPEC
+ && XINT (src, 1) == UNSPEC_PIC_SYMBOL_GRS)
+ return "grs\t%0, %1";
+ else
+ return "lrw\t%0, %1";
+ }
+ else if (GET_CODE (dst) == MEM)
+ {
+ decompose_csky_address (XEXP (dst, 0), &op0);
+
+ if (op0.index)
+ switch (GET_MODE (src))
+ {
+ case E_HImode:
+ return "str.h\t%1, %0";
+ case E_QImode:
+ return "str.b\t%1, %0";
+ case E_SFmode:
+ case E_SImode:
+ if (CSKY_VREG_P (REGNO (src)))
+ return "fstrs\t%1, %0";
+ else
+ return "str.w\t%1, %0";
+ default:
+ gcc_unreachable ();
+ }
+ else
+ switch (GET_MODE (dst))
+ {
+ case E_HImode:
+ return "st.h\t%1, %0";
+ case E_QImode:
+ return "st.b\t%1, %0";
+ case E_SImode:
+ case E_SFmode:
+ if (CSKY_VREG_P (REGNO (src)))
+ return "fsts\t%1, %0";
+ else
+ return "st.w\t%1, %0";
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ gcc_unreachable ();
+}
+
+
+/* Output a move of a word or less value. Specific for ck801. */
+
+const char *
+csky_output_ck801_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[],
+ machine_mode mode ATTRIBUTE_UNUSED)
+{
+ rtx dst = operands[0];
+ rtx src = operands[1];
+ struct csky_address op1;
+
+ if (REG_P (dst))
+ {
+ if (REG_P (src))
+ return "mov\t%0, %1";
+ else if (GET_CODE (src) == MEM)
+ {
+ decompose_csky_address (XEXP (src, 0), &op1);
+
+ /* Generate lrw rx, [LABEL]. This happens when the compiler
+ generates constant pool references and uses lrw to get the
+ constant in memory. */
+ if (op1.label)
+ return "lrw\t%0, %1";
+ else
+ switch (GET_MODE (src))
+ {
+ case E_HImode:
+ return "ld.h\t%0, %1";
+ case E_QImode:
+ return "ld.b\t%0, %1";
+ case E_SFmode:
+ case E_SImode:
+ return "ld.w\t%0, %1";
+ default:
+ gcc_unreachable ();
+ }
+ }
+ else if (GET_CODE (src) == CONST_INT)
+ {
+ if (REGNO (dst) > 7)
+ return "lrw\t%0, %x1\t";
+ else if (CSKY_CONST_OK_FOR_N (INTVAL (src) + 1))
+ return "movi\t%0, %1";
+ /* Return '#' to split it. */
+ else if (CSKY_CONST_OK_FOR_T (INTVAL (src)))
+ return "#";
+ else if (csky_shifted_imm8_constant (INTVAL (src), NULL, NULL))
+ return "#";
+ else
+ return "lrw\t%0, %x1\t";
+ }
+ else if (GET_CODE (src) == CONST_DOUBLE && GET_MODE (src) == SFmode)
+ {
+ const REAL_VALUE_TYPE *d;
+ long l;
+
+ d = CONST_DOUBLE_REAL_VALUE (src);
+ REAL_VALUE_TO_TARGET_SINGLE (*d, l);
+ operands[1] = GEN_INT (l);
+ src = operands[1];
+
+ if (CSKY_CONST_OK_FOR_N (INTVAL (src) + 1))
+ return "movi\t%0, %1";
+ else
+ return "lrw\t%0, %x1\t";
+ }
+ else if (TARGET_ANCHOR && GET_CODE (src) == SYMBOL_REF)
+ {
+ if (SYMBOL_REF_FUNCTION_P (src))
+ return "lrw\t%0, %1@BTEXT";
+ else
+ return "lrw\t%0, %1@BDATA";
+ }
+ else
+ return "lrw\t%0, %1";
+ }
+ else if (GET_CODE (dst) == MEM)
+ switch (GET_MODE (dst))
+ {
+ case E_HImode:
+ return "st.h\t%1, %0";
+ case E_QImode:
+ return "st.b\t%1, %0";
+ case E_SImode:
+ case E_SFmode:
+ return "st.w\t%1, %0";
+ default:
+ gcc_unreachable ();
+ }
+
+ gcc_unreachable ();
+}
+
+
+/* Return a sequence of instructions to perform DI or DF move.
+ Since the CSKY cannot move a DI or DF in one instruction, we have
+ to take care when we see overlapping source and dest registers. */
+
+const char *
+csky_output_movedouble (rtx operands[],
+ machine_mode mode ATTRIBUTE_UNUSED)
+{
+ rtx dst = operands[0];
+ rtx src = operands[1];
+
+ if (REG_P (dst))
+ {
+ if (REG_P (src))
+ {
+ int dstreg = REGNO (dst);
+ int srcreg = REGNO (src);
+
+ if (CSKY_HILO_REG_P (srcreg))
+ {
+ if (TARGET_BIG_ENDIAN)
+ return "mfhi\t%0\n\tmflo\t%R0";
+ else
+ return "mfhi\t%R0\n\tmflo\t%0";
+ }
+ else if (CSKY_HILO_REG_P (dstreg))
+ {
+ if (TARGET_BIG_ENDIAN)
+ return "mthi\t%1\n\tmtlo\t%R1";
+ else
+ return "mthi\t%R1\n\tmtlo\t%1";
+ }
+ else if (CSKY_VREG_P (srcreg) && CSKY_VREG_P (dstreg))
+ return "fmovd\t%0, %1";
+ else if (CSKY_VREG_P (srcreg))
+ {
+ /* Since the vector registers in fpuv2_soft processors
+ like ck803f are 32 bits wide, just one insn is needed
+ to complete the move operation. */
+ if (TARGET_SOFT_FPU)
+ return "fmfvrl\t%0, %1";
+ else if (TARGET_BIG_ENDIAN)
+ return "fmfvrh\t%0, %1\n\tfmfvrl\t%R0, %1";
+ else
+ return "fmfvrh\t%R0, %1\n\tfmfvrl\t%0, %1";
+ }
+ else if (CSKY_VREG_P (dstreg))
+ {
+ if (TARGET_SOFT_FPU)
+ return "fmtvrl\t%0, %1";
+ else if (TARGET_BIG_ENDIAN)
+ return "fmtvrh\t%0, %1\n\tfmtvrl\t%0, %R1";
+ else
+ return "fmtvrh\t%0, %R1\n\tfmtvrl\t%0, %1";
+ }
+
+ /* Ensure the second source not overwritten. */
+ if (srcreg + 1 == dstreg)
+ return "mov\t%R0, %R1\n\tmov\t%0, %1";
+ else
+ return "mov\t%0, %1\n\tmov\t%R0, %R1";
+ }
+ else if (GET_CODE (src) == MEM)
+ {
+ rtx memexp = XEXP (src, 0);
+ int dstreg = REGNO (dst);
+ int basereg = -1;
+ struct csky_address op0;
+
+ decompose_csky_address (XEXP (src, 0), &op0);
+
+ if (GET_CODE (memexp) == LABEL_REF
+ || (GET_CODE (memexp) == CONST
+ && GET_CODE (XEXP (memexp, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (memexp, 0), 0)) == LABEL_REF))
+ return "lrw\t%0, [%1]\n\tlrw\t%R0, [%R1]";
+ else if (GET_CODE (memexp) == REG)
+ basereg = REGNO (memexp);
+ else if (GET_CODE (memexp) == PLUS)
+ {
+ if (GET_CODE (XEXP (memexp, 0)) == REG)
+ basereg = REGNO (XEXP (memexp, 0));
+ else if (GET_CODE (XEXP (memexp, 1)) == REG)
+ basereg = REGNO (XEXP (memexp, 1));
+ else
+ gcc_unreachable ();
+ }
+ else
+ gcc_unreachable ();
+
+
+ /* When FPUV2. */
+ if (CSKY_VREG_P (dstreg))
+ {
+ if (op0.index)
+ return "fldrd\t%0, %1";
+ else
+ return "fldd\t%0, %1";
+ }
+ /* FIXME length attribute is wrong here. */
+ if (dstreg == basereg)
+ /* Just load them in reverse order. */
+ return "ld.w\t%R0, %R1\n\tld.w\t%0, %1";
+ else
+ return "ld.w\t%0, %1\n\tld.w\t%R0, %R1";
+ }
+ else if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE)
+ {
+ split_double (src, operands + 2, operands + 3);
+
+ if (CSKY_CONST_OK_FOR_I (INTVAL (operands[2])))
+ output_asm_insn ("movi\t%0, %2", operands);
+ else if (CSKY_CONST_OK_FOR_Uc (INTVAL (operands[2])))
+ output_asm_insn ("bmaski\t%0, %N2", operands);
+ else if (CSKY_CONST_OK_FOR_Ub (INTVAL (operands[2])))
+ output_asm_insn ("bgeni\t%0, %P2", operands);
+ else
+ output_asm_insn ("lrw\t%0, %2", operands);
+
+ if (CSKY_CONST_OK_FOR_I (INTVAL (operands[3])))
+ output_asm_insn ("movi\t%R0, %3", operands);
+ else if (CSKY_CONST_OK_FOR_Uc (INTVAL (operands[3])))
+ output_asm_insn ("bmaski\t%R0, %N3", operands);
+
+ else if (CSKY_CONST_OK_FOR_Ub (INTVAL (operands[3])))
+ output_asm_insn ("bgeni\t%R0, %P3", operands);
+ else
+ output_asm_insn ("lrw\t%R0, %3", operands);
+
+ return "";
+ }
+ else
+ gcc_unreachable ();
+ }
+ else if (GET_CODE (dst) == MEM && GET_CODE (src) == REG)
+ {
+ rtx memexp = XEXP (dst, 0);
+ int srcreg = REGNO (src);
+ int basereg = -1;
+ struct csky_address op0;
+
+ decompose_csky_address (XEXP (dst, 0), &op0);
+
+ if (GET_CODE (memexp) == REG)
+ basereg = REGNO (memexp);
+ else if (GET_CODE (memexp) == PLUS)
+ {
+ if (GET_CODE (XEXP (memexp, 0)) == REG)
+ basereg = REGNO (XEXP (memexp, 0));
+ else if (GET_CODE (XEXP (memexp, 1)) == REG)
+ basereg = REGNO (XEXP (memexp, 1));
+ else
+ gcc_unreachable ();
+ }
+ else
+ gcc_unreachable ();
+
+ /* When FPUV2. */
+ if (CSKY_VREG_P (srcreg))
+ {
+ if (op0.index)
+ return "fstrd\t%1, %0";
+ else
+ return "fstd\t%1, %0";
+ }
+ /* FIXME length attribute is wrong here. */
+ if (srcreg == basereg)
+ /* Just load them in reverse order. */
+ return "st.w\t%R1, %R0\n\tst.w\t%1, %0";
+ else
+ return "st.w\t%1, %0\n\tst.w\t%R1, %R0";
+ }
+ else
+ gcc_unreachable ();
+}
+
+
+const char *
+csky_output_ck801_movedouble (rtx operands[],
+ machine_mode mode ATTRIBUTE_UNUSED)
+{
+ rtx dst = operands[0];
+ rtx src = operands[1];
+
+ if (REG_P (dst))
+ {
+ if (REG_P (src))
+ {
+ int dstreg = REGNO (dst);
+ int srcreg = REGNO (src);
+
+ /* Ensure the second source not overwritten. */
+ if (srcreg + 1 == dstreg)
+ return "mov\t%R0, %R1\n\tmov\t%0, %1";
+ else
+ return "mov\t%0, %1\n\tmov\t%R0, %R1";
+ }
+ else if (GET_CODE (src) == MEM)
+ {
+ rtx memexp = XEXP (src, 0);
+ int dstreg = REGNO (dst);
+ int basereg = -1;
+ struct csky_address op0;
+
+ decompose_csky_address (XEXP (src, 0), &op0);
+
+ if (GET_CODE (memexp) == LABEL_REF
+ || (GET_CODE (memexp) == CONST
+ && GET_CODE (XEXP (memexp, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (memexp, 0), 0)) == LABEL_REF))
+ return "lrw\t%0, [%1]\n\tlrw\t%R0, [%R1]";
+ else if (GET_CODE (memexp) == REG)
+ basereg = REGNO (memexp);
+ else if (GET_CODE (memexp) == PLUS)
+ {
+ if (GET_CODE (XEXP (memexp, 0)) == REG)
+ basereg = REGNO (XEXP (memexp, 0));
+ else if (GET_CODE (XEXP (memexp, 1)) == REG)
+ basereg = REGNO (XEXP (memexp, 1));
+ else
+ gcc_unreachable ();
+ }
+ else
+ gcc_unreachable ();
+
+ /* FIXME length attribute is wrong here. */
+ if (dstreg == basereg)
+ /* Just load them in reverse order. */
+ return "ld.w\t%R0, %R1\n\tld.w\t%0, %1";
+ else
+ return "ld.w\t%0, %1\n\tld.w\t%R0, %R1";
+ }
+ else if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE)
+ {
+ split_double (src, operands + 2, operands + 3);
+
+ if (REGNO (dst) <= 7
+ && CSKY_CONST_OK_FOR_N (INTVAL (operands[2]) + 1))
+ output_asm_insn ("movi\t%0, %2", operands);
+ else
+ output_asm_insn ("lrw\t%0, %2", operands);
+
+
+ if (REGNO (dst) <= 6
+ && CSKY_CONST_OK_FOR_N (INTVAL (operands[3]) + 1))
+ output_asm_insn ("movi\t%R0, %3", operands);
+ else
+ output_asm_insn ("lrw\t%R0, %3", operands);
+
+ return "";
+
+
+ }
+ else
+ gcc_unreachable ();
+ }
+ else if (GET_CODE (dst) == MEM && GET_CODE (src) == REG)
+ {
+ rtx memexp = XEXP (dst, 0);
+ int srcreg = REGNO (src);
+ int basereg = -1;
+ struct csky_address op0;
+
+ decompose_csky_address (XEXP (dst, 0), &op0);
+
+ if (GET_CODE (memexp) == REG)
+ basereg = REGNO (memexp);
+ else if (GET_CODE (memexp) == PLUS)
+ {
+ if (GET_CODE (XEXP (memexp, 0)) == REG)
+ basereg = REGNO (XEXP (memexp, 0));
+ else if (GET_CODE (XEXP (memexp, 1)) == REG)
+ basereg = REGNO (XEXP (memexp, 1));
+ else
+ gcc_unreachable ();
+ }
+ else
+ gcc_unreachable ();
+
+ /* FIXME length attribute is wrong here. */
+ if (srcreg == basereg)
+ /* Just load them in reverse order. */
+ return "st.w\t%R1, %R0\n\tst.w\t%1, %0";
+ else
+ return "st.w\t%1, %0\n\tst.w\t%R1, %R0";
+ }
+ else
+ gcc_unreachable ();
+}
+
+/* Split operands for an AND expression when OPERANDS[2] is a constant.
+ Note operands[0] is marked earlyclobber in this case and can be
+ overwritten. Return true if "DONE", false otherwise. */
+bool
+csky_split_and (rtx *operands)
+{
+ HOST_WIDE_INT mask = INTVAL (operands[2]);
+ rtx not_value = GEN_INT (~mask);
+ int i;
+
+ /* All zeros or all ones can be handled by a move instruction. */
+ if (mask == 0)
+ {
+ emit_move_insn (operands[0], const0_rtx);
+ return true;
+ }
+ if (mask == -1)
+ {
+ emit_move_insn (operands[0], operands[1]);
+ return true;
+ }
+
+ /* Check for constants that can be handled directly by the 32-bit andi
+ instruction. */
+ if (CSKY_ISA_FEATURE (E2) && csky_arith_O_operand (operands[2], SImode))
+ return false;
+
+ /* Try to transform to andni instruction. */
+ if (CSKY_ISA_FEATURE (E2) && csky_arith_O_operand (not_value, SImode))
+ {
+ emit_insn (gen_cskyv2_andnsi3 (operands[0], not_value, operands[1]));
+ return true;
+ }
+
+ /* If there are only one or two 0 bits in the constant, we can
+ replace the operation with bclri instructions on those bits.
+ Note CK801 has only the 16-bit bclri that operates on a single
+ register, so we must count a move if we are post-reload. */
+ if (popcount_hwi (~mask & 0xffffffff)
+ <= (reload_completed && !CSKY_ISA_FEATURE (E2) ? 1 : 2))
+ {
+ rtx input = operands[1];
+
+ if (!CSKY_ISA_FEATURE (E2))
+ {
+ emit_move_insn (operands[0], input);
+ input = operands[0];
+ }
+
+ for (i = 0; i < 32; i++)
+ if ((mask & (1 << i)) == 0x0)
+ {
+ emit_insn (gen_bclri (operands[0], input, GEN_INT (i)));
+ input = operands[0];
+ }
+ return true;
+ }
+
+ /* If the constant mask is outside the [0, 4095] range for
+ constraint O, or if constraint O is not allowed (ck801),
+ maybe the constant is a contiguous bit range that we can
+ handle by bit extract (low bits) or shifts (high bits). */
+ for (i = (CSKY_ISA_FEATURE (E2) ? 13 : 1); i < 32; i++)
+ {
+ if ((((HOST_WIDE_INT) 1) << i) - 1 == mask)
+ {
+ if (CSKY_ISA_FEATURE (2E3))
+ emit_insn (gen_cskyv2_extzv (operands[0], operands[1],
+ GEN_INT (i), const0_rtx));
+ else
+ {
+ rtx shift = GEN_INT (32 - i);
+ rtx reg = (reload_completed
+ ? operands[0] : gen_reg_rtx (SImode));
+
+ emit_insn (gen_ashlsi3 (reg, operands[1], shift));
+ emit_insn (gen_lshrsi3 (operands[0], reg, shift));
+ }
+ return true;
+ }
+ else if ((((HOST_WIDE_INT) 1) << i) - 1 == ~mask)
+ {
+ rtx shift = GEN_INT (i);
+ rtx reg = (reload_completed
+ ? operands[0] : gen_reg_rtx (SImode));
+
+ emit_insn (gen_lshrsi3 (reg, operands[1], shift));
+ emit_insn (gen_ashlsi3 (operands[0], reg, shift));
+ return true;
+ }
+ }
+
+ /* If the constant is a negative number, it seems better to use
+ andn and copy the NOT_VALUE to a register instead of the
+ original value, since the NOT_VALUE is always smaller and thus
+ more likely to be representable as a small constant.
+ This transformation can only be done before reload because
+ it requires a temporary. Hopefully register allocation can get
+ rid of the extra move required for CK801. */
+ if (!reload_completed && INTVAL (operands[2]) < 0)
+ {
+ rtx reg = copy_to_mode_reg (SImode, not_value);
+
+ if (CSKY_ISA_FEATURE (E2))
+ emit_insn (gen_cskyv2_andnsi3 (operands[0], reg, operands[1]));
+ else
+ {
+ emit_move_insn (operands[0], operands[1]);
+ emit_insn (gen_ck801_andnsi3 (operands[0], reg, operands[0]));
+ }
+ return true;
+ }
+
+ /* If the above ways are all not working, move the constant
+ to a register. We can clobber operands[0] as it is
+ marked earlyclobber in the insn constraints, but then we have to
+ swap operands 1 and 2 to match the constraints on the 2-operand
+ 16-bit and instruction. */
+ if (reload_completed)
+ {
+ emit_move_insn (operands[0], operands[2]);
+ operands[2] = operands[1];
+ operands[1] = operands[0];
+ }
+ else
+ operands[2] = copy_to_mode_reg (SImode, operands[2]);
+ return false;
+}
+
+/* Split operands for an IOR expression when OPERANDS[2] is a constant.
+ Note operands[0] is marked earlyclobber in this case and can be
+ overwritten. Return true if "DONE", false otherwise. */
+bool
+csky_split_ior (rtx *operands)
+{
+ HOST_WIDE_INT mask = INTVAL (operands[2]);
+ int i;
+
+ /* All zeros or all ones can be handled by a move instruction. */
+ if (mask == 0)
+ {
+ emit_move_insn (operands[0], operands[1]);
+ return true;
+ }
+ if (mask == -1)
+ {
+ emit_move_insn (operands[0], gen_int_mode (-1, SImode));
+ return true;
+ }
+
+ /* Check for constants that can be handled directly by the 32-bit ori
+ instruction. */
+ if (CSKY_ISA_FEATURE (E2) && csky_literal_I_operand (operands[2], SImode))
+ return false;
+
+ /* If there are only one or two 1 bits in the value, we can replace
+ the operation with bseti instructions to set those bits.
+ Note CK801 has only the 16-bit bclri that operates on a single
+ register, so we must count a move if we are post-reload. */
+ if (popcount_hwi (mask & 0xffffffff)
+ <= (reload_completed && !CSKY_ISA_FEATURE (E2) ? 1 : 2))
+ {
+ rtx input = operands[1];
+
+ if (!CSKY_ISA_FEATURE (E2))
+ {
+ emit_move_insn (operands[0], input);
+ input = operands[0];
+ }
+
+ for (i = 0; i < 32; i++)
+ if (mask & (1 << i))
+ {
+ emit_insn (gen_bseti (operands[0], input, GEN_INT (i)));
+ input = operands[0];
+ }
+ return true;
+ }
+
+ /* If the above ways are all not working, move the constant
+ to a register. We can clobber operands[0] as it is
+ marked earlyclobber in the insn constraints, but then we have to
+ swap operands 1 and 2 to match the constraints on the 2-operand
+ 16-bit ior instruction. */
+ if (reload_completed)
+ {
+ emit_move_insn (operands[0], operands[2]);
+ operands[2] = operands[1];
+ operands[1] = operands[0];
+ }
+ else
+ operands[2] = copy_to_mode_reg (SImode, operands[2]);
+ return false;
+}
+
+
+/* Split operands for an XOR expression when OPERANDS[2] is a constant.
+ Note operands[0] is marked earlyclobber in this case and can be
+ overwritten. Return true if "DONE", false otherwise. */
+bool
+csky_split_xor (rtx *operands)
+{
+ HOST_WIDE_INT mask = INTVAL (operands[2]);
+
+ /* All zeros can be turned into move instruction. */
+ if (mask == 0)
+ {
+ emit_move_insn (operands[0], operands[1]);
+ return true;
+ }
+
+ /* All ones can be turned into a bitwise not. */
+ if (mask == -1)
+ {
+ if (CSKY_ISA_FEATURE (E2))
+ emit_insn (gen_cskyv2_one_cmplsi2 (operands[0], operands[1]));
+ else
+ {
+ emit_move_insn (operands[0], operands[1]);
+ emit_insn (gen_ck801_one_cmplsi2 (operands[0], operands[0]));
+ }
+ return true;
+ }
+
+ /* Check for constants that can be handled directly by the 32-bit xori
+ instruction. */
+ if (CSKY_ISA_FEATURE (E2) && csky_arith_O_operand (operands[2], SImode))
+ return false;
+
+ /* If the above ways are all not working, move the constant
+ to a register. We can clobber operands[0] as it is
+ marked earlyclobber in the insn constraints, but then we have to
+ swap operands 1 and 2 to match the constraints on the 2-operand
+ 16-bit ior instruction. */
+ if (reload_completed)
+ {
+ emit_move_insn (operands[0], operands[2]);
+ operands[2] = operands[1];
+ operands[1] = operands[0];
+ }
+ else
+ operands[2] = copy_to_mode_reg (SImode, operands[2]);
+ return false;
+}
+
+
+/* Return true if X is an address form involving a symbol or label ref. */
+bool
+csky_symbolic_address_p (rtx x)
+{
+ switch (GET_CODE (x))
+ {
+ case SYMBOL_REF:
+ case LABEL_REF:
+ return 1;
+ case CONST:
+ x = XEXP (x, 0);
+ return ((GET_CODE (XEXP (x, 0)) == SYMBOL_REF
+ || GET_CODE (XEXP (x, 0)) == LABEL_REF)
+ && GET_CODE (XEXP (x, 1)) == CONST_INT);
+ default:
+ return 0;
+ }
+}
+
+
+/* Emit a comparison instruction.
+ Return true if an inverted comparison is generated. */
+
+bool
+csky_emit_compare (enum rtx_code code, rtx op0, rtx op1)
+{
+ bool invert;
+ rtx cc_reg = gen_rtx_REG (CCmode, CSKY_CC_REGNUM);
+
+ if (GET_CODE (op1) == CONST_INT)
+ {
+ HOST_WIDE_INT val = INTVAL (op1);
+
+ switch (code)
+ {
+ case GTU:
+ /* Unsigned (GTU 0) is the same as (NE 0); everything else is
+ converted below to LEU (reversed cmphs). */
+ if (val == 0)
+ code = NE;
+ /* Check whether (GTU A imm) can become (GEU A imm + 1). */
+ else if (TARGET_MINI_REGISTERS
+ ? CSKY_CONST_OK_FOR_J (val + 1)
+ : CSKY_CONST_OK_FOR_Uk (val + 1))
+ {
+ op1 = GEN_INT (val + 1);
+ code = GEU;
+ }
+ break;
+ /* Check whether (LE A imm) can become (LT A imm + 1),
+ or (GT A imm) can become (GE A imm + 1). */
+ case GT:
+ case LE:
+ if (TARGET_MINI_REGISTERS
+ ? CSKY_CONST_OK_FOR_J (val + 1)
+ : CSKY_CONST_OK_FOR_Uk (val + 1))
+ {
+ op1 = GEN_INT (val + 1);
+ code = code == LE ? LT : GE;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (CONSTANT_P (op1) && GET_CODE (op1) != CONST_INT)
+ op1 = force_reg (GET_MODE (op1), op1);
+
+ /* cmpnei: 0-31 (K immediate)
+ ti: 1-32 (J immediate, 0 using btsti x,31). */
+ invert = false;
+ switch (code)
+ {
+ /* Use inverted condition, cmpne. */
+ case EQ:
+ code = NE;
+ invert = true;
+ /* Fall through. */
+ /* Use normal condition, cmpne. */
+ case NE:
+ if (GET_CODE (op1) == CONST_INT
+ && (TARGET_MINI_REGISTERS
+ ? !csky_literal_K_operand (op1, SImode)
+ : !csky_literal_I_operand (op1, SImode)))
+ op1 = force_reg (SImode, op1);
+ break;
+
+ /* Use inverted condition, reversed cmplt. */
+ case LE:
+ code = GT;
+ invert = true;
+ /* Fall through. */
+ /* Use normal condition, reversed cmplt. */
+ case GT:
+ if (GET_CODE (op1) == CONST_INT)
+ op1 = force_reg (SImode, op1);
+ break;
+
+ /* Use inverted condition, cmplt. */
+ case GE:
+ code = LT;
+ invert = true;
+ /* Fall through. */
+ /* Use normal condition, cmplt. */
+ case LT:
+ /* covered by btsti x,31. */
+ if (GET_CODE (op1) == CONST_INT && INTVAL (op1) != 0
+ && (TARGET_MINI_REGISTERS
+ ? !csky_literal_J_operand (op1, SImode)
+ : !csky_literal_Uk_operand (op1, SImode)))
+ op1 = force_reg (SImode, op1);
+ break;
+
+ /* Use inverted condition, cmple. */
+ case GTU:
+ /* We coped with unsigned > 0 above. */
+ gcc_assert (GET_CODE (op1) != CONST_INT || INTVAL (op1) != 0);
+ code = LEU;
+ invert = true;
+ /* Fall through. */
+ /* Use normal condition, reversed cmphs. */
+ case LEU:
+ if (GET_CODE (op1) == CONST_INT && INTVAL (op1) != 0)
+ op1 = force_reg (SImode, op1);
+ break;
+
+ /* Use inverted condition, cmphs. */
+ case LTU:
+ code = GEU;
+ invert = true;
+ /* Fall through. */
+ /* Use normal condition, cmphs. */
+ case GEU:
+ if (GET_CODE (op1) == CONST_INT && INTVAL (op1) != 0
+ && (TARGET_MINI_REGISTERS
+ ? !csky_literal_J_operand (op1, SImode)
+ : !csky_literal_Uk_operand (op1, SImode)))
+ op1 = force_reg (SImode, op1);
+ break;
+
+ default:
+ break;
+ }
+
+ emit_insn (gen_rtx_SET (cc_reg,
+ gen_rtx_fmt_ee (code, CCmode, op0, op1)));
+ return invert;
+}
+
+/* Return true if push/pop can be used to save/restore all the registers
+ indicated by MASK. We currently don't attempt to handle situations where
+ some of the registers could be handled by push/pop and others saved and
+ restored individually. */
+
+static bool
+csky_can_use_pushpop (unsigned int mask)
+{
+ int i;
+ int end_reg;
+
+ if (!TARGET_PUSHPOP)
+ return false;
+
+ if (mask == 0)
+ return false;
+
+ /* Regs 0-3, 12-14, 18-27, 29-31 cannot be in the mask. */
+ if (mask & 0xeffc700f)
+ return false;
+
+ /* Regs in the range r4-r11 must be contiguous. */
+ for (end_reg = 0, i = 11; i >= 4; i--)
+ {
+ if (!end_reg && (mask & (1 << i)))
+ end_reg = i;
+ if (end_reg && !(mask & (1 << i)))
+ return false;
+ }
+
+ /* Likewise for regs in the range r16-r17. */
+ for (end_reg = 0, i = 17; i >= 16; i--)
+ {
+ if (!end_reg && (mask & (1 << i)))
+ end_reg = i;
+ if (end_reg && !(mask & (1 << i)))
+ return false;
+ }
+
+ return true;
+}
+
+
+/* Return true if store/load multiple instructions can be used to
+ save/restore at least some of the registers indicated by MASK.
+ Unlike the push/pop case, this does handle partial ranges.
+ Set *BR and *ER to the beginning and end (respectively) of the
+ register range that can be handled. */
+
+static bool
+csky_can_use_ldstm (int mask, int *br, int *er)
+{
+ int regno;
+ int begin_reg = 0, end_reg = 0;
+ int count = 0;
+
+ if (!TARGET_MULTIPLE_STLD)
+ return false;
+
+ /* We'll only handle registers in the range 4-11, the contiguous range
+ of caller-saved registers. Higher-numbered registers are handled
+ individually in addition to this, but we'll give up on doing ldstm
+ entirely if we need to save/restore the low-numbered EH registers. */
+ if (mask & 0xf)
+ return false;
+
+ for (regno = 4; regno <= 11; regno++)
+ {
+ if (mask & 1 << regno)
+ {
+ if (!begin_reg)
+ begin_reg = regno;
+ end_reg = regno;
+ count++;
+ }
+ else if (begin_reg)
+ break;
+ }
+
+ if (count >= CSKY_MIN_MULTIPLE_STLD && count <= CSKY_MAX_MULTIPLE_STLD)
+ {
+ if (br)
+ *br = begin_reg;
+ if (er)
+ *er = end_reg;
+ return true;
+ }
+ return false;
+}
+
+
+const char *
+csky_output_return_instruction (void)
+{
+ unsigned long func_type = get_csky_current_func_type ();
+
+ if (CSKY_FUNCTION_IS_NAKED (func_type))
+ return "";
+ if (CSKY_FUNCTION_IS_INTERRUPT (func_type))
+ return "ipop\n\tnir\n";
+ else
+ return "rts\n";
+}
+
+
+/* Adjust the stack pointer by OFFSET bytes. OFFSET is negative if this
+ is in the prologue, positive if in the epilogue. This may require
+ multiple instructions and/or use of CSKY_STACKADJUST_REGNUM as
+ a scratch register. Emit CFA notes as appropriate. */
+static void
+expand_csky_stack_adjust (int offset)
+{
+ rtx set;
+ rtx_insn *insn;
+ int size = (offset > 0 ? offset : -offset);
+
+ if (offset == 0)
+ return;
+
+ /* If OFFSET is too large for addi/subi, load it into
+ CSKY_STACKADJUST_REGNUM and use a register add/sub instead.
+ This case is not mentioned in the ABI documentation, but it is
+ supported by GDB prologue analysis provided that the instruction(s)
+ to initialize CSKY_STACKADJUST_REGNUM appear directly before
+ the sub. Depending on the value of OFFSET, this might be a
+ lrw instruction or the "tricks" used by csky_output_inline_const to
+ encode special-case integer constants. */
+ if (size > CSKY_MAX_SP_ADJUST * 2)
+ {
+ rtx tmp, dwarf;
+
+ /* We should have reserved the scratch register already in
+ csky_layout_stack_frame. */
+ gcc_assert (cfun->machine->reg_size != 0
+ && (cfun->machine->reg_mask
+ & (1 << CSKY_STACKADJUST_REGNUM)));
+
+ /* Prevent the optimizer from reordering these instructions to
+ keep GDB happy. */
+ if (!flag_sched_prolog)
+ emit_insn (gen_blockage ());
+
+ tmp = gen_rtx_REG (SImode, CSKY_STACKADJUST_REGNUM);
+ emit_move_insn (tmp, GEN_INT (size));
+
+ if (offset > 0)
+ set = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp);
+ else
+ set = gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp);
+ insn = emit_insn (set);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ dwarf = gen_rtx_SET (stack_pointer_rtx,
+ plus_constant (Pmode, stack_pointer_rtx, offset));
+ add_reg_note (insn, REG_FRAME_RELATED_EXPR, dwarf);
+
+ /* More make GDB happy. */
+ if (!flag_sched_prolog)
+ emit_insn (gen_blockage ());
+ }
+
+ /* Use one or two addi or subi insns to adjust stack. */
+ else
+ while (size)
+ {
+ int delta = (size > CSKY_MAX_SP_ADJUST
+ ? CSKY_MAX_SP_ADJUST : size);
+
+ if (offset > 0)
+ set = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+ GEN_INT (delta));
+ else
+ set = gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
+ GEN_INT (delta));
+ insn = emit_insn (set);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ size -= delta;
+ }
+}
+
+
+/* Generate and emit an insn that we will recognize as a push_multi.
+ Unfortunately, since this insn does not reflect very well the actual
+ semantics of the operation, we need to annotate the insn for the benefit
+ of DWARF2 frame unwind information. DWARF_REGS_MASK is a subset of
+ MASK for registers that should be annotated for DWARF2 frame unwind
+ information. */
+
+static rtx
+emit_csky_regs_push (unsigned long mask)
+{
+ int num_regs = 0;
+ int i, j;
+ rtx par;
+ rtx dwarf;
+ rtx tmp;
+ int dwarf_par_index;
+
+ for (i = 0; i < CSKY_NGPR_REGS; i++)
+ {
+ if (mask & (1 << i))
+ num_regs++;
+ }
+
+ /* The reg range for push is:r4-r11,r15-r17,r28. */
+ gcc_assert (num_regs && num_regs <= 12);
+
+ /* For the body of the insn we are going to generate an UNSPEC in
+ parallel with several USEs. This allows the insn to be recognized
+ by the push_multi pattern in the csky.md file.
+
+ The body of the insn looks something like this:
+
+ (parallel [
+ (set (mem:BLK (pre_modify:SI (reg:SI sp)
+ (const_int:SI <num>)))
+ (unspec:BLK [(reg:SI r4)] UNSPEC_PUSHPOP_MULT))
+ (use (reg:SI XX))
+ (use (reg:SI YY))
+ ...
+ ])
+
+ For the frame note however, we try to be more explicit and actually
+ show each register being stored into the stack frame, plus a (single)
+ decrement of the stack pointer. We do it this way in order to be
+ friendly to the stack unwinding code, which only wants to see a single
+ stack decrement per instruction. The RTL we generate for the note looks
+ something like this:
+
+ (sequence [
+ (set (reg:SI sp) (plus:SI (reg:SI sp) (const_int -20)))
+ (set (mem:SI (reg:SI sp)) (reg:SI r4))
+ (set (mem:SI (plus:SI (reg:SI sp) (const_int 4))) (reg:SI XX))
+ (set (mem:SI (plus:SI (reg:SI sp) (const_int 8))) (reg:SI YY))
+ ...
+ ])
+
+ FIXME:: In an ideal world the PRE_MODIFY would not exist and
+ instead we'd have a parallel expression detailing all
+ the stores to the various memory addresses so that debug
+ information is more up-to-date. Remember however while writing
+ this to take care of the constraints with the push instruction.
+
+ Note also that this has to be taken care of for the VFP registers.
+
+ For more see PR43399. */
+
+ par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_regs));
+ dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (num_regs + 1));
+ dwarf_par_index = 1;
+
+ for (i = 0; i < CSKY_NGPR_REGS; i++)
+ if (mask & (1 << i))
+ {
+ rtx reg = gen_rtx_REG (SImode, i);
+ rtx addr = plus_constant (Pmode, stack_pointer_rtx, -4 * num_regs);
+ tmp = gen_frame_mem (BLKmode,
+ gen_rtx_PRE_MODIFY (Pmode,
+ stack_pointer_rtx, addr));
+ XVECEXP (par, 0, 0)
+ = gen_rtx_SET (tmp,
+ gen_rtx_UNSPEC (BLKmode,
+ gen_rtvec (1, reg),
+ UNSPEC_PUSHPOP_MULT));
+ tmp = gen_rtx_SET (gen_frame_mem (SImode, stack_pointer_rtx),
+ reg);
+ RTX_FRAME_RELATED_P (tmp) = 1;
+ XVECEXP (dwarf, 0, dwarf_par_index++) = tmp;
+
+ break;
+ }
+
+ for (j = 1, i++; j < num_regs; i++)
+ if (mask & (1 << i))
+ {
+ rtx reg = gen_rtx_REG (SImode, i);
+ rtx addr = plus_constant (Pmode, stack_pointer_rtx, 4 * j);
+ tmp = gen_rtx_SET (gen_frame_mem (SImode, addr), reg);
+ RTX_FRAME_RELATED_P (tmp) = 1;
+ XVECEXP (par, 0, j) = gen_rtx_USE (VOIDmode, reg);
+ XVECEXP (dwarf, 0, dwarf_par_index++) = tmp;
+ j++;
+ }
+
+ par = emit_insn (par);
+
+ tmp = gen_rtx_SET (stack_pointer_rtx,
+ plus_constant (Pmode, stack_pointer_rtx, -4 * num_regs));
+ RTX_FRAME_RELATED_P (tmp) = 1;
+ XVECEXP (dwarf, 0, 0) = tmp;
+
+ add_reg_note (par, REG_FRAME_RELATED_EXPR, dwarf);
+ RTX_FRAME_RELATED_P (par) = 1;
+
+ return par;
+}
+
+
+/* Generate and emit an insn pattern that we will recognize as a pop_multi.
+ SAVED_REGS_MASK shows which registers need to be restored.
+
+ Unfortunately, since this insn does not reflect very well the actual
+ semantics of the operation, we need to annotate the insn for the benefit
+ of DWARF2 frame unwind information. */
+
+static void
+emit_csky_regs_pop (unsigned long mask)
+{
+ int num_regs = 0;
+ int i, j;
+ rtx par;
+
+ for (i = 0; i < CSKY_NGPR_REGS; i++)
+ if (mask & (1 << i))
+ num_regs++;
+
+ /* The reg range for push is:r4-r11,r15-r17,r28. */
+ gcc_assert (num_regs && num_regs <= 12);
+
+ /* The first element is (return),
+ the second element is
+ (set (reg:SI 'first reg number')
+ (unspec:SI [(mem)] UNSPEC_PUSHPOP_MULT),
+ the rest elements is (use (reg:SI 'rest reg number')),
+ so the length should be number of register to be poped
+ plus one. */
+ par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_regs + 1));
+
+ XVECEXP (par, 0, 0) = ret_rtx;
+
+ for (i = 0; i < CSKY_NGPR_REGS; i++)
+ if (mask & (1 << i))
+ {
+ rtx reg = gen_rtx_REG (SImode, i);
+ rtx addr = plus_constant (Pmode, stack_pointer_rtx, 4 * num_regs);
+ rtx tmp = gen_frame_mem (SImode,
+ gen_rtx_POST_MODIFY (Pmode,
+ stack_pointer_rtx, addr));
+ XVECEXP (par, 0, 1)
+ = gen_rtx_SET (reg,
+ gen_rtx_UNSPEC (SImode,
+ gen_rtvec (1, tmp),
+ UNSPEC_PUSHPOP_MULT));
+ break;
+ }
+
+ for (j = 2, i++; j < (num_regs + 1); i++)
+ if (mask & (1 << i))
+ {
+ rtx reg = gen_rtx_REG (SImode, i);
+ XVECEXP (par, 0, j) = gen_rtx_USE (VOIDmode, reg);
+ j++;
+ }
+
+ par = emit_jump_insn (par);
+}
+
+
+/* Generate the function prologue. */
+
+void
+csky_expand_prologue (void)
+{
+ rtx_insn *insn;
+ unsigned long func_type = get_csky_current_func_type ();
+ unsigned int reg_mask;
+ int reg_size;
+
+ if (CSKY_FUNCTION_IS_NAKED (func_type))
+ {
+ if (flag_stack_usage_info)
+ current_function_static_stack_size = 0;
+ return;
+ }
+
+ csky_layout_stack_frame ();
+ reg_mask = cfun->machine->reg_mask;
+ reg_size = cfun->machine->reg_size;
+
+ /* Adjust stack pointer past argument overflow area. */
+ if (cfun->machine->arg_size != 0)
+ {
+ int offset = cfun->machine->arg_size;
+ expand_csky_stack_adjust (- offset);
+
+ /* If we have a parameter passed partially in regs and partially
+ in memory, the registers will have been stored to memory already
+ in function.c. So we only need to copy varargs from registers
+ to stack. */
+ if (cfun->machine->uses_anonymous_args)
+ {
+ int rn = CSKY_FIRST_PARM_REGNUM + CSKY_NPARM_REGS - 1;
+ for (offset -= 4; offset >= 0; offset -= 4, rn--)
+ {
+ rtx dst = gen_frame_mem (SImode,
+ plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset));
+ insn = emit_move_insn (dst, gen_rtx_REG (SImode, rn));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ }
+ }
+
+ /* Push caller-saved registers to stack. */
+ if (csky_can_use_pushpop (reg_mask))
+ emit_csky_regs_push (reg_mask);
+ else if (reg_size)
+ {
+ int sreg = -1, ereg = -1;
+ bool stm_p = csky_can_use_ldstm (reg_mask, &sreg, &ereg);
+ int stm_regs = stm_p ? ereg - sreg + 1 : 0;
+ int stm_size = stm_regs * 4;
+
+ /* First adjust the SP to the low end of the register save area. */
+ expand_csky_stack_adjust (- reg_size);
+
+ /* Emit individual register saves. Even if we are going to emit an
+ stm, we may need to save individual registers above that too. */
+ if (reg_size > stm_size)
+ {
+ int offset = reg_size - 4;
+ int regno = 31;
+ for ( ; regno > ereg; regno--)
+ if (reg_mask & (1 << regno))
+ {
+ rtx dst = gen_rtx_MEM (SImode,
+ plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset));
+ rtx insn = emit_insn (gen_movsi (dst,
+ gen_rtx_REG (SImode, regno)));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ if (offset == stm_size)
+ break;
+ offset -= 4;
+ }
+ }
+
+ /* If possible, emit a stm to do a bulk store of sequential
+ registers to the stack. Note that it is an error in the ABI
+ documentation that it doesn't list stm as a valid prologue
+ instruction. */
+ if (stm_p)
+ {
+ rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (stm_regs));
+ int regno, slot;
+ for (regno = sreg, slot = 0; regno <= ereg; regno++, slot++)
+ {
+ rtx reg = gen_rtx_REG (SImode, regno);
+ rtx addr = plus_constant (Pmode, stack_pointer_rtx, slot * 4);
+ rtx set = gen_rtx_SET (gen_frame_mem (SImode, addr), reg);
+ RTX_FRAME_RELATED_P (set) = 1;
+ XVECEXP (par, 0, slot) = set;
+ }
+ insn = emit_insn (par);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ }
+
+ /* Initialize hard frame pointer, if necessary. It points at the base
+ of the register save area. */
+ if (frame_pointer_needed)
+ {
+ insn = emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ /* Reserve stack space for locals and outgoing args. */
+ expand_csky_stack_adjust (- cfun->machine->reg_offset);
+
+ /* Put the GOT address in reg_gb for PIC, using R13 as a scratch.
+ See section 4.7.1 in the ABI documentation,
+ "Function Prologue for PIC". */
+ if (flag_pic && (reg_mask & (1 << PIC_OFFSET_TABLE_REGNUM)))
+ {
+ rtx l1 = gen_label_rtx ();
+ rtx grs_label = gen_rtx_LABEL_REF (SImode, l1);
+ rtx reg_gb = gen_rtx_REG (SImode, PIC_OFFSET_TABLE_REGNUM);
+ rtx reg_temp = gen_rtx_REG (SImode, 13);
+
+ rtx tmp0_unspec = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (1, grs_label),
+ UNSPEC_PIC_SYMBOL_GOTPC_GRS);
+ rtx tmp1_unspec = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (1, grs_label),
+ UNSPEC_PIC_SYMBOL_GOTPC);
+
+ emit_insn (gen_prologue_get_pc (tmp0_unspec));
+ emit_move_insn (reg_temp, tmp1_unspec);
+ emit_insn (gen_addsi3 (reg_gb, reg_gb, reg_temp));
+ }
+
+ if (flag_stack_usage_info)
+ current_function_static_stack_size = cfun->machine->frame_size;
+
+ if (!flag_sched_prolog)
+ emit_insn (gen_blockage ());
+}
+
+void
+csky_expand_epilogue (void)
+{
+ unsigned long func_type = get_csky_current_func_type ();
+ unsigned int reg_mask;
+ int reg_size;
+ int adjust;
+ rtx_insn *insn;
+
+ if (!flag_sched_prolog)
+ emit_insn (gen_blockage ());
+
+ if (CSKY_FUNCTION_IS_NAKED (func_type))
+ {
+ emit_jump_insn (gen_simple_return ());
+ return;
+ }
+
+ /* Get the frame information. */
+ csky_layout_stack_frame ();
+ reg_mask = cfun->machine->reg_mask;
+ reg_size = cfun->machine->reg_size;
+ adjust = reg_size + cfun->machine->arg_size;
+
+ /* Restore the SP to the base of the register save area. */
+ if (frame_pointer_needed)
+ {
+ insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ else
+ expand_csky_stack_adjust (cfun->machine->reg_offset);
+
+ /* Restore the callee-saved registers. */
+ if (csky_can_use_pushpop (reg_mask)
+ && cfun->machine->arg_size == 0
+ && !CSKY_FUNCTION_IS_INTERRUPT (func_type)
+ && !crtl->calls_eh_return)
+ {
+ /* Pop includes an implicit return, so we are done. */
+ emit_csky_regs_pop (reg_mask);
+ return;
+ }
+ else if (reg_size)
+ {
+ int sreg = -1, ereg = -1;
+ bool ldm_p = csky_can_use_ldstm (reg_mask, &sreg, &ereg);
+ int ldm_regs = ldm_p ? ereg - sreg + 1 : 0;
+ int ldm_size = ldm_regs * 4;
+
+ /* Emit individual register loads. Even if we are going to emit an
+ ldm, we may need to load individual registers above that too. */
+ if (reg_size > ldm_size)
+ {
+ int offset = reg_size - 4;
+ int regno = 31;
+ for ( ; regno > ereg; regno--)
+ if (reg_mask & (1 << regno))
+ {
+ rtx src = gen_frame_mem (SImode,
+ plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset));
+ rtx reg = gen_rtx_REG (SImode, regno);
+ insn = emit_move_insn (reg, src);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ add_reg_note (insn, REG_CFA_RESTORE, reg);
+ if (offset == ldm_size)
+ break;
+ offset -= 4;
+ }
+ }
+
+ /* If possible, emit a ldm to do a bulk load of sequential
+ registers from the stack. */
+ if (ldm_p)
+ {
+ rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (ldm_regs));
+ int regno, slot;
+ for (regno = sreg, slot = 0; regno <= ereg; regno++, slot++)
+ {
+ rtx reg = gen_rtx_REG (SImode, regno);
+ rtx addr = plus_constant (Pmode, stack_pointer_rtx, slot * 4);
+ rtx set = gen_rtx_SET (reg, gen_frame_mem (SImode, addr));
+ XVECEXP (par, 0, slot) = set;
+ }
+ insn = emit_insn (par);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ for (regno = sreg; regno <= ereg; regno++)
+ {
+ rtx reg = gen_rtx_REG (SImode, regno);
+ add_reg_note (insn, REG_CFA_RESTORE, reg);
+ }
+ }
+ }
+
+ /* Emit the final stack pointer adjustment to deallocate the saved
+ registers and incoming argument area. */
+ expand_csky_stack_adjust (adjust);
+
+ /* Extra stack adjustment for exception handler return. */
+ if (crtl->calls_eh_return)
+ emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+ EH_RETURN_STACKADJ_RTX));
+
+ /* Now we can return. */
+ emit_jump_insn (gen_simple_return ());
+}
+
+
+static void
+csky_output_function_prologue (FILE *f)
+{
+ unsigned long func_type = get_csky_current_func_type ();
+
+ switch ((int) CSKY_FUNCTION_TYPE (func_type))
+ {
+ default:
+ case CSKY_FT_NORMAL:
+ break;
+ case CSKY_FT_INTERRUPT:
+ {
+ asm_fprintf (f, "\t# Interrupt Service Routine.\n");
+ asm_fprintf (f, "\tnie\n\tipush\n");
+ break;
+ }
+ case CSKY_FT_FIQ:
+ asm_fprintf (f, "\t# Fast Interrupt Service Routine.\n");
+ break;
+ case CSKY_FT_EXCEPTION:
+ asm_fprintf (f, "\t# CSKY Exception Handler.\n");
+ break;
+ case CSKY_FT_NAKED:
+ asm_fprintf (f, "\t# Naked Function: prologue and epilogue \
+ provided by programmer.\n");
+ return;
+ }
+
+ csky_layout_stack_frame ();
+
+ /* Generate .stack_size function-name, size for callgraph;
+ the default stack size is 0. */
+ if (TARGET_STACK_SIZE && cfun->machine->frame_size > 0)
+ {
+ gcc_assert (current_function_decl != NULL);
+ const char *func_name =
+ IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
+ if (func_name[0] == '*')
+ asm_fprintf (f, "\t.stack_size %s, %d\n",
+ &func_name[1], cfun->machine->frame_size);
+ else
+ asm_fprintf (f, "\t.stack_size %s, %d\n",
+ func_name, cfun->machine->frame_size);
+ }
+}
+
+
+static void
+csky_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED)
+{
+
+}
+
+
+/* Helper for csky_eh_return splitter: store the call frame exception
+ handler address in lr. */
+void
+csky_set_eh_return_address (rtx source, rtx scratch)
+{
+ HOST_WIDE_INT delta = 0;
+ rtx basereg, addr;
+ unsigned int reg_mask;
+
+ csky_layout_stack_frame ();
+ reg_mask = cfun->machine->reg_mask;
+
+ if (reg_mask & (1 << CSKY_LR_REGNUM))
+ {
+ /* Find LR in the stack frame. */
+ int i = 0;
+
+ if (frame_pointer_needed)
+ {
+ basereg = frame_pointer_rtx;
+ delta = 0;
+ }
+ else
+ {
+ basereg = stack_pointer_rtx;
+ delta = cfun->machine->reg_offset;
+ }
+
+ /* At this point, (basereg + delta) points at the low end of
+ the reg save area. Regs are saved sequentially from low
+ to high from this address. */
+ for (i = 0; i < CSKY_LR_REGNUM; i++)
+ if (reg_mask & (1 << i))
+ delta += 4;
+
+ if ((CSKY_TARGET_ARCH (CK801) && delta >= CSKY_LD16_MAX_OFFSET (Pmode))
+ || delta >= CSKY_LD32_MAX_OFFSET (Pmode))
+ {
+ emit_insn (gen_movsi (scratch, GEN_INT (delta)));
+ emit_insn (gen_addsi3 (scratch, scratch, basereg));
+ addr = scratch;
+ }
+ else
+ addr = plus_constant (Pmode, basereg, delta);
+ emit_move_insn (gen_frame_mem (Pmode, addr), source);
+ }
+ else
+ emit_move_insn (gen_rtx_REG (Pmode, CSKY_LR_REGNUM), source);
+}
+
+/* Return TRUE if X references a SYMBOL_REF. */
+
+bool
+csky_symbol_mentioned_p (rtx x)
+{
+ const char *fmt;
+ int i;
+
+ if (GET_CODE (x) == SYMBOL_REF)
+ return true;
+
+ fmt = GET_RTX_FORMAT (GET_CODE (x));
+ for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'E')
+ {
+ int j;
+
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+ if (csky_symbol_mentioned_p (XVECEXP (x, i, j)))
+ return true;
+ }
+ else if (fmt[i] == 'e' && csky_symbol_mentioned_p (XEXP (x, i)))
+ return true;
+ }
+ return false;
+}
+
+
+/* Return TRUE if X references a LABEL_REF. */
+
+bool
+csky_label_mentioned_p (rtx x)
+{
+ const char *fmt;
+ int i;
+
+ if (GET_CODE (x) == LABEL_REF)
+ return true;
+
+ fmt = GET_RTX_FORMAT (GET_CODE (x));
+ for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'E')
+ {
+ int j;
+
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+ if (csky_label_mentioned_p (XVECEXP (x, i, j)))
+ return true;
+ }
+ else if (fmt[i] == 'e' && csky_label_mentioned_p (XEXP (x, i)))
+ return true;
+ }
+
+ return false;
+}
+
+
+static bool
+tls_unspec_mentioned_p (rtx x)
+{
+ switch (GET_CODE (x))
+ {
+ case CONST:
+ return tls_unspec_mentioned_p (XEXP (x, 0));
+
+ case UNSPEC:
+ if (XINT (x, 1) == UNSPEC_TLS)
+ return true;
+
+ /* Fall through. */
+ default:
+ return false;
+ }
+}
+
+
+/* Implement LEGITIMATE_PIC_OPERAND_P. */
+bool
+csky_legitimate_pic_operand_p (rtx x)
+{
+ if (tls_unspec_mentioned_p (x))
+ return true;
+ if (csky_symbol_mentioned_p (x) || csky_label_mentioned_p (x))
+ return false;
+ return true;
+}
+
+rtx
+csky_legitimize_pic_address (rtx orig, rtx reg, bool gotrel_p)
+{
+ rtx pic_reg = gen_rtx_REG (SImode, PIC_OFFSET_TABLE_REGNUM);
+ bool optimize_p = false;
+
+ if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
+ {
+ rtx pic_ref, address, rtx_tmp;
+ rtx insn;
+ rtx pic_reg = gen_rtx_REG (SImode, PIC_OFFSET_TABLE_REGNUM);
+ int subregs = 0;
+
+ if (reg == 0)
+ {
+ gcc_assert (can_create_pseudo_p ());
+ reg = gen_reg_rtx (Pmode);
+ subregs = 1;
+ }
+
+ if (subregs)
+ address = gen_reg_rtx (Pmode);
+ else
+ address = reg;
+
+ if (GET_CODE (orig) == SYMBOL_REF && !SYMBOL_REF_LOCAL_P (orig))
+ {
+ /* When gotrel_p generate sym@GOT, otherwise generate sym@PLT. */
+ rtx_tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, orig),
+ (gotrel_p
+ ? UNSPEC_PIC_SYMBOL_GOT
+ : UNSPEC_PIC_SYMBOL_PLT));
+ optimize_p = gotrel_p;
+ if (flag_pic != 1)
+ {
+ emit_move_insn (address, rtx_tmp);
+ rtx_tmp = gen_rtx_MULT (Pmode, address, GEN_INT (1));
+ }
+ pic_ref = gen_const_mem (Pmode,
+ gen_rtx_PLUS (Pmode, pic_reg, rtx_tmp));
+ }
+ else
+ {
+ /* bsr symbol */
+ if (flag_pic == 1 && !gotrel_p)
+ {
+ pic_ref = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (1, orig),
+ UNSPEC_PIC_SYMBOL_BSR);
+ return pic_ref;
+ }
+ /* grs rx, symbol */
+ else if (flag_pic == 1 && (GET_CODE (orig) == SYMBOL_REF)
+ && SYMBOL_REF_FUNCTION_P (orig))
+ {
+ pic_ref = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (1, orig),
+ UNSPEC_PIC_SYMBOL_GRS);
+ return pic_ref;
+ }
+ /* lrw rx, symbol@GOTOFF; add rx, rx, gb */
+ else
+ {
+ rtx_tmp = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (1, orig),
+ UNSPEC_PIC_SYMBOL_GOTOFF);
+ emit_move_insn (address, rtx_tmp);
+ pic_ref = gen_rtx_PLUS (Pmode, address, pic_reg);
+ optimize_p = true;
+ }
+ }
+
+ insn = emit_move_insn (reg, pic_ref);
+ /* Put a REG_EQUAL note on this insn,
+ so that it can be optimized by loop. */
+ if (optimize_p)
+ set_unique_reg_note (insn, REG_EQUAL, orig);
+
+ return reg;
+ }
+ else if (GET_CODE (orig) == CONST)
+ {
+ rtx base, offset;
+
+ if (GET_CODE (XEXP (orig, 0)) == PLUS
+ && XEXP (XEXP (orig, 0), 1) == pic_reg)
+ return orig;
+
+ if (reg == 0)
+ {
+ gcc_assert (can_create_pseudo_p ());
+ reg = gen_reg_rtx (Pmode);
+ }
+
+ gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
+
+ base = csky_legitimize_pic_address (XEXP (XEXP (orig, 0), 0),
+ reg, gotrel_p);
+ offset = csky_legitimize_pic_address (XEXP (XEXP (orig, 0), 1),
+ base == reg ? 0 : reg, gotrel_p);
+
+ if (GET_CODE (offset) == CONST_INT)
+ return plus_constant (Pmode, base, INTVAL (offset));
+
+ return gen_rtx_PLUS (Pmode, base, offset);
+ }
+
+ return orig;
+}
+
+
+/* Functions to output assembly code for a function call. */
+
+char *
+csky_output_call (rtx *operands, int index)
+{
+ static char buffer[20];
+ rtx addr = operands[index];
+
+ if (REG_P (addr))
+ sprintf (buffer, "jsr\t%%%d", index);
+ else if (flag_pic && (GET_CODE (addr) == UNSPEC))
+ sprintf (buffer, "bsr\t%%%d", index);
+ else
+ sprintf (buffer, "jbsr\t%%%d", index);
+
+ return buffer;
+}
+
+
+/* Worker function for TARGET_ASM_TRAMPOLINE_TEMPLATE.
+ Output assembler code for a block containing the constant parts
+ of a trampoline, leaving space for the variable parts.
+ Note that STATIC_CHAIN_REGNUM is t1 (aka r12) on ck801 and
+ t1 (r13) otherwise. */
+
+static void
+csky_asm_trampoline_template (FILE *f)
+{
+ if (CSKY_ISA_FEATURE (2E3))
+ {
+ fprintf (f, "\tlrw\t%s, [.Lstatic_chain]\n",
+ reg_names[STATIC_CHAIN_REGNUM]);
+ fprintf (f, "\tjmpi\t[.Lfunc_address]\n");
+ /* 2 32-bit insns = 8 bytes. */
+ }
+ else if (CSKY_TARGET_ARCH (CK801))
+ {
+ /* It's hard to provide general support for trampolines on this
+ core. We need a register other than the one holding the
+ static chain (r13) to hold the function pointer for the
+ indirect jump to it. But ck801 has such a limited register set
+ there is no other call-clobbered scratch register available -- in
+ particular, this core does not have r12, which we use for the
+ ck802 case below. If we use a callee-saved register like r4,
+ saving the old value on the stack screws up the stack frame
+ if there are overflow arguments pushed on the stack
+ by the caller. In theory we could test for that and handle
+ limited cases with parameters that all fit in r0-r3 with no
+ stack overflow, but punt for now. */
+ sorry ("Nested function trampolines not supported on CK801.");
+ }
+ else
+ {
+ fprintf (f, "\tlrw\t%s, [.Lfunc_address]\n",
+ reg_names[CSKY_T1_REGNUM]);
+ fprintf (f, "\tlrw\t%s, [.Lstatic_chain]\n",
+ reg_names[STATIC_CHAIN_REGNUM]);
+ fprintf (f, "\tjmp\t%s\n",
+ reg_names[CSKY_T1_REGNUM]);
+ /* To align constant pool on a word boundary. */
+ fprintf (f, "\t.align 2\n");
+ /* 2 32-bit lrw insns + 16-bit jump + 16-bit pad = 12 bytes. */
+ }
+
+ fprintf (f, ".Lstatic_chain:\n");
+ fprintf (f, "\t.long 0\n");
+ fprintf (f, ".Lfunc_address:\n");
+ fprintf (f, "\t.long 0\n");
+ /* 2 words of constant pool = 8 bytes. */
+}
+
+/* Worker function for TARGET_TRAMPOLINE_INIT. */
+
+static void
+csky_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
+{
+ rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
+ rtx mem, a_tramp;
+ int pool = TRAMPOLINE_SIZE - 8;
+
+ emit_block_move (m_tramp, assemble_trampoline_template (),
+ GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
+
+ mem = adjust_address (m_tramp, SImode, pool);
+ emit_move_insn (mem, chain_value);
+ mem = adjust_address (m_tramp, SImode, pool + 4);
+ emit_move_insn (mem, fnaddr);
+
+ a_tramp = XEXP (m_tramp, 0);
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"),
+ LCT_NORMAL, VOIDmode, a_tramp, Pmode,
+ plus_constant (Pmode, a_tramp, TRAMPOLINE_SIZE), Pmode);
+}
+
+
+/* Emit a comparison insn for float values.
+ Return true if the comparison is inverted. */
+
+bool
+csky_emit_compare_float (enum rtx_code code, rtx op0, rtx op1)
+{
+ rtx cc_reg = gen_rtx_REG (CCmode, CSKY_CC_REGNUM);
+ bool invert;
+ machine_mode mode = GET_MODE (op1);
+
+ if (op1 != CONST0_RTX (mode))
+ op1 = force_reg (mode, op1);
+
+ invert = false;
+ switch (code)
+ {
+ case EQ:
+ code = NE;
+ invert = true;
+ break;
+
+ case NE:
+ break;
+ case LE:
+ if (op1 == CONST0_RTX (mode))
+ op1 = force_reg (mode, op1);
+ break;
+ case GT:
+ if (op1 == CONST0_RTX (mode))
+ op1 = force_reg (mode, op1);
+ break;
+ case GE:
+ break;
+ case LT:
+ if (op1 == CONST0_RTX (mode))
+ {
+ code = GE;
+ invert = true;
+ }
+ break;
+ case UNORDERED:
+ break;
+ case ORDERED:
+ code = UNORDERED;
+ invert = true;
+ break;
+
+ default:
+ break;
+ }
+
+ emit_insn (gen_rtx_SET (cc_reg, gen_rtx_fmt_ee (code, CCmode, op0, op1)));
+
+ return invert;
+}
+
+/* Support for the Q memory constraint. Returns true if OP is a MEM RTX
+ with an address consisting of base + index or base + displacement. */
+bool
+csky_valid_fpuv2_mem_operand (rtx op)
+{
+ struct csky_address addr;
+
+ if (GET_CODE (op) != MEM)
+ return false;
+
+ if (!decompose_csky_address (XEXP (op, 0), &addr))
+ return false;
+
+ /* Verify base register. */
+ if (!is_csky_address_register_rtx_p (addr.base, 0))
+ return false;
+
+ /* Verify index operand. */
+ if (addr.index)
+ {
+ if (!is_csky_address_register_rtx_p (addr.index, 0))
+ return false;
+
+ if (addr.scale == 1 || addr.scale == 2 || addr.scale == 4
+ || addr.scale == 8)
+ return true;
+
+ return false;
+ }
+ /* Verify disp operand. */
+ else if (addr.disp)
+ {
+ rtx disp = addr.disp;
+
+ if (!CONST_INT_P (disp))
+ return false;
+
+ if (((unsigned) INTVAL (disp) % 4) == 0
+ && (unsigned) INTVAL (disp) <= (unsigned) 1020)
+ return true;
+
+ return false;
+ }
+ return true;
+}
+
+
+/* Returns the (interrupt) function type of the current
+ function, or CSKY_FT_UNKNOWN if the type cannot be determined. */
+
+static unsigned long
+csky_isr_value (tree argument)
+{
+ const isr_attribute_entry *ptr;
+ const char *arg;
+
+ /* No argument - default to IRQ. */
+ if (argument == NULL_TREE)
+ return CSKY_FT_ISR;
+
+ /* Get the value of the argument. */
+ if (TREE_VALUE (argument) == NULL_TREE
+ || TREE_CODE (TREE_VALUE (argument)) != STRING_CST)
+ return CSKY_FT_UNKNOWN;
+
+ arg = TREE_STRING_POINTER (TREE_VALUE (argument));
+
+ /* Check it against the list of known arguments. */
+ for (ptr = isr_attribute_map; ptr->arg != NULL; ptr++)
+ if (strcmp (arg, ptr->arg) == 0)
+ return ptr->return_value;
+
+ /* An unrecognized interrupt type. */
+ return CSKY_FT_UNKNOWN;
+}
+
+/* Handle an attribute requiring a FUNCTION_DECL;
+ arguments as in struct attribute_spec.handler. */
+
+static tree
+csky_handle_fndecl_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute only applies to functions",
+ name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle an "interrupt" or "isr" attribute;
+ arguments as in struct attribute_spec.handler. */
+
+static tree
+csky_handle_isr_attribute (tree *node, tree name, tree args, int flags,
+ bool *no_add_attrs)
+{
+
+ if (!TARGET_ISTACK)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored without -mistack",
+ name);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ if (DECL_P (*node))
+ {
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute only applies to functions",
+ name);
+ *no_add_attrs = true;
+ }
+ }
+ else
+ {
+ if (TREE_CODE (*node) == FUNCTION_TYPE
+ || TREE_CODE (*node) == METHOD_TYPE)
+ {
+ if (csky_isr_value (args) == CSKY_FT_UNKNOWN)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+ }
+ else if (TREE_CODE (*node) == POINTER_TYPE
+ && (TREE_CODE (TREE_TYPE (*node)) == FUNCTION_TYPE
+ || TREE_CODE (TREE_TYPE (*node)) == METHOD_TYPE)
+ && csky_isr_value (args) != CSKY_FT_UNKNOWN)
+ {
+ *node = build_variant_type_copy (*node);
+ TREE_TYPE (*node) = build_type_attribute_variant (TREE_TYPE (*node),
+ tree_cons (name, args, TYPE_ATTRIBUTES (TREE_TYPE (*node))));
+ *no_add_attrs = true;
+ }
+ else if (flags & ((int)ATTR_FLAG_DECL_NEXT
+ | (int)ATTR_FLAG_FUNCTION_NEXT
+ | (int)ATTR_FLAG_ARRAY_NEXT))
+ {
+ *no_add_attrs = true;
+ return tree_cons (name, args, NULL_TREE);
+ }
+ else
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ }
+ return NULL_TREE;
+}
+
+
+/* Implement TARGET_REGISTER_MOVE_COST: compute extra cost of moving data
+ between one register class and another. */
+
+int
+csky_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
+ reg_class_t from, reg_class_t to)
+{
+#define GR_REG_CLASS_P(CLASS) \
+ ((CLASS) == GENERAL_REGS || (CLASS) == MINI_REGS || (CLASS) == SP_REGS \
+ || (CLASS) == LOW_REGS)
+
+#define HILO_REG_CLASS_P(CLASS) \
+ ((CLASS) == HI_REGS || (CLASS) == LO_REGS || (CLASS) == HILO_REGS)
+
+#define V_REG_CLASS_P(CLASS) \
+ ((CLASS) == V_REGS)
+
+ if (V_REG_CLASS_P (from) && V_REG_CLASS_P (to))
+ return 2;
+
+ if ((V_REG_CLASS_P (from) && GR_REG_CLASS_P (to))
+ || (GR_REG_CLASS_P (from) && V_REG_CLASS_P (to)))
+ return 6;
+
+ if ((HILO_REG_CLASS_P (from) && GR_REG_CLASS_P (to))
+ || (GR_REG_CLASS_P (from) && HILO_REG_CLASS_P (to)))
+ return 16;
+
+ if (HILO_REG_CLASS_P (from) && HILO_REG_CLASS_P (to))
+ return 32;
+
+ if ((HILO_REG_CLASS_P (from) && V_REG_CLASS_P (to))
+ || (V_REG_CLASS_P (from) && HILO_REG_CLASS_P (to)))
+ return 64;
+
+ return 2;
+}
+
+
+/* Implement TARGET_MEMORY_MOVE_COST: compute the cost of moving data
+ between registers and memory. */
+
+int
+csky_memory_move_cost (machine_mode mode, reg_class_t rclass,
+ bool in)
+{
+ return (4 + memory_move_secondary_cost (mode, rclass, in));
+}
+
+
+/* TARGET_RTX_COSTS helper for ck801/ck802. */
+
+static bool
+ck802_ck801_rtx_costs (rtx x, int code, int outer_code, int *total,
+ bool speed)
+{
+ machine_mode mode = GET_MODE (x);
+ switch (code)
+ {
+ /* Accessing memory costs quite a lot for first word; */
+ case MEM:
+ *total = COSTS_N_INSNS (1 + CSKY_NUM_REGS (mode));
+ return false;
+ case DIV:
+ case UDIV:
+ case MOD:
+ case UMOD:
+ *total = 100;
+ return true;
+
+ case ROTATE:
+ case ROTATERT:
+ case ASHIFT:
+ case LSHIFTRT:
+ case ASHIFTRT:
+ if (speed)
+ *total = 2;
+ else
+ *total = COSTS_N_INSNS (1);
+ return false;
+
+ case MINUS:
+ case PLUS:
+ *total = COSTS_N_INSNS (CSKY_NUM_REGS (mode));
+ return false;
+
+ case AND:
+ {
+ enum rtx_code subcode = GET_CODE (XEXP (x, 1));
+
+ /* If subcode is "not", we'll try to combine it into e.g. "andn"
+ instruction, so give AND itself zero cost. */
+ if (subcode == NOT)
+ {
+ *total = 0;
+ return false;
+ }
+ }
+ /* Fall through. */
+ case XOR:
+ case IOR:
+ *total = COSTS_N_INSNS (CSKY_NUM_REGS (mode));
+ return false;
+
+ case MULT:
+ /* FIXME: is ixw supported on ck801/ck802? */
+ /* We can use "ix.h/w" insn to replace multiply by 2 or 4.
+ "ix.h/w" is a 32-bit insn, so let its cost be a little less than
+ "mult" insn. */
+ if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1)))
+ {
+ unsigned HOST_WIDE_INT m
+ = (unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)));
+ if ((m == 2 || m == 4) && outer_code == PLUS)
+ {
+ *total = 2;
+ return true;
+ }
+ else
+ {
+ /* Because mult is relatively slower than other operations,
+ we try to use other insns when optimizing for speed.
+ When optimizing for size, give it lower cost. */
+ if (speed)
+ {
+ *total = COSTS_N_INSNS (10 * CSKY_NUM_REGS (mode));
+ return true;
+ }
+ int cycle = 0;
+ while (m)
+ {
+ m >>= 2;
+ cycle++;
+ }
+ *total = COSTS_N_INSNS (1) + cycle;
+ return false;
+ }
+ }
+ if (!speed)
+ *total = COSTS_N_INSNS (1);
+ return false;
+
+ case NEG:
+ /* Usually, we use subtract from 0 to substitute for neg, and
+ it costs 1 extra insn to move 0 to a register. */
+ *total = COSTS_N_INSNS (2 * CSKY_NUM_REGS (mode));
+ return false;
+
+ case NOT:
+ *total = COSTS_N_INSNS (CSKY_NUM_REGS (mode));
+ return false;
+
+ case COMPARE:
+ *total = COSTS_N_INSNS (1);
+ return false;
+
+ case SIGN_EXTEND:
+ case ZERO_EXTEND:
+ *total = COSTS_N_INSNS (CSKY_NUM_REGS (mode));
+ return false;
+
+ case SIGN_EXTRACT:
+ case ZERO_EXTRACT:
+ if (REG_P (XEXP (x, 0))
+ && CONST_INT_P (XEXP (x, 1))
+ && CONST_INT_P (XEXP (x, 2))
+ && INTVAL (XEXP (x, 1)) == 8
+ && INTVAL (XEXP (x, 2)) % 8 == 0)
+ {
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
+ *total = COSTS_N_INSNS (CSKY_NUM_REGS (mode));
+ return false;
+
+ case CONST_INT:
+ {
+ unsigned HOST_WIDE_INT t = (unsigned HOST_WIDE_INT) (INTVAL (x));
+
+ if (outer_code == COMPARE)
+ {
+ if (t < 0x10000)
+ *total = 0;
+ else
+ *total = COSTS_N_INSNS (2);
+ }
+ else if (outer_code == AND || outer_code == IOR || outer_code == XOR)
+ {
+ /* "andi,xori,ori" are 32-bit insns, so let it cost a
+ little more. */
+ if (t < 0x1000)
+ {
+ /* Try replacing "andi" by "sextb/h", so let it cost more. */
+ if (outer_code == AND && (t == 0xff || t == 0xffff))
+ {
+ *total = 8;
+ return true;
+ }
+ *total = 2;
+ }
+ else if (t < 0x10000)
+ *total = COSTS_N_INSNS (1);
+ else
+ *total = COSTS_N_INSNS (2);
+ }
+ else if (outer_code == PLUS || outer_code == MINUS)
+ {
+ /* "addi/subi rx,ry,imm", if imm<9, it is more often a
+ 16-bit insn. If imm>=9, use "movi" insn; it's probably
+ less than "addi/subi". */
+ if (t < 9)
+ *total = 0;
+ else if (t < 0x1000)
+ *total = 2;
+ else if (t < 0x10000)
+ *total = COSTS_N_INSNS (1);
+ else
+ *total = COSTS_N_INSNS (2);
+ }
+ else if (outer_code == ROTATE || outer_code == ROTATERT
+ || outer_code == LSHIFTRT || outer_code == ASHIFTRT
+ || outer_code == ASHIFT)
+ {
+ if (t < 32)
+ *total = 0;
+ else
+ *total = COSTS_N_INSNS (2);
+ }
+ else
+ {
+ if (t < 0x10000)
+ if (outer_code == SET && t < 256)
+ *total = 0;
+ else
+ *total = COSTS_N_INSNS (1);
+ else
+ *total = COSTS_N_INSNS (2);
+ }
+ }
+ return true;
+
+ case CONST:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ *total = COSTS_N_INSNS (3);
+ return true;
+ default:
+ return false;
+ }
+}
+
+
+/* TARGET_RTX_COSTS helper for ck803. */
+
+static bool
+ck803_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
+ int *total, bool speed ATTRIBUTE_UNUSED)
+{
+ switch (code)
+ {
+ case SET:
+ if (MEM_P (XEXP (x, 1)))
+ {
+ struct csky_address op1;
+ bool address_valid
+ = decompose_csky_address (XEXP (XEXP (x, 1), 0), &op1);
+ if (op1.index)
+ {
+ *total = COSTS_N_INSNS (3);
+ return true;
+ }
+ else if (address_valid)
+ {
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
+ }
+ if (REG_P (XEXP (x, 0)) && (GET_CODE (XEXP (x, 1)) == PLUS))
+ {
+ rtx sub_exp = XEXP (x, 1);
+ if (REG_P (XEXP (sub_exp, 0)) && REG_P (XEXP (sub_exp, 1)))
+ {
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
+ }
+ return false;
+ case MULT:
+ if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1)))
+ {
+ HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
+ if (val % 2 == 0 && val < 0xffffffff && val > 0)
+ {
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
+ }
+ return false;
+
+ case CONST:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ *total = COSTS_N_INSNS (3);
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* TARGET_RTX_COSTS helper for ck807+ arches. */
+
+static bool
+ck807_ck810_rtx_costs (rtx x, int code,
+ int outer_code ATTRIBUTE_UNUSED,
+ int *total, bool speed ATTRIBUTE_UNUSED)
+{
+ switch (code)
+ {
+ case MULT:
+ if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1)))
+ {
+ HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
+ if (val % 2 == 0 && val < 0xffffffff && val > 0)
+ {
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
+ }
+ return false;
+
+ case CONST:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ *total = COSTS_N_INSNS (3);
+ return true;
+ default:
+ return false;
+ }
+}
+
+
+/* Implement TARGET_RTX_COSTS, to compute a (partial) cost for rtx X.
+ Return true if the complete cost has been computed, and false if
+ subexpressions should be scanned. In either case, *TOTAL contains
+ the cost result. */
+
+static bool
+csky_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code,
+ int opno ATTRIBUTE_UNUSED, int *total, bool speed)
+{
+ int code = GET_CODE (x);
+
+ if (CSKY_TARGET_ARCH (CK802) || CSKY_TARGET_ARCH (CK801))
+ return ck802_ck801_rtx_costs (x, code, outer_code, total, speed);
+ else if (CSKY_TARGET_ARCH (CK803))
+ return ck803_rtx_costs (x, code, outer_code, total, speed);
+ else if (CSKY_TARGET_ARCH (CK807) || CSKY_TARGET_ARCH (CK810))
+ return ck807_ck810_rtx_costs (x, code, outer_code, total, speed);
+ else
+ gcc_unreachable ();
+}
+
+/* Emit assembly code for CASESI. This is only used on CK801 and CK802
+ when optimizing for size, and uses helper functions in libgcc instead
+ of doing the control transfer inline. */
+
+const char *
+csky_output_casesi (rtx *operands)
+{
+ rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[0])));
+
+ gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
+
+ switch (GET_MODE (diff_vec))
+ {
+ case E_QImode:
+ return (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned
+ ? "jbsr\t___gnu_csky_case_uqi"
+ : "jbsr\t___gnu_csky_case_sqi");
+ case E_HImode:
+ return (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned
+ ? "jbsr\t___gnu_csky_case_uhi"
+ : "jbsr\t___gnu_csky_case_shi");
+ case E_SImode:
+ return "jbsr\t___gnu_csky_case_si";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Implement TARGET_SCHED_ISSUE_RATE. Lookup the issue rate in the
+ per-core tuning structs. */
+static int
+csky_sched_issue_rate (void)
+{
+ if (CSKY_TARGET_ARCH (CK810))
+ return 2;
+ else
+ return 1;
+}
+
+
+/* This function implements the target macro TARGET_SCHED_ADJUST_COST.
+ It corrects the value of COST based on the relationship between
+ INSN and DEP through the dependence DEP_TYPE. It returns the new
+ value. */
+
+static int
+csky_sched_adjust_cost (rtx_insn *insn,
+ int dep_type,
+ rtx_insn *dep,
+ int cost,
+ unsigned int dw ATTRIBUTE_UNUSED)
+{
+ if (dep_type == REG_DEP_ANTI || dep_type == REG_DEP_OUTPUT)
+ return 0;
+ /* The REG_DEP_TRUE situation. */
+ else if (recog_memoized (insn) >= 0 && recog_memoized (dep) >= 0)
+ {
+ enum attr_type insn_type = get_attr_type (insn);
+ if (CSKY_TARGET_ARCH (CK803))
+ {
+ /* The ld or st's base reg depends on the pre insn,
+ it will delay 1 cycle. */
+ if (insn_type == TYPE_LOAD || insn_type == TYPE_STORE)
+ {
+ rtx pattern = PATTERN (insn);
+
+ gcc_assert (GET_CODE (pattern) == SET);
+ rtx addr = (insn_type == TYPE_LOAD
+ ? SET_SRC (pattern) : SET_DEST (pattern));
+
+ enum rtx_code code = GET_CODE (addr);
+ if (code == ZERO_EXTEND || code == SIGN_EXTEND)
+ addr = XEXP (addr, 0);
+ gcc_assert (GET_CODE (addr) == MEM);
+
+ rtx base = XEXP (addr, 0);
+ rtx reg = NULL_RTX;
+ if (REG_P (base))
+ reg = base;
+ if (GET_CODE (base) == PLUS
+ && GET_CODE (XEXP (base, 0)) == REG)
+ reg = XEXP (base, 0);
+ if ((reg != NULL_RTX) && reg_set_p (reg, PATTERN (dep)))
+ return 2;
+ }
+ }
+ else if (CSKY_TARGET_ARCH (CK802))
+ {
+ if ((insn_type == TYPE_CALL_JSR || insn_type == TYPE_BRANCH_JMP)
+ && get_attr_type (dep) != TYPE_LOAD)
+ return 1;
+
+ if (insn_type == TYPE_LOAD || insn_type == TYPE_STORE)
+ {
+ rtx pattern = PATTERN (insn);
+
+ gcc_assert (GET_CODE (pattern) == SET);
+
+ rtx addr = (insn_type == TYPE_LOAD
+ ? SET_SRC (pattern) : SET_DEST (pattern));
+
+ enum rtx_code code = GET_CODE (addr);
+ if (code == ZERO_EXTEND || code == SIGN_EXTEND)
+ addr = XEXP (addr, 0);
+ gcc_assert (GET_CODE (addr) == MEM);
+
+ rtx base = XEXP (addr, 0);
+ rtx reg = NULL_RTX;
+ if (REG_P (base))
+ reg = base;
+ if (GET_CODE (base) == PLUS
+ && GET_CODE (XEXP (base, 0)) == REG)
+ reg = XEXP (base, 0);
+ if ((reg != NULL_RTX) && reg_set_p (reg, PATTERN (dep))
+ && get_attr_type (dep) != TYPE_LOAD)
+ return 1;
+
+ if (insn_type == TYPE_STORE
+ && reg_referenced_p (SET_SRC (pattern), PATTERN (dep)))
+ return 1;
+ }
+ }
+ }
+ return cost;
+}
+
+static bool
+csky_warn_func_return (tree decl)
+{
+ /* Naked functions are implemented entirely in assembly, including the
+ return sequence, so suppress warnings about this. */
+ return lookup_attribute ("naked", DECL_ATTRIBUTES (decl)) == NULL_TREE;
+}
+
+
+/* Implement TARGET_RETURN_IN_MEMORY to decide whether TYPE should be
+ returned in memory (true) or in a register (false).
+ FNTYPE is the type of the function making the call. */
+static bool
+csky_return_in_memory (const_tree type,
+ const_tree fntype ATTRIBUTE_UNUSED)
+{
+ const HOST_WIDE_INT size = int_size_in_bytes (type);
+ return (size == -1 || size > 2 * UNITS_PER_WORD);
+}
+
+
+/* Implement TARGET_DWARF_REGISTER_SPAN.
+ Dwarf models VFP registers as 64-bit or 128-bit registers default.
+ GCC models tham as 32-bit registers, so we need to describe this to
+ the DWARF generation code. Other registers can use the default. */
+static rtx
+csky_dwarf_register_span (rtx rtl)
+{
+ machine_mode mode;
+ unsigned regno;
+ rtx parts[16];
+ int nregs;
+ int i;
+
+ regno = REGNO (rtl);
+ if (!CSKY_VREG_P (regno))
+ return NULL_RTX;
+
+ mode = GET_MODE (rtl);
+ if (GET_MODE_SIZE (mode) < 8)
+ return NULL_RTX;
+
+ if (TARGET_SOFT_FPU)
+ {
+ nregs = GET_MODE_SIZE (mode) / 4;
+ for (i = 0; i < nregs; i += 2)
+ if (TARGET_BIG_ENDIAN)
+ {
+ parts[i] = gen_rtx_REG (SImode, regno + i + 1);
+ parts[i + 1] = gen_rtx_REG (SImode, regno + i);
+ }
+ else
+ {
+ parts[i] = gen_rtx_REG (SImode, regno + i);
+ parts[i + 1] = gen_rtx_REG (SImode, regno + i + 1);
+ }
+ }
+ else
+ {
+ /* FIXME: dwarf2 considers all general registers to be the same
+ as the CPU bit width. Transform the 64-bit FPU registers to
+ 32 bits here, and we will modify the unwind processing to
+ fit CSKY architecture later. */
+ nregs = GET_MODE_SIZE (mode) / 8;
+ for (i = 0; i < nregs; i++)
+ parts[i] = gen_rtx_REG (SImode, regno + i);
+ }
+
+ return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nregs , parts));
+}
+
+/* Implement TARGET_INIT_LIBFUNCS. */
+
+static void
+csky_init_libfuncs (void)
+{
+ if (TARGET_CSKY_LINUX)
+ init_sync_libfuncs (UNITS_PER_WORD);
+ if (!TARGET_LIBCCRT)
+ return;
+
+ #define CSKY_GCC_SYM(sym) "__csky_ccrt_" # sym
+
+ /* int */
+
+ /* Arithmetic functions */
+ set_optab_libfunc (ashl_optab, DImode, CSKY_GCC_SYM (ashldi3));
+ set_optab_libfunc (ashr_optab, DImode, CSKY_GCC_SYM (ashrdi3));
+ set_optab_libfunc (sdiv_optab, SImode, CSKY_GCC_SYM (divsi3));
+ set_optab_libfunc (sdiv_optab, DImode, CSKY_GCC_SYM (divdi3));
+ set_optab_libfunc (lshr_optab, DImode, CSKY_GCC_SYM (lshrdi3));
+ set_optab_libfunc (smod_optab, SImode, CSKY_GCC_SYM (modsi3));
+ set_optab_libfunc (smod_optab, DImode, CSKY_GCC_SYM (moddi3));
+ set_optab_libfunc (smul_optab, DImode, CSKY_GCC_SYM (muldi3));
+ set_optab_libfunc (neg_optab, DImode, CSKY_GCC_SYM (negdi2));
+ set_optab_libfunc (udiv_optab, SImode, CSKY_GCC_SYM (udivsi3));
+ set_optab_libfunc (udiv_optab, DImode, CSKY_GCC_SYM (udivdi3));
+ set_optab_libfunc (udivmod_optab, DImode, CSKY_GCC_SYM (udivmoddi4));
+ set_optab_libfunc (umod_optab, SImode, CSKY_GCC_SYM (umodsi3));
+ set_optab_libfunc (umod_optab, DImode, CSKY_GCC_SYM (umoddi3));
+
+ /* Comparison functions */
+ set_optab_libfunc (cmp_optab, DImode, CSKY_GCC_SYM (cmpdi2));
+ set_optab_libfunc (ucmp_optab, DImode, CSKY_GCC_SYM (ucmpdi2));
+
+ /* Trapping arithmetic functions */
+ set_optab_libfunc (absv_optab, SImode, CSKY_GCC_SYM (absvsi2));
+ set_optab_libfunc (absv_optab, DImode, CSKY_GCC_SYM (absvdi2));
+ set_optab_libfunc (addv_optab, SImode, CSKY_GCC_SYM (addvsi3));
+ set_optab_libfunc (addv_optab, DImode, CSKY_GCC_SYM (addvdi3));
+ set_optab_libfunc (smulv_optab, SImode, CSKY_GCC_SYM (mulvsi3));
+ set_optab_libfunc (smulv_optab, DImode, CSKY_GCC_SYM (mulvdi3));
+ set_optab_libfunc (negv_optab, SImode, CSKY_GCC_SYM (negvsi2));
+ set_optab_libfunc (negv_optab, DImode, CSKY_GCC_SYM (negvdi2));
+ set_optab_libfunc (subv_optab, SImode, CSKY_GCC_SYM (subvsi3));
+ set_optab_libfunc (subv_optab, DImode, CSKY_GCC_SYM (subvdi3));
+
+ /* Bit operations */
+ set_optab_libfunc (clz_optab, SImode, CSKY_GCC_SYM (clzsi2));
+ set_optab_libfunc (clz_optab, DImode, CSKY_GCC_SYM (clzdi2));
+ set_optab_libfunc (ctz_optab, SImode, CSKY_GCC_SYM (ctzsi2));
+ set_optab_libfunc (ctz_optab, DImode, CSKY_GCC_SYM (ctzdi2));
+ set_optab_libfunc (ffs_optab, DImode, CSKY_GCC_SYM (ffsdi2));
+ set_optab_libfunc (parity_optab, SImode, CSKY_GCC_SYM (paritysi2));
+ set_optab_libfunc (parity_optab, DImode, CSKY_GCC_SYM (paritydi2));
+ set_optab_libfunc (popcount_optab,SImode, CSKY_GCC_SYM (popcountsi2));
+ set_optab_libfunc (popcount_optab,DImode, CSKY_GCC_SYM (popcountdi2));
+ set_optab_libfunc (bswap_optab, SImode, CSKY_GCC_SYM (bswapsi2));
+ set_optab_libfunc (bswap_optab, DImode, CSKY_GCC_SYM (bswapdi2));
+
+ /* float */
+
+ /* Arithmetic functions */
+ set_optab_libfunc (add_optab, SFmode, CSKY_GCC_SYM (addsf3));
+ set_optab_libfunc (add_optab, DFmode, CSKY_GCC_SYM (adddf3));
+ set_optab_libfunc (sub_optab, SFmode, CSKY_GCC_SYM (subsf3));
+ set_optab_libfunc (sub_optab, DFmode, CSKY_GCC_SYM (subdf3));
+ set_optab_libfunc (smul_optab, SFmode, CSKY_GCC_SYM (mulsf3));
+ set_optab_libfunc (smul_optab, DFmode, CSKY_GCC_SYM (muldf3));
+ set_optab_libfunc (sdiv_optab, SFmode, CSKY_GCC_SYM (divsf3));
+ set_optab_libfunc (sdiv_optab, DFmode, CSKY_GCC_SYM (divdf3));
+ set_optab_libfunc (neg_optab, SFmode, CSKY_GCC_SYM (negsf2));
+ set_optab_libfunc (neg_optab, DFmode, CSKY_GCC_SYM (negdf2));
+
+ /* Conversion functions */
+ set_conv_libfunc (sext_optab, DFmode, SFmode, CSKY_GCC_SYM (extendsfdf2));
+ set_conv_libfunc (trunc_optab, SFmode, DFmode, CSKY_GCC_SYM (truncdfsf2));
+ set_conv_libfunc (sfix_optab, SImode, SFmode, CSKY_GCC_SYM (fixsfsi));
+ set_conv_libfunc (sfix_optab, SImode, DFmode, CSKY_GCC_SYM (fixdfsi));
+ set_conv_libfunc (sfix_optab, DImode, SFmode, CSKY_GCC_SYM (fixsfdi));
+ set_conv_libfunc (sfix_optab, DImode, DFmode, CSKY_GCC_SYM (fixdfdi));
+ set_conv_libfunc (ufix_optab, SImode, SFmode, CSKY_GCC_SYM (fixunssfsi));
+ set_conv_libfunc (ufix_optab, SImode, DFmode, CSKY_GCC_SYM (fixunsdfsi));
+ set_conv_libfunc (ufix_optab, DImode, SFmode, CSKY_GCC_SYM (fixunssfdi));
+ set_conv_libfunc (ufix_optab, DImode, DFmode, CSKY_GCC_SYM (fixunsdfdi));
+ set_conv_libfunc (sfloat_optab, SFmode, SImode, CSKY_GCC_SYM (floatsisf));
+ set_conv_libfunc (sfloat_optab, DFmode, SImode, CSKY_GCC_SYM (floatsidf));
+ set_conv_libfunc (sfloat_optab, SFmode, DImode, CSKY_GCC_SYM (floatdisf));
+ set_conv_libfunc (sfloat_optab, DFmode, DImode, CSKY_GCC_SYM (floatdidf));
+ set_conv_libfunc (ufloat_optab, SFmode, SImode, CSKY_GCC_SYM (floatunsisf));
+ set_conv_libfunc (ufloat_optab, DFmode, SImode, CSKY_GCC_SYM (floatunsidf));
+ set_conv_libfunc (ufloat_optab, SFmode, DImode, CSKY_GCC_SYM (floatundisf));
+ set_conv_libfunc (ufloat_optab, DFmode, DImode, CSKY_GCC_SYM (floatundidf));
+
+ /* Comparison functions */
+ set_optab_libfunc (cmp_optab, SFmode, CSKY_GCC_SYM (cmpsf2));
+ set_optab_libfunc (cmp_optab, DFmode, CSKY_GCC_SYM (cmpdf2));
+ set_optab_libfunc (unord_optab, SFmode, CSKY_GCC_SYM (unordsf2));
+ set_optab_libfunc (unord_optab, DFmode, CSKY_GCC_SYM (unorddf2));
+ set_optab_libfunc (eq_optab, SFmode, CSKY_GCC_SYM (eqsf2));
+ set_optab_libfunc (eq_optab, DFmode, CSKY_GCC_SYM (eqdf2));
+ set_optab_libfunc (ne_optab, SFmode, CSKY_GCC_SYM (nesf2));
+ set_optab_libfunc (ne_optab, DFmode, CSKY_GCC_SYM (nedf2));
+ set_optab_libfunc (ge_optab, SFmode, CSKY_GCC_SYM (gesf2));
+ set_optab_libfunc (ge_optab, DFmode, CSKY_GCC_SYM (gedf2));
+ set_optab_libfunc (lt_optab, SFmode, CSKY_GCC_SYM (ltsf2));
+ set_optab_libfunc (lt_optab, DFmode, CSKY_GCC_SYM (ltdf2));
+ set_optab_libfunc (le_optab, SFmode, CSKY_GCC_SYM (lesf2));
+ set_optab_libfunc (le_optab, DFmode, CSKY_GCC_SYM (ledf2));
+ set_optab_libfunc (gt_optab, SFmode, CSKY_GCC_SYM (gtsf2));
+ set_optab_libfunc (gt_optab, DFmode, CSKY_GCC_SYM (gtdf2));
+}
+
+
+/* Implement TARGET_ADDRESS_COST to estimate cost of the memory address X.
+ For C-SKY, (register) and (register + offset) have the same cost.
+ Other situations cost more. */
+
+static int
+csky_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
+ addr_space_t as ATTRIBUTE_UNUSED,
+ bool speed ATTRIBUTE_UNUSED)
+{
+ enum rtx_code code = GET_CODE (x);
+
+ if (code == REG)
+ return COSTS_N_INSNS (1);
+ if (code == PLUS
+ && REG_P (XEXP (x, 0))
+ && CONST_INT_P (XEXP (x, 1)))
+ return COSTS_N_INSNS (1);
+
+ return COSTS_N_INSNS (3);
+}
+
+
+/* Implement TARGET_FIXED_CONDITION_CODE_REGS. */
+
+static bool
+csky_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
+{
+ *p1 = CSKY_CC_REGNUM;
+ *p2 = INVALID_REGNUM;
+ return true;
+}
+
+
+struct gcc_target targetm = TARGET_INITIALIZER;
+
+#include "gt-csky.h"
diff --git a/gcc/config/csky/csky.h b/gcc/config/csky/csky.h
new file mode 100644
index 0000000..39aac6b
--- /dev/null
+++ b/gcc/config/csky/csky.h
@@ -0,0 +1,1054 @@
+/* Declarations for the C-SKY back end.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ Contributed by C-SKY Microsystems and Mentor Graphics.
+
+ 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_CSKY_H
+#define GCC_CSKY_H
+
+/* In some places e.g. csky_secondary_reload, we use -1 to indicate an
+ invalid register. In other places where N is unsigned the comparison
+ to zero would give an error, so explicitly cast to int here. */
+#define CSKY_GENERAL_REGNO_P(N) \
+ ((N) < CSKY_NGPR_REGS && (int)(N) >= 0)
+
+#define CSKY_VREG_P(N) \
+ ((N) >= CSKY_FIRST_VFP_REGNUM && (N) <= CSKY_LAST_VFP_REGNUM)
+
+#define CSKY_HILO_REG_P(N) \
+ ((N) == CSKY_HI_REGNUM || (N) == CSKY_LO_REGNUM)
+
+/* Helper macros for constant constraints and predicates. */
+#define CSKY_VALUE_BETWEEN(VALUE, LOW, HIGH) \
+ ((VALUE) >= (LOW) && (VALUE) <= (HIGH))
+
+#define CSKY_CONST_OK_FOR_I(VALUE) \
+ CSKY_VALUE_BETWEEN (VALUE, 0, 65535)
+
+#define CSKY_CONST_OK_FOR_J(VALUE) \
+ CSKY_VALUE_BETWEEN (VALUE, 1, 32)
+
+#define CSKY_CONST_OK_FOR_K(VALUE) \
+ CSKY_VALUE_BETWEEN (VALUE, 0, 31)
+
+#define CSKY_CONST_OK_FOR_L(VALUE) \
+ CSKY_VALUE_BETWEEN (VALUE, 1, 8)
+
+#define CSKY_CONST_OK_FOR_M(VALUE) \
+ CSKY_VALUE_BETWEEN (VALUE, 1, 4096)
+
+#define CSKY_CONST_OK_FOR_N(VALUE) \
+ CSKY_VALUE_BETWEEN (VALUE, 1, 256)
+
+#define CSKY_CONST_OK_FOR_O(VALUE) \
+ CSKY_VALUE_BETWEEN (VALUE, 0, 4095)
+
+#define CSKY_CONST_OK_FOR_P(VALUE) \
+ (((VALUE) & 0x3) == 0 && CSKY_VALUE_BETWEEN (VALUE, 4, 508))
+
+#define CSKY_CONST_OK_FOR_T(VALUE) \
+ CSKY_VALUE_BETWEEN (VALUE, -256, -1)
+
+#define CSKY_CONST_OK_FOR_Ub(VALUE) \
+ (exact_log2 (VALUE & 0xFFFFFFFF) >= 0)
+
+#define CSKY_CONST_OK_FOR_Uc(VALUE) \
+ ((VALUE) == (HOST_WIDE_INT) -1 \
+ || (exact_log2 ((VALUE) + 1) >= 0 \
+ && exact_log2 ((VALUE) + 1) <= 31))
+
+#define CSKY_CONST_OK_FOR_Ud(VALUE) \
+ ((CSKY_CONST_OK_FOR_I ((VALUE) & 0xffffffff) \
+ || CSKY_CONST_OK_FOR_Ub ((VALUE)) \
+ || CSKY_CONST_OK_FOR_Uc (((VALUE) << 32) >> 32)) \
+ && (CSKY_CONST_OK_FOR_I ((VALUE) >> 32) \
+ || CSKY_CONST_OK_FOR_Ub ((VALUE) >> 32) \
+ || CSKY_CONST_OK_FOR_Uc ((VALUE) >> 32))) \
+
+#define CSKY_CONST_OK_FOR_Ug(VALUE) \
+ (((VALUE) & 0x3) == 0 && CSKY_VALUE_BETWEEN (VALUE, -508, -4))
+
+#define CSKY_CONST_OK_FOR_Uh(VALUE) \
+ CSKY_VALUE_BETWEEN (VALUE, -31, 0)
+
+#define CSKY_CONST_OK_FOR_Uj(VALUE) \
+ (((VALUE) & 0x3) == 0 && CSKY_VALUE_BETWEEN (VALUE, 1, 1024))
+
+#define CSKY_CONST_OK_FOR_Uk(VALUE) \
+ CSKY_VALUE_BETWEEN (VALUE, 1, 65536)
+
+#define CSKY_CONST_OK_FOR_Ul(VALUE) \
+ (((VALUE) & 0x3) == 0 && CSKY_VALUE_BETWEEN (VALUE, -1024, -4))
+
+#define CSKY_CONST_OK_FOR_Um(VALUE) \
+ CSKY_VALUE_BETWEEN (VALUE, -4096, -1)
+
+#define CSKY_CONST_OK_FOR_US(VALUE) \
+ CSKY_VALUE_BETWEEN (VALUE, -8, -1)
+
+#define CSKY_CONST_OK_FOR_MOVIH(VALUE) \
+ (((VALUE) & 0xFFFF) == 0)
+
+#ifndef TARGET_CPU_DEFAULT
+#define TARGET_CPU_DEFAULT CSKY_TARGET_CORE_GET(ck810f)
+#endif
+
+/* Options that are enabled by default are specified as such in the
+ .opt file. */
+#define TARGET_DEFAULT 0
+
+/* The highest CSKY architecture version supported by the target. */
+#define CSKY_TARGET_ARCH(arch) \
+ (csky_base_arch == CSKY_TARGET_ARCH_GET (arch))
+
+/* Define some macros for target code generation options. */
+#define TARGET_SOFT_FPU \
+ (csky_fpu_index == TARGET_FPU_fpv2_sf)
+#define TARGET_CASESI \
+ (optimize_size && TARGET_CONSTANT_POOL \
+ && (CSKY_TARGET_ARCH (CK801) || CSKY_TARGET_ARCH (CK802)))
+#define TARGET_TLS \
+ (CSKY_TARGET_ARCH (CK807) || CSKY_TARGET_ARCH (CK810))
+
+/* Number of loads/stores handled by ldm/stm. */
+#define CSKY_MIN_MULTIPLE_STLD 3
+#define CSKY_MAX_MULTIPLE_STLD 12
+
+/* Pull in enums and defines for processor/arch variants. This makes
+ it possible to use CSKY_TARGET_ARCH in macros defined in this file. */
+#include "csky_opts.h"
+extern enum csky_base_architecture csky_base_arch;
+
+/* Pull in enums and defines for ISA features. Likewise required to
+ support use of CSKY_ISA_FEATURE in this file.
+ Note that the CSKY_ISA_FEATURE macro tests properties of the
+ particular processor we're compiling for, not code generation
+ options that may have dependencies on those features. The latter
+ are handled by TARGET_xxxx macros/variables instead. See csky.opt. */
+#include "csky_isa.h"
+extern int csky_arch_isa_features[];
+#define CSKY_ISA_FEATURE(IDENT) \
+ csky_arch_isa_features[CSKY_ISA_FEATURE_GET (IDENT)]
+
+/******************************************************************
+ * Storage Layout *
+ ******************************************************************/
+
+
+/* Define this if most significant bit is lowest numbered
+ in instructions that operate on numbered bit-fields. */
+#define BITS_BIG_ENDIAN 0
+
+/* If the most significant byte of a word is the lowest numbered. */
+#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
+
+/* If the most significant word of a multiword number is the lowest. */
+#define WORDS_BIG_ENDIAN (BYTES_BIG_ENDIAN)
+
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD 4
+
+/* Define this macro if it is advisable to hold scalars in registers
+ in a wider mode than that declared by the program. In such cases,
+ the value is constrained to be within the bounds of the declared
+ type, but kept valid in the wider mode. The signedness of the
+ extension may differ from that of the type. */
+#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
+ if (GET_MODE_CLASS (MODE) == MODE_INT \
+ && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \
+ (MODE) = SImode;
+
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY 32
+
+/* Boundary (in *bits*) on which stack pointer should be aligned.
+ Per C-SKY, the published V2 ABI document is incorrect and the proper
+ alignment is on a 4-byte boundary rather than 8 bytes. */
+#define STACK_BOUNDARY 32
+
+/* Align definitions of arrays, unions and structures so that
+ initializations and copies can be made more efficient. This is not
+ ABI-changing, so it only affects places where we can see the
+ definition. Increasing the alignment tends to introduce padding,
+ so don't do this when optimizing for size/conserving stack space. */
+#define CSKY_EXPAND_ALIGNMENT(COND, EXP, ALIGN) \
+ (((COND) && ((ALIGN) < BITS_PER_WORD) \
+ && (TREE_CODE (EXP) == ARRAY_TYPE \
+ || TREE_CODE (EXP) == UNION_TYPE \
+ || TREE_CODE (EXP) == RECORD_TYPE)) \
+ ? BITS_PER_WORD : (ALIGN))
+
+/* Align global data. */
+#define DATA_ALIGNMENT(EXP, ALIGN) \
+ CSKY_EXPAND_ALIGNMENT (!optimize_size, EXP, ALIGN)
+
+/* Similarly, make sure that objects on the stack are sensibly aligned. */
+#define LOCAL_ALIGNMENT(EXP, ALIGN) \
+ CSKY_EXPAND_ALIGNMENT (!flag_conserve_stack, EXP, ALIGN)
+
+/* No data type wants to be aligned rounder than this. */
+#define BIGGEST_ALIGNMENT 32
+
+/* Every structures size must be a multiple of 8 bits. */
+#define STRUCTURE_SIZE_BOUNDARY 8
+
+/* Look at the fundamental type that is used for a bit-field and use
+ that to impose alignment on the enclosing structure.
+ struct s {int a:8}; should have same alignment as "int", not "char". */
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* Largest integer machine mode for structures. If undefined, the default
+ is GET_MODE_SIZE(DImode). */
+#define MAX_FIXED_MODE_SIZE 64
+
+/* Allocation boundary (in *bits*) for the code of a function.
+ Optimize ck801 and ck802 a little harder for size. */
+#define FUNCTION_BOUNDARY \
+ (((CSKY_TARGET_ARCH (CK801) || CSKY_TARGET_ARCH (CK802)) \
+ && optimize_size) \
+ ? 16 : 32)
+
+/* C-SKY does not support unaligned access. */
+#define STRICT_ALIGNMENT 1
+
+#undef SIZE_TYPE
+#define SIZE_TYPE "unsigned int"
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "int"
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "long int"
+
+#undef UINT_LEAST32_TYPE
+#define UINT_LEAST32_TYPE "unsigned int"
+
+#undef INT_LEAST32_TYPE
+#define INT_LEAST32_TYPE "int"
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE BITS_PER_WORD
+
+/******************************************************************
+ * Layout of Source Language Data Types *
+ ******************************************************************/
+
+
+/* 'char' is unsigned by default for backward compatibility. */
+#define DEFAULT_SIGNED_CHAR 0
+
+
+/******************************************************************
+ * Stack Layout and Calling Conventions *
+ ******************************************************************/
+
+
+/* Basic Stack Layout */
+
+
+/* Define this if pushing a word on the stack
+ makes the stack pointer a smaller address. */
+#define STACK_GROWS_DOWNWARD 1
+
+/* Define this to nonzero if the nominal address of the stack frame
+ is at the high-address end of the local variables;
+ that is, each additional local variable allocated
+ goes at a more negative offset in the frame. */
+#define FRAME_GROWS_DOWNWARD 1
+
+/* Offset of first parameter from the argument pointer register value. */
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+/* A C expression whose value is RTL representing the value of the return
+ address for the frame COUNT steps up from the current frame. */
+#define RETURN_ADDR_RTX(COUNT, FRAME) \
+ csky_return_addr (COUNT, FRAME)
+
+/* Pick up the return address upon entry to a procedure. Used for
+ dwarf2 unwind information. This also enables the table driven
+ mechanism. */
+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, CSKY_LR_REGNUM)
+
+
+/* Exception Handling Support */
+
+/* The register that holds the return address in exception handlers. */
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (SImode, CSKY_EH_STACKADJ_REGNUM)
+
+
+/* Registers That Address the Stack Frame */
+
+
+/* Register to use for pushing function arguments. */
+#define STACK_POINTER_REGNUM CSKY_SP_REGNUM
+
+/* Base register for access to local variables of the function. */
+#define FRAME_POINTER_REGNUM 8
+
+/* Base register for access to arguments of the function. This is a fake
+ register that is always eliminated. */
+#define ARG_POINTER_REGNUM 32
+
+/* Static chain register.
+ Register use is more restricted on CK801. */
+#define STATIC_CHAIN_REGNUM (CSKY_TARGET_ARCH (CK801) ? 13 : 12)
+
+
+/* Eliminating Frame Pointer and Arg Pointer */
+
+
+/* Definitions for register eliminations.
+
+ This is an array of structures. Each structure initializes one pair
+ of eliminable registers. The "from" register number is given first,
+ followed by "to". Eliminations of the same "from" register are listed
+ in order of preference.
+
+ We have two registers that can be eliminated on the CSKY. First, the
+ arg pointer register can often be eliminated in favor of the stack
+ pointer register. Secondly, the pseudo frame pointer register can always
+ be eliminated; it is replaced with the stack pointer. */
+#define ELIMINABLE_REGS \
+{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM },\
+ { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM },\
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }}
+
+/* Define the offset between two registers, one to be eliminated, and the
+ other its replacement, at the start of a routine. */
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+ (OFFSET) = csky_initial_elimination_offset (FROM, TO)
+
+
+/* Passing Function Arguments on the Stack */
+
+
+/* Define this if the maximum size of all the outgoing args is to be
+ accumulated and pushed during the prologue. The amount can be
+ found in the variable crtl->outgoing_args_size. */
+#define ACCUMULATE_OUTGOING_ARGS 1
+
+
+/* Passing Arguments in Registers */
+
+
+/* A C type for declaring a variable that is used as the first argument of
+ TARGET_ FUNCTION_ARG and other related values. */
+#define CUMULATIVE_ARGS int
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+ For a library call, FNTYPE is 0.
+
+ On CSKY, the offset always starts at 0: the first parm reg is always
+ the same reg. */
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
+ ((CUM) = 0)
+
+/* True if N is a possible register number for function argument passing.
+ On the CSKY, r0-r3 are used to pass args.
+ The int cast is to prevent a complaint about unsigned comparison to
+ zero, since CSKY_FIRST_PARM_REGNUM is zero. */
+#define FUNCTION_ARG_REGNO_P(REGNO) \
+ (((int)(REGNO) >= CSKY_FIRST_PARM_REGNUM) && \
+ ((REGNO) < (CSKY_NPARM_REGS + CSKY_FIRST_PARM_REGNUM)))
+
+/* How Large Values Are Returned */
+
+
+/* Define DEFAULT_PCC_STRUCT_RETURN to 1 if all structure and union return
+ values must be in memory. On the CSKY, small
+ structures (eight bytes or fewer) are returned in
+ the register pair r0/r1. */
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
+ the stack pointer does not matter. The value is tested only in
+ functions that have frame pointers.
+ No definition is equivalent to always zero.
+
+ On the CSKY, the function epilogue recovers the stack pointer from the
+ frame. */
+#define EXIT_IGNORE_STACK 1
+
+
+/******************************************************************
+ * Register Usage & Register Classes *
+ ******************************************************************/
+
+
+#define FIRST_PSEUDO_REGISTER 71
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator.
+ On C-SKY, r14 is SP, r26 is used by linker,
+ r27 is used by assembler, r28 is data base address,
+ r29 is GOT base address, r30 is handler base address,
+ r31 is TLS register. */
+#define FIXED_REGISTERS \
+ /* r0 r1 r2 r3 r4 r5 r6 r7 */ \
+{ 0, 0, 0, 0, 0, 0, 0, 0, \
+ /* r8 r9 r10 r11 r12 r13 r14 r15 */ \
+ 0, 0, 0, 0, 0, 0, 1, 0, \
+ /* r16 r17 r18 r19 r20 r21 r22 r23 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ /* r24 r25 r26 r27 r28 r29 r30 tls */ \
+ 0, 0, 1, 1, 1, 1, 1, 1, \
+ /* reserved c hi lo */ \
+ 1, 1, 0, 0, \
+ /* reserved */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* vr0 vr1 vr2 vr3 vr4 vr5 vr6 vr7 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ /* vr8 vr9 vr10 vr11 vr12 vr13 vr14 vr15 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0 , \
+ /* reserved */ \
+ 1, 1, \
+ /* epc */ \
+ 1 \
+}
+
+/* 1 for registers that is clobbered (in general) by function calls.
+ If a register has 0, the compiler automatically saves it on
+ function entry and restores it on function exit, if the register
+ is used within the function. */
+#define CALL_USED_REGISTERS \
+ /* r0 r1 r2 r3 r4 r5 r6 r7 */ \
+{ 1, 1, 1, 1, 0, 0, 0, 0, \
+ /* r8 r9 r10 r11 r12 r13 r14 r15 */ \
+ 0, 0, 0, 0, 1, 1, 1, 0, \
+ /* r16 r17 r18 r19 r20 r21 r22 r23 */ \
+ 0, 0, 1, 1, 1, 1, 1, 1, \
+ /* r24 r25 r26 r27 r28 r29 r30 r31 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* reserved c hi lo */ \
+ 1, 1, 1, 1, \
+ /* reserved */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* vr0 vr1 vr2 vr3 vr4 vr5 vr6 vr7 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* vr8 vr9 vr10 vr11 vr12 vr13 vr14 vr15 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* reserved */ \
+ 1, 1, \
+ /* epc */ \
+ 1 \
+}
+
+/* Like `CALL_USED_REGISTERS' but used to overcome a historical
+ problem which makes CALL_USED_REGISTERS *always* include
+ all the FIXED_REGISTERS. Until this problem has been
+ resolved this macro can be used to overcome this situation.
+ In particular, block_propagate() requires this list
+ be accurate, or we can remove registers which should be live.
+ This macro is used in get_csky_live_regs(). */
+#define CALL_REALLY_USED_REGISTERS \
+ /* r0 r1 r2 r3 r4 r5 r6 r7 */ \
+{ 1, 1, 1, 1, 0, 0, 0, 0, \
+ /* r8 r9 r10 r11 r12 r13 r14 r15 */ \
+ 0, 0, 0, 0, 1, 1, 1, 0, \
+ /* r16 r17 r18 r19 r20 r21 r22 r23 */ \
+ 0, 0, 1, 1, 1, 1, 1, 1, \
+ /* r24 r25 r26 r27 r28 r29 r30 r31 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* reserved c hi lo */ \
+ 1, 1, 1, 1, \
+ /* reserved */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* vr0 vr1 vr2 vr3 vr4 vr5 vr6 vr7 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* vr8 vr9 vr10 vr11 vr12 vr13 vr14 vr15 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* reserved */ \
+ 1, 1, \
+ /* epc */ \
+ 1 \
+}
+
+#define REGISTER_NAMES \
+{ \
+ "a0", "a1", "a2", "a3", "l0", "l1", "l2", "l3", \
+ "l4", "l5", "l6", "l7", "t0", "t1", "sp", "lr", \
+ "l8", "l9", "t2", "t3", "t4", "t5", "t6", "t7", \
+ "t8", "t9", "r26", "r27", "gb", "r29", "svbr", "r31", \
+ /* reserved */ \
+ "reserved", \
+ /* CC register: 33 */ \
+ "c", \
+ /* DSP instruction register: 34, 35 */ \
+ "hi", "lo", \
+ "reserved", "reserved", "reserved", "reserved", "reserved", \
+ "reserved", "reserved", "reserved", "reserved", "reserved", \
+ "reserved", "reserved", "reserved", "reserved", "reserved", \
+ "reserved", \
+ /* V registers: 52~67 */ \
+ "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", \
+ "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", \
+ "reserved", "reserved", \
+ "epc" \
+}
+
+/* Table of additional register names to use in user input. */
+#define ADDITIONAL_REGISTER_NAMES \
+{ \
+ {"r0", 0}, \
+ {"r1", 1}, \
+ {"r2", 2}, \
+ {"r3", 3}, \
+ {"r4", 4}, \
+ {"r5", 5}, \
+ {"r6", 6}, \
+ {"r7", 7}, \
+ {"r8", 8}, \
+ {"r9", 9}, \
+ {"r10", 10}, \
+ {"r11", 11}, \
+ {"r12", 12}, \
+ {"r13", 13}, \
+ {"r14", 14}, \
+ {"r15", 15}, \
+ {"r16", 16}, \
+ {"r17", 17}, \
+ {"r18", 18}, \
+ {"r19", 19}, \
+ {"r20", 20}, \
+ {"r21", 21}, \
+ {"r22", 22}, \
+ {"r23", 23}, \
+ {"r24", 24}, \
+ {"r25", 25}, \
+ {"r26", 26}, \
+ {"r27", 27}, \
+ {"r28", 28}, \
+ {"r29", 29}, \
+ {"r30", 30}, \
+ {"r31", 31}, \
+}
+
+/* The order in which registers should be allocated.
+ It is better to use the registers the caller need not save.
+ Allocate r0 through r3 in reverse order since r3 is least likely
+ to contain a function parameter; in addition results are returned
+ in r0. It is quite good to use lr since other calls may clobber
+ it anyway. */
+#define REG_ALLOC_ORDER \
+/* r3 r2 r1 r0 r12 r13 r18 r19 */ \
+ { 3, 2, 1, 0, 12, 13, 18, 19, \
+/* r20 r21 r22 r23 r24 r25 */ \
+ 20, 21, 22, 23, 24, 25, \
+/* r15 r4 r5 r6 r7 r8 r9 r10 r11 */ \
+ 15, 4, 5, 6, 7, 8, 9, 10, 11, \
+/* r16 r17 r26 r27 r28 r29 r30 hi lo */ \
+ 16, 17, 26, 27, 28, 29, 30, 34, 35, \
+/* vr0 vr1 vr2 vr3 vr4 vr5 vr6 vr7 */ \
+ 52, 53, 54, 55, 56, 57, 58, 59, \
+/* vr8 vr9 vr10 vr11 vr12 vr13 vr14 vr15 */ \
+ 60, 61, 62, 63, 64, 65, 66, 67, \
+/* reserved */ \
+ 36, 37, 38, 39, 40, 41, 42, 43, \
+ 44, 45, 46, 47, 48, 49, 50, 51, \
+/* sp tls reserved c reserved epc */ \
+ 14, 31, 32, 33, 68, 69, 70 }
+
+/* Register classes. */
+enum reg_class
+{
+ NO_REGS,
+ MINI_REGS,
+ SP_REGS,
+ LOW_REGS,
+ GENERAL_REGS,
+ C_REGS,
+ HI_REGS,
+ LO_REGS,
+ HILO_REGS,
+ V_REGS,
+ OTHER_REGS,
+ RESERVE_REGS,
+ ALL_REGS,
+ LIM_REG_CLASSES
+};
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+/* Give names of register classes as strings for dump file. */
+#define REG_CLASS_NAMES \
+{ \
+ "NO_REGS", \
+ "MINI_REGS", \
+ "SP_REGS", \
+ "LOW_REGS", \
+ "GENERAL_REGS", \
+ "C_REGS", \
+ "HI_REGS", \
+ "LO_REGS", \
+ "HILO_REGS", \
+ "V_REGS", \
+ "OTHER_REGS", \
+ "RESERVE_REGS", \
+ "ALL_REGS", \
+}
+
+/* Define which registers fit in which classes. This is an initializer
+ for a vector of HARD_REG_SET of length N_REG_CLASSES. */
+#define REG_CLASS_CONTENTS \
+{ \
+ {0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \
+ {0x000000FF, 0x00000000, 0x00000000 }, /* MINI_REGS */ \
+ {0x00004000, 0x00000000, 0x00000000 }, /* SP_REGS */ \
+ {0x0000FFFF, 0x00000000, 0x00000000 }, /* LOW_REGS */ \
+ {0xFFFFFFFF, 0x00000000, 0x00000000 }, /* GENERAL_REGS */ \
+ {0x00000000, 0x00000002, 0x00000000 }, /* C_REGS */ \
+ {0x00000000, 0x00000004, 0x00000000 }, /* HI_REG */ \
+ {0x00000000, 0x00000008, 0x00000000 }, /* LO_REG */ \
+ {0x00000000, 0x0000000c, 0x00000000 }, /* HILO_REGS */ \
+ {0x00000000, 0xFFF00000, 0x0000000F }, /* V_REGS */ \
+ {0x00000000, 0x00000000, 0x00000040 }, /* OTHER_REGS */ \
+ {0x00000000, 0x0FF00001, 0x00000030 }, /* RESERVE_REGS */ \
+ {0xFFFFFFFF, 0xFFFFFFFF, 0x0000007F }, /* ALL_REGS */ \
+}
+
+/* Return register class from regno. */
+extern enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];
+#define REGNO_REG_CLASS(REGNO) regno_reg_class[REGNO]
+
+/* The class value for index registers, and the one for base regs. */
+#define INDEX_REG_CLASS (CSKY_ISA_FEATURE (2E3) ? GENERAL_REGS : NO_REGS)
+#define BASE_REG_CLASS GENERAL_REGS
+
+/* TODO is it necessary to set it to MINI_REGS to emit more 16-bit
+ instructions? */
+#define MODE_BASE_REG_CLASS(MODE) GENERAL_REGS
+
+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
+ and check its validity for a certain class.
+ We have two alternate definitions for each of them.
+ The usual definition accepts all pseudo regs; the other rejects
+ them unless they have been allocated suitable hard regs.
+ The symbol REG_OK_STRICT causes the latter definition to be used.
+
+ Most source files want to accept pseudo regs in the hope that
+ they will get allocated to the class that the insn wants them to be in.
+ Source files for reload pass need to be strict.
+ After reload, it makes no difference, since pseudo regs have
+ been eliminated by then.
+
+ The reg_renumber is used to map pseudo regs into hardware
+ regs, it is set up as a result of register allocation. */
+#ifdef REG_OK_STRICT
+#define REGNO_OK_FOR_BASE_P(REGNO) \
+ (CSKY_GENERAL_REGNO_P (REGNO) \
+ || CSKY_GENERAL_REGNO_P (reg_renumber[(REGNO)]) )
+#else
+#define REGNO_OK_FOR_BASE_P(REGNO) \
+ (CSKY_GENERAL_REGNO_P (REGNO) \
+ || (REGNO) >= FIRST_PSEUDO_REGISTER)
+#endif
+
+
+#ifdef REG_OK_STRICT
+#define REGNO_OK_FOR_INDEX_P(REGNO) \
+ (CSKY_GENERAL_REGNO_P (REGNO) \
+ || CSKY_GENERAL_REGNO_P (reg_renumber[(REGNO)]) )
+#else
+#define REGNO_OK_FOR_INDEX_P(REGNO) \
+ (CSKY_GENERAL_REGNO_P (REGNO) \
+ || (REGNO) >= FIRST_PSEUDO_REGISTER)
+#endif
+
+
+/******************************************************************
+ * Addressing Modes *
+ ******************************************************************/
+
+
+/* Recognize any constant value that is a valid address. */
+#define CONSTANT_ADDRESS_P(X) \
+ (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF)
+
+/* Maximum number of registers that can appear in a valid memory address.
+ Shifts in addresses can't be by a register. */
+#define MAX_REGS_PER_ADDRESS 2
+
+
+/******************************************************************
+ * Run-time Target *
+ ******************************************************************/
+
+
+#define TARGET_CPU_CPP_BUILTINS() \
+ csky_cpu_cpp_builtins (pfile)
+
+/******************************************************************
+ * Per-function Data *
+ ******************************************************************/
+
+
+/* Initialize data used by insn expanders. This is called from insn_emit,
+ once for every function before code is generated. */
+#define INIT_EXPANDERS csky_init_expanders ()
+
+
+/******************************************************************
+ * Dividing the Output into Sections (Texts, Data, . . . ) *
+ ******************************************************************/
+
+
+/* Switch to the text or data segment. */
+#define TEXT_SECTION_ASM_OP "\t.text"
+#define DATA_SECTION_ASM_OP "\t.data"
+
+/* The subroutine calls in the .init and .fini sections create literal
+ pools which must be jumped around... */
+#define FORCE_CODE_SECTION_ALIGN \
+ asm ("br 1f ; .literals ; .align 2 ; 1:");
+
+/* Define this macro to be an expression with a nonzero value if
+ jump tables (for tablejump insns) should be output in the text section,
+ along with the assembler instructions. */
+#define JUMP_TABLES_IN_TEXT_SECTION TARGET_CASESI
+
+
+/******************************************************************
+ * Assembler Format *
+ ******************************************************************/
+
+
+/* A C string constant for text to be output before(after) each asm
+ statement or group of consecutive ones. */
+#undef ASM_APP_ON
+#define ASM_APP_ON "// inline asm begin\n"
+#undef ASM_APP_OFF
+#define ASM_APP_OFF "// inline asm end\n"
+
+/* A C string constant describing how to begin a comment in the target
+ assembler language. */
+#define ASM_COMMENT_START "\t//"
+
+/* This says how to output an assembler line
+ to define a global common symbol, with alignment information. */
+#undef ASM_OUTPUT_ALIGNED_COMMON
+#define ASM_OUTPUT_ALIGNED_COMMON(STREAM, NAME, SIZE, ALIGN) \
+ do \
+ { \
+ fputs ("\t.comm\t", STREAM); \
+ assemble_name (STREAM, NAME); \
+ fprintf (STREAM, ",%lu, %u\n", (unsigned long)(SIZE), \
+ (ALIGN) / BITS_PER_UNIT); \
+ } \
+while (0)
+
+/* Define a local common symbol whose alignment we wish to specify.
+ ALIGN comes in as bits, we have to turn it into bytes. */
+#undef ASM_OUTPUT_ALIGNED_LOCAL
+#define ASM_OUTPUT_ALIGNED_LOCAL(STREAM, NAME, SIZE, ALIGN) \
+ do \
+{ \
+ fputs ("\t.bss\t", (STREAM)); \
+ assemble_name ((STREAM), (NAME)); \
+ fprintf ((STREAM), ",%d, %d\n", (int)(SIZE), \
+ (ALIGN) / BITS_PER_UNIT); \
+} \
+while (0)
+
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP "\t.global\t"
+
+/* Output a reference to a label. */
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
+ fprintf (STREAM, "%s%s", user_label_prefix, \
+ (* targetm.strip_name_encoding) (NAME))
+
+/* Make an internal label into a string. */
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM) \
+ sprintf (STRING, "*.%s%ld", PREFIX, (long) NUM)
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+#define ASM_OUTPUT_REG_PUSH(STREAM,REGNO) \
+ fprintf (STREAM, "\tsubi\t %s,%d\n\tst.w\t %s,(%s)\n", \
+ reg_names[STACK_POINTER_REGNUM], \
+ (STACK_BOUNDARY / BITS_PER_UNIT), \
+ reg_names[REGNO], \
+ reg_names[STACK_POINTER_REGNUM])
+
+/* This is how to output an insn to pop a register from the stack. */
+#define ASM_OUTPUT_REG_POP(STREAM,REGNO) \
+ fprintf (STREAM, "\tld.w\t %s,(%s)\n\taddi\t %s,%d\n", \
+ reg_names[REGNO], \
+ reg_names[STACK_POINTER_REGNUM], \
+ reg_names[STACK_POINTER_REGNUM], \
+ (STACK_BOUNDARY / BITS_PER_UNIT))
+
+/* Output an element of a dispatch table. */
+#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE) \
+ fprintf (STREAM, "\t.long\t.L%d\n", VALUE)
+
+/* This is how to output an assembler line
+ that says to advance the location counter by SIZE bytes. */
+#undef ASM_OUTPUT_SKIP
+#define ASM_OUTPUT_SKIP(STREAM,SIZE) \
+ fprintf (STREAM, "\t.fill %d, 1\n", (int)(SIZE))
+
+/* Align output to a power of two. Note ".align 0" is redundant,
+ and also GAS will treat it as ".align 2" which we do not want. */
+#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
+ do \
+ { \
+ if ((POWER) > 0) \
+ fprintf (STREAM, "\t.align\t%d\n", POWER); \
+ } \
+ while (0)
+
+
+/******************************************************************
+ * Controlling the Compilation Driver *
+ ******************************************************************/
+
+
+/* Define this macro as a C expression for the initializer of an
+ array of string to tell the driver program which options are
+ defaults for this target and thus do not need to be handled
+ specially when using MULTILIB_OPTIONS. */
+#undef MULTILIB_DEFAULTS
+#define MULTILIB_DEFAULTS \
+ {"mlittle-endian", "mcpu=ck810f", "msoft-float"}
+
+/* Support for a compile-time default CPU, et cetera. The rules are:
+ --with-arch is ignored if -march or -mcpu are specified.
+ --with-cpu is ignored if -march or -mcpu are specified, and is overridden
+ by --with-arch. */
+#define OPTION_DEFAULT_SPECS \
+ {"arch", "%{!march=*:%{!mcpu=*:-march=%(VALUE)}}" }, \
+ {"cpu", "%{!march=*:%{!mcpu=*:-mcpu=%(VALUE)}}" }, \
+ {"endian", "%{!mbig-endian:%{!mlittle-endian:-m%(VALUE)-endian}}" }, \
+ {"float", "%{!msoft-float:%{!mhard-float:-m%(VALUE)-float}}" },
+
+
+/******************************************************************
+ * Position Independent Code *
+ ******************************************************************/
+
+/* Define the global table register. */
+#define PIC_OFFSET_TABLE_REGNUM (flag_pic ? CSKY_GB_REGNUM : INVALID_REGNUM)
+
+/* Nonzero if x is a legitimate immediate operand on the target machine
+ when generating position-independent code. */
+#define LEGITIMATE_PIC_OPERAND_P(X) \
+ csky_legitimate_pic_operand_p (X)
+
+
+/******************************************************************
+ * Controlling Debugging Information Format *
+ ******************************************************************/
+
+
+/* Define this macro if GCC should produce dwarf version 2 format debugging
+ output in response to the `-g' option. */
+#define DWARF2_DEBUGGING_INFO 1
+
+/* Define this macro to 0 if your target supports DWARF 2 frame unwind
+ information, but it does not yet work with exception handling. */
+#define DWARF2_UNWIND_INFO 1
+
+/* Define this if you have arranged for GCC to support
+ more than one format of debugging output.
+ The value of this macro only affects the default debugging output. */
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+/* Define this macro if the target’s representation
+ for dwarf registers used in .eh_frame or .debug_frame
+ is different from that used in other debug info sections.
+ Given a GCC hard register number,
+ this macro should return the .eh_frame register number.*/
+#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG)
+
+/* If INCOMING_RETURN_ADDR_RTX is defined & the RTL is REG,
+ define DWARF_FRAME_RETURN_COLUMN to DWARF_FRAME_REGNUM. */
+#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (CSKY_LR_REGNUM)
+
+/* Use r0 and r1 to pass exception handling information. */
+#define EH_RETURN_DATA_REGNO(N) ((N) < 2 ? N : INVALID_REGNUM)
+
+/* How to renumber registers for dbx and gdb. */
+extern const int csky_dbx_regno[];
+#define DBX_REGISTER_NUMBER(REGNO) ((unsigned int) csky_dbx_regno[REGNO])
+
+
+/******************************************************************
+ * Miscellaneous Parameters *
+ ******************************************************************/
+
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction. */
+#define CASE_VECTOR_MODE SImode
+
+/* Define if operations between registers always perform the operation
+ on the full register even if a narrower mode is specified. */
+#define WORD_REGISTER_OPERATIONS 1
+
+/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD
+ will either zero-extend or sign-extend. The value of this macro should
+ be the code that says which one of the two operations is implicitly
+ done, UNKNOWN if none. */
+#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
+
+/* Max number of bytes we can move from memory to memory
+ in one reasonably fast instruction. */
+#define MOVE_MAX 4
+
+/* Shift counts are truncated to 6-bits (0 to 63) instead of the expected
+ 5-bits, so we can not define SHIFT_COUNT_TRUNCATED to true for this
+ target. */
+#define SHIFT_COUNT_TRUNCATED 0
+
+#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
+
+/* The machine modes of pointers and functions. */
+#define Pmode SImode
+#define FUNCTION_MODE Pmode
+
+/* Define this macro to be a C expression to indicate when jump-tables
+ should contain relative addresses. */
+#define CASE_VECTOR_PC_RELATIVE \
+ (optimize_size && TARGET_CONSTANT_POOL \
+ && (CSKY_TARGET_ARCH (CK802) || CSKY_TARGET_ARCH (CK801)))
+
+/* Return the preferred mode for an addr_diff_vec when the minimum
+ and maximum offset are known. */
+#define CASE_VECTOR_SHORTEN_MODE(min, max, body) \
+ (min >= 0 && max < 512 \
+ ? (ADDR_DIFF_VEC_FLAGS (body).offset_unsigned = 1, QImode) \
+ : min >= -256 && max < 256 \
+ ? (ADDR_DIFF_VEC_FLAGS (body).offset_unsigned = 0, QImode) \
+ : min >= 0 && max < 8192 \
+ ? (ADDR_DIFF_VEC_FLAGS (body).offset_unsigned = 1, HImode) \
+ : min >= -4096 && max < 4096 \
+ ? (ADDR_DIFF_VEC_FLAGS (body).offset_unsigned = 0, HImode) \
+ : SImode)
+
+/* This is how to output an element of a case-vector that is relative. */
+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
+ do \
+ { \
+ if (optimize_size && TARGET_CONSTANT_POOL \
+ && (CSKY_TARGET_ARCH (CK802) || CSKY_TARGET_ARCH (CK801))) \
+ { \
+ switch (GET_MODE (BODY)) \
+ { \
+ case E_QImode: \
+ asm_fprintf (STREAM, "\t.byte\t(.L%d-.L%d)/2\n", \
+ VALUE, REL); \
+ break; \
+ case E_HImode: /* TBH */ \
+ asm_fprintf (STREAM, "\t.short\t(.L%d-.L%d)/2\n", \
+ VALUE, REL); \
+ break; \
+ case E_SImode: \
+ asm_fprintf (STREAM, "\t.long\t.L%d-.L%d\n", \
+ VALUE, REL); \
+ break; \
+ default: \
+ gcc_unreachable (); \
+ } \
+ } \
+ else \
+ asm_fprintf (STREAM, "\t.long\t.L%d@GOTOFF\n", VALUE); \
+ } while (0)
+
+/* This macro is not documented yet.
+ But we do need it to make jump table vector aligned. */
+#define ADDR_VEC_ALIGN(JUMPTABLE) 0
+
+/* We have to undef this first to override the version from elfos.h. */
+#undef ASM_OUTPUT_CASE_LABEL
+#define ASM_OUTPUT_CASE_LABEL(stream, prefix, num, table) \
+ do \
+ { \
+ if (GET_MODE (PATTERN (table)) == SImode) \
+ ASM_OUTPUT_ALIGN (stream, 2); \
+ (*targetm.asm_out.internal_label) (stream, prefix, num); \
+ } while (0)
+
+/* Make sure subsequent insns are aligned after a byte-sized jump offset
+ table. */
+#define ASM_OUTPUT_CASE_END(stream, num, table) \
+ do \
+ { \
+ if (GET_MODE (PATTERN (table)) == QImode) \
+ ASM_OUTPUT_ALIGN (stream, 1); \
+ } while (0)
+
+
+
+
+/******************************************************************
+ * Trampolines for Nested Functions *
+ ******************************************************************/
+
+
+/* Length in units of the trampoline for entering a nested function. */
+#define TRAMPOLINE_SIZE (CSKY_ISA_FEATURE (2E3) ? 16 : 20)
+
+/* Alignment required for a trampoline in bits. */
+#define TRAMPOLINE_ALIGNMENT 32
+
+
+/******************************************************************
+ * Describing Relative Costs of Operations *
+ ******************************************************************/
+
+
+/* Nonzero if access to memory by bytes is slow and undesirable.
+ For RISC chips, it means that access to memory by bytes is no
+ better than access by words when possible, so grab a whole word
+ and maybe make use of that. */
+#define SLOW_BYTE_ACCESS 0
+
+/* On C-SKY, function CSE would allow use of 16-bit jsr instructions
+ instead of normal 32-bit calls. But it also needs a separate constant
+ pool entry for the function address and an instruction to load it, and
+ may cause additional spills due to increased register pressure, etc.
+ It doesn't seem like a good idea overall. */
+#define NO_FUNCTION_CSE 1
+
+/* Try to generate sequences that don't involve branches, we can then use
+ conditional instructions. */
+#define BRANCH_COST(speed_p, predictable_p) \
+ csky_default_branch_cost (speed_p, predictable_p)
+
+/* False if short circuit operation is preferred. */
+#define LOGICAL_OP_NON_SHORT_CIRCUIT \
+ (csky_default_logical_op_non_short_circuit ())
+
+
+/******************************************************************
+ * Generating Code for Profiling *
+ ******************************************************************/
+
+
+#define FUNCTION_PROFILER(FILE, LABELNO)
+
+#endif /* GCC_CSKY_H */
diff --git a/gcc/config/csky/csky.md b/gcc/config/csky/csky.md
new file mode 100644
index 0000000..cde2bd6
--- /dev/null
+++ b/gcc/config/csky/csky.md
@@ -0,0 +1,3798 @@
+;; Machine description for C-SKY processors.
+;; Copyright (C) 2018 Free Software Foundation, Inc.
+;; Contributed by C-SKY Microsystems and Mentor Graphics.
+;;
+;; 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/>. */
+
+
+;; ------------------------------------------------------------------------
+;; Constant
+;; ------------------------------------------------------------------------
+
+;; Register numbering.
+
+(define_constants
+ [(CSKY_NGPR_REGS 32)
+ (CSKY_NPARM_REGS 4)
+ (CSKY_FIRST_PARM_REGNUM 0)
+ (CSKY_FIRST_RET_REGNUM 0)
+ (CSKY_FIRST_VFP_REGNUM 52)
+ (CSKY_LAST_VFP_REGNUM 67)
+ (CSKY_FIRST_HIGH_REGNUM 16)
+ (CSKY_LAST_HIGH_REGNUM 31)
+ (CSKY_FIRST_MINI_REGNUM 0)
+ (CSKY_LAST_MINI_REGNUM 7)
+ (CSKY_T0_REGNUM 12)
+ (CSKY_T1_REGNUM 13)
+ (CSKY_SP_REGNUM 14)
+ (CSKY_CC_REGNUM 33)
+ (CSKY_HI_REGNUM 34)
+ (CSKY_LO_REGNUM 35)
+ (CSKY_LR_REGNUM 15)
+ (CSKY_LAST_HIGH_UNFIXED_REGNUM 25)
+ (CSKY_GB_REGNUM 28)
+ (CSKY_TLS_REGNUM 31)
+ (CSKY_FIRST_EH_RETDATA_REGNUM 0)
+ (CSKY_LAST_EH_RETDATA_REGNUM 1)
+ (CSKY_EH_STACKADJ_REGNUM 2)
+ (CSKY_STACKADJUST_REGNUM 4)
+])
+
+;; Supported TLS relocations.
+
+(define_constants
+ [(TLS_GD32 0)
+ (TLS_LDM32 1)
+ (TLS_LDO32 2)
+ (TLS_IE32 3)
+ (TLS_LE32 4)
+])
+
+;; Unspec constants.
+
+(define_c_enum "unspec"
+ [
+ ; Push or pop multiple operation: operand 0 is the first register,
+ ; subsequent registers are in parallel (use ...) expressions.
+ UNSPEC_PUSHPOP_MULT
+
+ ; Represent TLS base, TLS offset, and TLS base + offset, respectively.
+ UNSPEC_TLS_BASE
+ UNSPEC_TLS_LABEL
+ UNSPEC_TLS
+
+ ; PIC symbol relocations.
+ UNSPEC_PIC_SYMBOL_GOTPC
+ UNSPEC_PIC_SYMBOL_GOTPC_GRS
+ UNSPEC_PIC_SYMBOL_GOTOFF
+ UNSPEC_PIC_SYMBOL_GOT
+ UNSPEC_PIC_SYMBOL_PLT
+ UNSPEC_PIC_SYMBOL_BSR
+ UNSPEC_PIC_SYMBOL_GRS
+
+ ; casesi dispatch table.
+ UNSPEC_CSKY_CASESI
+ ])
+
+
+(define_c_enum "unspecv"
+ [
+ ; Used for constant pools.
+ VUNSPEC_ALIGN
+ VUNSPEC_POOL_LABEL
+ VUNSPEC_POOL_4
+ VUNSPEC_POOL_8
+ VUNSPEC_SYMBOL_REF
+
+ ; Support for the eh_return pattern.
+ VUNSPEC_EH_RETURN
+ ])
+
+
+;; ------------------------------------------------------------------------
+;; Attributes
+;; ------------------------------------------------------------------------
+
+;; LENGTH of an instruction (in bytes).
+
+(define_attr "length" ""
+ (if_then_else (match_test "CSKY_TARGET_ARCH (CK801)")
+ (const_int 2)
+ (const_int 4)))
+
+;; Used for ck801 to represent whether we need to use bsr for long
+;; distance jumps. If set to yes, the function will save lr in the
+;; prologue.
+
+(define_attr "far_jump" "yes,no" (const_string "no"))
+
+;; Used for insn schedule.
+
+(define_attr "type"
+ "alu,load,store,cmp,branch,cbranch,addsub,alu_ix,branch_jmp,call_jsr,call"
+ (const_string "alu"))
+
+
+;; ------------------------------------------------------------------------
+;; Include files
+;; ------------------------------------------------------------------------
+
+(include "constraints.md")
+(include "predicates.md")
+(include "csky_insn_fpu.md")
+(include "csky_insn_dsp.md")
+(include "csky_pipeline_ck801.md")
+(include "csky_pipeline_ck802.md")
+(include "csky_pipeline_ck803.md")
+(include "csky_pipeline_ck810.md")
+
+;; ------------------------------------------------------------------------
+;; Mov insns
+;; ------------------------------------------------------------------------
+
+(define_mode_iterator QHI [QI HI])
+
+(define_expand "movsi"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (match_operand:SI 1 "general_operand" ""))]
+ ""
+ "
+ {
+ rtx scratch = !can_create_pseudo_p () ? operands[0] : 0;
+ if (can_create_pseudo_p () && MEM_P (operands[0]))
+ {
+ operands[1] = force_reg (SImode, operands[1]);
+ emit_insn (gen_rtx_SET (operands[0], operands[1]));
+ DONE;
+ }
+
+ /* Recognize the case where operand[1] is a reference to thread-local
+ data and load its address to a register. */
+ if (csky_tls_referenced_p (operands[1]))
+ {
+ rtx tmp = operands[1];
+ rtx addend = NULL;
+
+ if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
+ {
+ addend = XEXP (XEXP (tmp, 0), 1);
+ tmp = XEXP (XEXP (tmp, 0), 0);
+ }
+
+ gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
+ gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
+
+ tmp = csky_legitimize_tls_address (tmp, scratch);
+ if (addend)
+ {
+ tmp = gen_rtx_PLUS (SImode, tmp, addend);
+ tmp = force_operand (tmp, operands[0]);
+ }
+ operands[1] = tmp;
+ }
+ else if (flag_pic
+ && (CONSTANT_P (operands[1])
+ || csky_symbol_mentioned_p (operands[1])
+ || csky_label_mentioned_p (operands[1])))
+ operands[1] = csky_legitimize_pic_address (operands[1], scratch, true);
+ }"
+)
+
+;; Note that we conservatively estimate all load and store insns as having
+;; a size of 4 bytes throughout even though some variants can be encoded
+;; as 2-byte machine instructions. Getting more accurate instruction counts
+;; would be better handled by calling into a C function than encoding it
+;; as an RTL conditional here.
+;; Also note that we don't count the extra space required for constant
+;; pool entries here; that's handled by the constant pool entries themselves.
+;; In -mno-constpool cases where we're relying on the assembler to create
+;; the constant pool, we'll undercount branch lengths, but in that case the
+;; assembler also handles branch relaxation as needed. It's only ck801 that
+;; requires compiler cooperation when long branches are needed.
+
+(define_insn "*cskyv2_movsi"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=b,r,r,r, r, r, r,r, m,r,*y,*r,*v,*r,*v")
+ (match_operand:SI 1 "general_operand" " b,r,I,Un,Uc,Uo,m,miF,r,c,*r,*y,*r,*v,*v"))]
+ "CSKY_ISA_FEATURE (E2)"
+ "* return csky_output_move (insn, operands, SImode);"
+ [(set_attr "length" "2,4,4,4,4,8,4,4,4,4,4,4,4,4,4")
+ (set_attr "type" "alu,alu,alu,alu,alu,alu,load,load,store,alu,alu,alu,alu,alu,alu")]
+)
+
+(define_insn "*ck801_movsi"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,a, a,r,r, m,r")
+ (match_operand:SI 1 "general_operand" "r, Up,T,m,miF,r,c"))]
+ "CSKY_ISA_FEATURE (E1)"
+ "* return csky_output_ck801_move (insn, operands, SImode);"
+ [(set_attr "length" "2,2,2,4,4,4,2")
+ (set_attr "type" "alu,alu,alu,load,load,store,alu")]
+)
+
+;; Convert negative assignments to zero minus positive numbers.
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "const_int_operand" ""))]
+ "satisfies_constraint_T (operands[1])"
+ [(set (match_dup 0) (match_dup 2))
+ (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
+ "operands[2] = const0_rtx;"
+)
+
+;; Convert const assignments to small number of assignments and left shift.
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "const_int_operand" ""))]
+ ""
+ [(set (match_dup 0) (match_dup 1))
+ (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
+ "
+ {
+ unsigned int base, shift;
+
+ if (!csky_shifted_imm8_constant (INTVAL (operands[1]), &base, &shift))
+ FAIL;
+ if (shift == 0)
+ FAIL;
+ operands[1] = GEN_INT (base);
+ operands[2] = GEN_INT (shift);
+ }"
+)
+
+
+(define_expand "movhi"
+ [(set (match_operand:HI 0 "general_operand" "")
+ (match_operand:HI 1 "general_operand" ""))]
+ ""
+ "
+ {
+ if (GET_CODE (operands[0]) == MEM)
+ operands[1] = force_reg (HImode, operands[1]);
+ else if (CONSTANT_P (operands[1])
+ && (GET_CODE (operands[1]) != CONST_INT
+ || (! CSKY_CONST_OK_FOR_I (INTVAL (operands[1]))
+ && ! CSKY_CONST_OK_FOR_Ub (INTVAL (operands[1]))
+ && ! CSKY_CONST_OK_FOR_Uc (INTVAL (operands[1]))))
+ && ! reload_completed && ! reload_in_progress)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+ emit_insn (gen_movsi (reg, operands[1]));
+ operands[1] = gen_lowpart (HImode, reg);
+ }
+ }"
+)
+
+(define_insn "*cskyv2_movhi"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=b,r,r,r, r, r, r,r, m,r,*y,*r,*v,*r,*v")
+ (match_operand:HI 1 "general_operand" " b,r,I,Un,Uc,Uo,m,miF,r,c,*r,*y,*r,*v,*v"))]
+ "CSKY_ISA_FEATURE (E2)"
+ "* return csky_output_move (insn, operands, HImode);"
+ [(set_attr "length" "2,4,4,4,4,8,4,4,4,4,4,4,4,4,4")
+ (set_attr "type" "alu,alu,alu,alu,alu,alu,load,load,store,alu,alu,alu,alu,alu,alu")]
+)
+
+(define_insn "*ck801_movhi"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,a, a,r,r, m,r")
+ (match_operand:HI 1 "general_operand" "r, Up,T,m,miF,r,c"))]
+ "CSKY_ISA_FEATURE (E1)"
+ "* return csky_output_ck801_move (insn, operands, HImode);"
+ [(set_attr "length" "2,2,2,4,4,4,2")
+ (set_attr "type" "alu,alu,alu,load,load,store,alu")]
+)
+
+
+(define_expand "movqi"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (match_operand:QI 1 "general_operand" ""))]
+ ""
+ "
+ {
+ if (can_create_pseudo_p () && GET_CODE (operands[0]) == MEM)
+ operands[1] = force_reg (QImode, operands[1]);
+ else if (CONSTANT_P (operands[1])
+ && (GET_CODE (operands[1]) != CONST_INT
+ || (! CSKY_CONST_OK_FOR_I (INTVAL (operands[1]))
+ && ! CSKY_CONST_OK_FOR_Ub (INTVAL (operands[1]))
+ && ! CSKY_CONST_OK_FOR_Uc (INTVAL (operands[1]))))
+ && ! reload_completed && ! reload_in_progress)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+ emit_insn (gen_movsi (reg, operands[1]));
+ operands[1] = gen_lowpart (QImode, reg);
+ }
+ }"
+)
+
+(define_insn "*cskyv2_movqi"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=b,r,r,r, r, r, r,r, m,r,*y,*r,*v,*r,*v")
+ (match_operand:QI 1 "general_operand" " b,r,I,Un,Uc,Uo,m,miF,r,c,*r,*y,*r,*v,*v"))]
+ "CSKY_ISA_FEATURE (E2)"
+ "* return csky_output_move (insn, operands, QImode);"
+ [(set_attr "length" "2,4,4,4,4,8,4,4,4,4,4,4,4,4,4")
+ (set_attr "type" "alu,alu,alu,alu,alu,alu,load,load,store,alu,alu,alu,alu,alu,alu")]
+)
+
+(define_insn "*ck801_movqi"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=r,a, a,r,r, m,r")
+ (match_operand:QI 1 "general_operand" "r, Up,T,m,miF,r,c"))]
+ "CSKY_ISA_FEATURE (E1)"
+ "* return csky_output_ck801_move (insn, operands, QImode);"
+ [(set_attr "length" "2,2,2,4,4,4,2")
+ (set_attr "type" "alu,alu,alu,load,load,store,alu")]
+)
+
+
+(define_expand "movdi"
+ [(set (match_operand:DI 0 "general_operand" "")
+ (match_operand:DI 1 "general_operand" ""))]
+ ""
+ "if (can_create_pseudo_p () && GET_CODE (operands[0]) == MEM)
+ operands[1] = force_reg (DImode, operands[1]);"
+)
+
+;; Convert negative assignments to zero minus positive numbers.
+(define_split
+ [(set (match_operand:QHI 0 "register_operand" "")
+ (match_operand:QHI 1 "const_int_operand" ""))]
+ "satisfies_constraint_T (operands[1])"
+ [(set (match_dup 4) (match_dup 2))
+ (set (match_dup 4) (match_dup 3))
+ (set (match_dup 0) (match_dup 5))]
+ "
+ {
+ int low;
+
+ if (TARGET_BIG_ENDIAN)
+ low = 4 - mode_size[GET_MODE (operands[0])];
+ else
+ low = 0;
+ operands[2] = const0_rtx;
+ if (can_create_pseudo_p ())
+ operands[4] = gen_reg_rtx (SImode);
+ else
+ operands[4] = gen_rtx_REG (SImode, REGNO (operands[0]));
+ operands[3] = gen_rtx_PLUS (SImode, operands[4], operands[1]);
+ operands[5] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[4], low);
+ }"
+)
+
+;; Convert const assignments to small number of assignments and left shift.
+(define_split
+ [(set (match_operand:QHI 0 "register_operand" "")
+ (match_operand:QHI 1 "const_int_operand" ""))]
+ ""
+ [(set (match_dup 3) (match_dup 1))
+ (set (match_dup 3) (ashift:SI (match_dup 3) (match_dup 2)))
+ (set (match_dup 0) (match_dup 4))]
+ "
+ {
+ unsigned int base, shift;
+ int low;
+
+ if (!csky_shifted_imm8_constant (INTVAL (operands[1]), &base, &shift))
+ FAIL;
+ if (shift == 0)
+ FAIL;
+
+ if (TARGET_BIG_ENDIAN)
+ low = 4 - mode_size[GET_MODE (operands[0])];
+ else
+ low = 0;
+
+ operands[1] = GEN_INT (base);
+ operands[2] = GEN_INT (shift);
+ if (can_create_pseudo_p ())
+ operands[3] = gen_reg_rtx (SImode);
+ else
+ operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
+ operands[4] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[3], low);
+ }"
+)
+
+
+(define_insn "*csky_movdi"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=b,r,r, r,r, m,*r,*y,*v,*r,*v")
+ (match_operand:DI 1 "general_operand" " b,r,Ud,m,miF,r,*y,*r,*r,*v,*v"))]
+ "CSKY_ISA_FEATURE (E2)"
+ "* return csky_output_movedouble (operands, DImode);"
+ [(set_attr "length" "4,8,8,8,8,8,16,16,16,16,16")
+ (set_attr "type" "alu,alu,alu,load,load,store,alu,alu,alu,alu,alu")]
+)
+
+(define_insn "*ck801_movdi"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,a, a,r,r, m")
+ (match_operand:DI 1 "general_operand" "r, Up,T,m,miF,r"))]
+ "CSKY_ISA_FEATURE (E1)"
+ "* return csky_output_ck801_movedouble (operands, DImode);"
+ [(set_attr "length" "4,4,4,8,8,8")
+ (set_attr "type" "alu,alu,alu,load,load,store")]
+)
+
+;; Float mov instructions.
+
+(define_expand "movsf"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (match_operand:SF 1 "general_operand" ""))]
+ ""
+ "
+ if (GET_CODE (operands[0]) == MEM && can_create_pseudo_p ())
+ operands[1] = force_reg (SFmode, operands[1]);
+ "
+)
+
+;; FIXME: maybe the vreg load/stores should have their own type attr.
+(define_insn "*csky_movsf_fpv2"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=b,r,v,r,r,r, m,Q,v,v,v")
+ (match_operand:SF 1 "general_operand" " b,r,r,v,m,mF,r,v,Q,v,m"))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "* return csky_output_move (insn, operands, SFmode);"
+ [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4")
+ (set_attr "type" "alu,alu,alu,alu,load,load,store,alu,alu,alu,alu")]
+)
+
+(define_insn "*ck801_movsf"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r, m")
+ (match_operand:SF 1 "general_operand" " r,m,mF,r"))]
+ "CSKY_ISA_FEATURE (E1)"
+ "* return csky_output_ck801_move (insn, operands, SFmode);"
+ [(set_attr "length" "2,4,4,4")
+ (set_attr "type" "alu,load,load,store")]
+)
+
+(define_insn "*csky_movsf"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=b,r,r,r, m")
+ (match_operand:SF 1 "general_operand" " b,r,m,mF,r"))]
+ "CSKY_ISA_FEATURE (E2) && !CSKY_ISA_FEATURE (fpv2_sf)"
+ "* return csky_output_move (insn, operands, SFmode);"
+ [(set_attr "length" "2,4,4,4,4")
+ (set_attr "type" "alu,alu,load,load,store")]
+)
+
+
+(define_expand "movdf"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (match_operand:DF 1 "general_operand" ""))]
+ ""
+ "
+ if (GET_CODE (operands[0]) == MEM && can_create_pseudo_p ())
+ operands[1] = force_reg (DFmode, operands[1]);
+ "
+)
+
+;; FIXME: maybe the vreg load/stores should have their own type attr.
+(define_insn "*csky_movdf_fpv2"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=b,r,v,r,r,r, m,Q,v,v,v")
+ (match_operand:DF 1 "general_operand" "b,r,r,v,m,mF,r,v,Q,v,m"))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "* return csky_output_movedouble (operands, DFmode);"
+ [(set_attr "length" "4,8,8,8,8,8,8,8,8,8,8")
+ (set_attr "type" "alu,alu,alu,alu,load,load,store,alu,alu,alu,alu")]
+)
+
+(define_insn "*ck801_movdf"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,r, m")
+ (match_operand:DF 1 "general_operand" " r,m,mF,r"))]
+ "CSKY_ISA_FEATURE (E1)"
+ "* return csky_output_ck801_movedouble (operands, DFmode);"
+ [(set_attr "length" "4,8,8,8")
+ (set_attr "type" "alu,load,load,store")]
+)
+
+(define_insn "*csky_movdf"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=b,r,r,r, m")
+ (match_operand:DF 1 "general_operand" " b,r,m,mF,r"))]
+ "CSKY_ISA_FEATURE (E2) && !CSKY_ISA_FEATURE (fpv2_df)"
+ "* return csky_output_movedouble (operands, DFmode);"
+ [(set_attr "length" "4,8,8,8,8")
+ (set_attr "type" "alu,alu,load,load,store")]
+)
+
+;; The only CCmode move supported is a nop. Without this pattern,
+;; CSE is unable to eliminate redundant comparisons in conditional
+;; execution expressions.
+
+(define_insn "*movcc_nop"
+ [(set (reg:CC CSKY_CC_REGNUM) (reg:CC CSKY_CC_REGNUM))]
+ ""
+ ""
+ [(set_attr "length" "0")]
+)
+
+;; ------------------------------------------------------------------------
+;; Conditional mov insns
+;; ------------------------------------------------------------------------
+
+;; Only handle integer comparisons because float and double require
+;; library calls.
+
+(define_expand "movsicc"
+ [(set (match_operand 0 "register_operand" "")
+ (if_then_else:SI (match_operand 1 "ordered_comparison_operator" "")
+ (match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "register_operand" "")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "
+ {
+ bool invert = csky_emit_compare (GET_CODE (operands[1]),
+ XEXP (operands[1], 0),
+ XEXP (operands[1], 1));
+
+ if (invert)
+ emit_insn (gen_movf (operands[0], operands[2], operands[3]));
+ else
+ emit_insn (gen_movt (operands[0], operands[2], operands[3]));
+ DONE;
+ }")
+
+(define_insn "movt"
+ [(set (match_operand:SI 0 "register_operand" "=r, r")
+ (if_then_else:SI (ne (reg:CC CSKY_CC_REGNUM) (const_int 0))
+ (match_operand:SI 1 "register_operand" "r, 0")
+ (match_operand:SI 2 "register_operand" "0, r")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "@
+ movt\t%0, %1
+ movf\t%0, %2"
+ [(set_attr "length" "4,4")]
+)
+
+(define_insn "movf"
+ [(set (match_operand:SI 0 "register_operand" "=r, r")
+ (if_then_else:SI (eq (reg:CC CSKY_CC_REGNUM) (const_int 0))
+ (match_operand:SI 1 "register_operand" "r, 0")
+ (match_operand:SI 2 "register_operand" "0, r")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "@
+ movf\t%0, %1
+ movt\t%0, %2"
+ [(set_attr "length" "4,4")]
+)
+
+(define_expand "cstoresi4"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operator 1 "ordered_comparison_operator"
+ [(match_operand:SI 2 "csky_compare_operand" "")
+ (match_operand:SI 3 "nonmemory_operand" "")]))]
+ ""
+ "
+ {
+ bool invert = csky_emit_compare (GET_CODE (operands[1]),
+ operands[2], operands[3]);
+
+ if (invert)
+ emit_insn (gen_mvcv (operands[0]));
+ else if (CSKY_ISA_FEATURE (E1))
+ {
+ emit_insn (gen_movsi (operands[0], const0_rtx));
+ emit_insn (gen_ck801_addc (operands[0], operands[0], operands[0]));
+ }
+ else
+ emit_insn (gen_mvc (operands[0]));
+ DONE;
+ }"
+)
+
+(define_insn "mvc"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ne:SI (reg:CC CSKY_CC_REGNUM) (const_int 0)))]
+ "CSKY_ISA_FEATURE (E2)"
+ "mvc\t%0"
+)
+
+(define_insn "mvcv"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (eq:SI (reg:CC CSKY_CC_REGNUM) (const_int 0)))]
+ ""
+ "mvcv\t%0"
+)
+
+;; ------------------------------------------------------------------------
+;; Arithmetic insns
+;; ------------------------------------------------------------------------
+
+(define_insn "abssi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (abs:SI (match_operand:SI 1 "register_operand" "r")))]
+ "CSKY_ISA_FEATURE (2E3)"
+ "abs\t%0, %1"
+ [(set_attr "type" "alu")]
+)
+
+(define_insn "extvsi"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extract:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "")
+ (match_operand:SI 3 "const_int_operand" "")))]
+ "CSKY_ISA_FEATURE (2E3)"
+ {
+ operands[2] = GEN_INT (INTVAL (operands[3]) + INTVAL (operands[2]) - 1);
+ return \"sext\t%0, %1, %2, %3\";
+ }
+)
+
+(define_insn "insvsi"
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
+ (match_operand:SI 1 "const_int_operand" "i")
+ (match_operand:SI 2 "const_int_operand" "i"))
+ (match_operand:SI 3 "register_operand" "r"))]
+ "CSKY_ISA_FEATURE (2E3)"
+ {
+ operands[1] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[1]) - 1);
+ return \"ins\t%0, %3, %1, %2\";
+ }
+)
+
+(define_expand "bseti"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (ior:SI (match_operand:SI 1 "register_operand" "")
+ (ashift:SI (const_int 1)
+ (match_operand:SI 2 "csky_literal_K_operand" ""))))]
+ ""
+ "")
+
+(define_insn "smart_bseti"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (match_operand:SI 1 "register_operand" "0")
+ (ashift:SI (const_int 1)
+ (match_operand:SI 2 "csky_literal_K_operand" "K"))))]
+ "TARGET_MINI_REGISTERS"
+ "bseti\t%0, %2"
+ [(set_attr "length" "2")])
+
+(define_insn "fast_bseti"
+ [(set (match_operand:SI 0 "register_operand" "=a,r")
+ (ior:SI (match_operand:SI 1 "register_operand" "0,r")
+ (ashift:SI (const_int 1)
+ (match_operand:SI 2 "csky_literal_K_operand" "K,K"))))]
+ "!TARGET_MINI_REGISTERS"
+ "bseti\t%0, %1, %2"
+ [(set_attr "length" "2,4")])
+
+(define_expand "bclri"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (and:SI (match_operand:SI 1 "register_operand" "")
+ (not:SI (ashift:SI (const_int 1)
+ (match_operand:SI 2 "csky_literal_K_operand" "")))))]
+ ""
+ "")
+
+(define_insn "smart_bclri"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (match_operand:SI 1 "register_operand" "0")
+ (not:SI (ashift:SI (const_int 1)
+ (match_operand:SI 2 "csky_literal_K_operand" "K")))))]
+ "TARGET_MINI_REGISTERS"
+ "bclri\t%0, %2"
+ [(set_attr "length" "2")])
+
+(define_insn "fast_bclri"
+ [(set (match_operand:SI 0 "register_operand" "=a,r")
+ (and:SI (match_operand:SI 1 "register_operand" "0,r")
+ (not:SI (ashift:SI (const_int 1)
+ (match_operand:SI 2 "csky_literal_K_operand" "K,K")))))]
+ "!TARGET_MINI_REGISTERS"
+ "bclri\t%0, %1, %2"
+ [(set_attr "length" "2,4")])
+
+
+;; Shift instructions.
+
+(define_expand "ashlsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (ashift:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "csky_arith_K_operand" "")))]
+ ""
+ ""
+)
+
+(define_insn "*cskyv2_ashlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=b,r,a,r")
+ (ashift:SI (match_operand:SI 1 "register_operand" "0,r,a,r")
+ (match_operand:SI 2 "csky_arith_K_operand" "b,r,K,K")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "@
+ lsl %0, %1, %2
+ lsl %0, %1, %2
+ lsli %0, %1, %2
+ lsli %0, %1, %2"
+ [(set_attr "length" "2,4,2,4")]
+)
+
+(define_insn "ck801_ashlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=a,r")
+ (ashift:SI (match_operand:SI 1 "register_operand" "a,0")
+ (match_operand:SI 2 "csky_arith_K_operand" "K,r")))]
+ "CSKY_ISA_FEATURE (E1)"
+ "@
+ lsli %0, %1, %2
+ lsl %0, %1, %2"
+)
+
+
+(define_expand "ashrsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "csky_arith_K_operand" "")))]
+ ""
+ ""
+)
+
+(define_insn "*cskyv2_ashrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=b,r,a,r")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,r,a,r")
+ (match_operand:SI 2 "csky_arith_K_operand" "b,r,K,K")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "@
+ asr %0, %1, %2
+ asr %0, %1, %2
+ asri %0, %1, %2
+ asri %0, %1, %2"
+ [(set_attr "length" "2,4,2,4")]
+)
+
+(define_insn "*ck801_ashrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=a,r")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "a,0")
+ (match_operand:SI 2 "csky_arith_K_operand" "K,r")))]
+ "CSKY_ISA_FEATURE (E1)"
+ "@
+ asri %0, %1, %2
+ asr %0, %1, %2"
+)
+
+
+(define_expand "lshrsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "csky_arith_K_operand" "")))]
+ ""
+ ""
+)
+
+(define_insn "*cskyv2_lshrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=b,r,a,r")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,r,a,r")
+ (match_operand:SI 2 "csky_arith_K_operand" "b,r,K,K")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "@
+ lsr %0, %1, %2
+ lsr %0, %1, %2
+ lsri %0, %1, %2
+ lsri %0, %1, %2"
+ [(set_attr "length" "2,4,2,4")]
+)
+
+(define_insn "ck801_lshrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=a,r")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "a,0")
+ (match_operand:SI 2 "csky_arith_K_operand" "K,r")))]
+ "CSKY_ISA_FEATURE (E1)"
+ "@
+ lsri %0, %1, %2
+ lsr %0, %1, %2"
+)
+
+
+(define_expand "rotlsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (rotate:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "csky_arith_K_operand" "")))]
+ ""
+ ""
+)
+
+(define_insn "*cskyv2_rotlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=b,r,r")
+ (rotate:SI (match_operand:SI 1 "register_operand" "0,r,r")
+ (match_operand:SI 2 "csky_arith_K_operand" "b,r,K")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "@
+ rotl %0, %1, %2
+ rotl %0, %1, %2
+ rotli %0, %1, %2"
+ [(set_attr "length" "2,4,4")]
+)
+
+(define_insn "*ck801_rotlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (rotate:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "csky_arith_K_operand" "r")))]
+ "CSKY_ISA_FEATURE (E1)"
+ "rotl %0, %1, %2"
+)
+
+
+;; Add instructions.
+;; C-SKY addi and subi machine instructions only accept positive immediate
+;; values, so we have to special case immediates <= 0 in these patterns.
+
+(define_expand "addsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (plus:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))]
+ ""
+ ""
+)
+
+(define_insn "smart_addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=a,r,a,a,a,a, r,r")
+ (plus:SI (match_operand:SI 1 "register_operand" "%a,0,0,a,0,a, r,r")
+ (match_operand:SI 2 "nonmemory_operand" "a, r,N,L,T,Us,M,Um")))]
+ "TARGET_MINI_REGISTERS && CSKY_ISA_FEATURE (E2)
+ && operands[0] != stack_pointer_rtx
+ && operands[1] != stack_pointer_rtx"
+ "@
+ addu\t%0, %1, %2
+ addu\t%0, %1, %2
+ addi\t%0, %1, %2
+ addi\t%0, %1, %2
+ subi\t%0, %1, %M2
+ subi\t%0, %1, %M2
+ addi\t%0, %1, %2
+ subi\t%0, %1, %M2"
+ [(set_attr "length" "2,2,2,2,2,2,4,4")
+ (set_attr "type" "addsub")]
+)
+
+(define_insn_and_split "*smart_addsi3_sp"
+ [(set (match_operand:SI 0 "register_operand" "=z,z, z,a,&a,z,a,r")
+ (plus:SI (match_operand:SI 1 "register_operand" "0, 0, 0,z, z,a,z,r")
+ (match_operand:SI 2 "nonmemory_operand" "P, Ug,r,Uq,i,a,a,M")))]
+ "TARGET_MINI_REGISTERS && CSKY_ISA_FEATURE (E2)
+ && (operands[0] == stack_pointer_rtx || operands[1] == stack_pointer_rtx)"
+ "@
+ addi\t%0, %1, %2
+ subi\t%0, %1, %M2
+ addu\t%0, %1, %2
+ addi\t%0, %1, %2
+ #
+ addu\t%0, %1, %2
+ addu\t%0, %1, %2
+ addi\t%0, %1, %2"
+ "(operands[0] != stack_pointer_rtx
+ && operands[1] == stack_pointer_rtx
+ && !satisfies_constraint_Uq (operands[2]))"
+ [(set (match_dup 0)
+ (plus:SI (match_dup 1) (match_dup 0)))]
+ "emit_move_insn (operands[0], operands[2]);"
+ [(set_attr "type" "addsub")]
+)
+
+(define_insn "*ck801_addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,a,a,a,a,a, !z,!z,!z,a")
+ (plus:SI (match_operand:SI 1 "register_operand" "%0,a,0,a,0,a, 0, 0, 0, !z")
+ (match_operand:SI 2 "nonmemory_operand" "r, a,N,L,T,Us,P, Ug,r, Uq")))]
+ "CSKY_ISA_FEATURE (E1)"
+ "@
+ addu\t%0, %1, %2
+ addu\t%0, %1, %2
+ addi\t%0, %1, %2
+ addi\t%0, %1, %2
+ subi\t%0, %1, %M2
+ subi\t%0, %1, %M2
+ addi\t%0, %1, %2
+ subi\t%0, %1, %M2
+ addu\t%0, %1, %2
+ addi\t%0, %1, %2"
+ [(set_attr "type" "addsub")]
+)
+
+(define_insn "fast_addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r, r")
+ (plus:SI (match_operand:SI 1 "register_operand" "%r,r, r")
+ (match_operand:SI 2 "nonmemory_operand" "M, Um,r")))]
+ "!TARGET_MINI_REGISTERS && CSKY_ISA_FEATURE (E2)"
+ "@
+ addi\t%0, %1, %2
+ subi\t%0, %1, %M2
+ addu\t%0, %1, %2"
+ [(set_attr "type" "addsub")]
+)
+
+(define_expand "adddi3"
+ [(parallel [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "csky_arith_int1_operand" "")))
+ (clobber (reg:CC CSKY_CC_REGNUM))])]
+ ""
+ "
+ if (CSKY_ISA_FEATURE (E1) && (GET_CODE (operands[2]) != REG))
+ operands[2] = force_reg (DImode, operands[2]);
+ "
+)
+
+/* Note that the csky addc instruction both reads and writes the carry bit.
+ The purpose of the initial cmplt instruction in the expansion is to
+ clear the carry bit before adding the lo words. */
+
+(define_insn_and_split "*cskyv2_adddi3"
+ [(set (match_operand:DI 0 "register_operand" "=&b,&r")
+ (plus:DI (match_operand:DI 1 "register_operand" "%0,r")
+ (match_operand:DI 2 "register_operand" "b, r")))
+ (clobber (reg:CC CSKY_CC_REGNUM))]
+ "CSKY_ISA_FEATURE (E2)"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ {
+ int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD;
+ int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0;
+ rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo);
+ rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi);
+ rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo);
+ rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi);
+ rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo);
+ rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi);
+
+ emit_insn (gen_cmpltsi_r (copy_rtx (l1), copy_rtx (l1)));
+ emit_insn (gen_cskyv2_addc (l0, l1, l2));
+ emit_insn (gen_cskyv2_addc (h0, h1, h2));
+ DONE;
+ }
+ [(set_attr "length" "6,12")]
+)
+
+(define_insn_and_split "*ck801_adddi3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "%0")
+ (match_operand:DI 2 "register_operand" "r")))
+ (clobber (reg:CC CSKY_CC_REGNUM))]
+ "CSKY_ISA_FEATURE (E1)"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ {
+ int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD;
+ int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0;
+ rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo);
+ rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi);
+ rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo);
+ rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi);
+ rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo);
+ rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi);
+
+ emit_insn (gen_cmpltsi_r (copy_rtx (l1), copy_rtx (l1)));
+ emit_insn (gen_ck801_addc (l0, l1, l2));
+ emit_insn (gen_ck801_addc (h0, h1, h2));
+ DONE;
+ }
+ [(set_attr "length" "6")]
+)
+
+;; Special case for "longlong += 1".
+
+(define_insn_and_split "*cskyv2_adddi1_1"
+ [(set (match_operand:DI 0 "register_operand" "=&r")
+ (plus:DI (match_operand:DI 1 "register_operand" "0")
+ (const_int 1)))
+ (clobber (reg:CC CSKY_CC_REGNUM))]
+ "CSKY_ISA_FEATURE (E2)"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ {
+ int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD;
+ int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0;
+ rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo);
+ rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi);
+
+ if (TARGET_MINI_REGISTERS)
+ {
+ emit_insn (gen_smart_addsi3 (l0, copy_rtx (l0),
+ gen_int_mode (1, SImode)));
+ emit_insn (gen_smart_cmpnesi_i (copy_rtx (l0),
+ gen_int_mode (0, SImode)));
+ emit_insn (gen_cskyv2_addcc_invert (h0, copy_rtx (h0),
+ gen_int_mode (1, SImode)));
+ }
+ else
+ {
+ emit_insn (gen_fast_addsi3 (l0, copy_rtx (l0),
+ gen_int_mode (1, SImode)));
+ emit_insn (gen_fast_cmpnesi_i (copy_rtx (l0),
+ gen_int_mode (0, SImode)));
+ emit_insn (gen_cskyv2_addcc_invert (h0, copy_rtx (h0),
+ gen_int_mode (1, SImode)));
+ }
+ DONE;
+ }
+ [(set (attr "length")
+ (if_then_else (match_test "TARGET_MINI_REGISTERS")
+ (const_int 8)
+ (const_int 12)))]
+)
+
+;; sub instructions.
+
+(define_expand "subsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (minus:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))]
+ ""
+ ""
+)
+
+(define_insn "smart_subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=a,a,a,a,a,a")
+ (minus:SI (match_operand:SI 1 "register_operand" "a, 0,0,a,0,a")
+ (match_operand:SI 2 "nonmemory_operand" "a, a,N,L,T,Us")))]
+ "TARGET_MINI_REGISTERS && CSKY_ISA_FEATURE (E2)
+ && operands[0] != stack_pointer_rtx
+ && operands[1] != stack_pointer_rtx"
+ "@
+ subu\t%0, %1, %2
+ subu\t%0, %1, %2
+ subi\t%0, %1, %2
+ subi\t%0, %1, %2
+ addi\t%0, %1, %M2
+ addi\t%0, %1, %M2"
+ [(set_attr "length" "2,2,2,2,2,2")
+ (set_attr "type" "addsub")]
+)
+
+(define_insn "*smart_subsi3_sp"
+ [(set (match_operand:SI 0 "register_operand" "=z,z, z,a, a,r")
+ (minus:SI (match_operand:SI 1 "register_operand" "0, 0, 0,z, a,r")
+ (match_operand:SI 2 "nonmemory_operand" "P, Ug,a,Ur,a,M")))]
+ "TARGET_MINI_REGISTERS && CSKY_ISA_FEATURE (E2)
+ && (operands[0] == stack_pointer_rtx || operands[1] == stack_pointer_rtx)"
+ "@
+ subi\t%0, %1, %2
+ addi\t%0, %1, %M2
+ subu\t%0, %1, %2
+ addi\t%0, %1, %M2
+ subu\t%0, %1, %2
+ subi\t%0, %1, %2"
+ [(set_attr "length" "2,2,2,2,2,4")
+ (set_attr "type" "addsub")]
+)
+
+(define_insn "*ck801_subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=a,a,a,a,a,a")
+ (minus:SI (match_operand:SI 1 "register_operand" "0, a,0,a,0,a")
+ (match_operand:SI 2 "nonmemory_operand" "a, a,N,L,T,Us")))]
+ "CSKY_ISA_FEATURE (E1)
+ && operands[0] != stack_pointer_rtx
+ && operands[1] != stack_pointer_rtx"
+ "@
+ subu\t%0, %1, %2
+ subu\t%0, %1, %2
+ subi\t%0, %1, %2
+ subi\t%0, %1, %2
+ addi\t%0, %1, %M2
+ addi\t%0, %1, %M2"
+ [(set_attr "type" "addsub")]
+)
+
+(define_insn "*ck801_subsi3_sp"
+ [(set (match_operand:SI 0 "register_operand" "=a,z,z, z")
+ (minus:SI (match_operand:SI 1 "register_operand" "z, 0,0, 0")
+ (match_operand:SI 2 "nonmemory_operand" "Ur,P,Ug,r")))]
+ "CSKY_ISA_FEATURE (E1)
+ && (operands[0] == stack_pointer_rtx || operands[1] == stack_pointer_rtx)"
+ "@
+ addi\t%0, %1, %M2
+ subi\t%0, %1, %2
+ addi\t%0, %1, %M2
+ subu\t%0, %1, %2"
+ [(set_attr "type" "addsub")]
+)
+
+(define_insn "fast_subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+ (minus:SI (match_operand:SI 1 "register_operand" "r, r,r")
+ (match_operand:SI 2 "nonmemory_operand" "r, M,Um")))]
+ "!TARGET_MINI_REGISTERS && CSKY_ISA_FEATURE (E2)"
+ "@
+ subu\t%0, %1, %2
+ subi\t%0, %1, %2
+ addi\t%0, %1, %M2"
+ [(set_attr "type" "addsub")]
+)
+
+(define_expand "subdi3"
+ [(parallel [(set (match_operand:DI 0 "register_operand" "")
+ (minus:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "register_operand" "")))
+ (clobber (reg:CC CSKY_CC_REGNUM))])]
+ ""
+ ""
+)
+
+/* Note that the csky subc instruction both reads and writes the C bit.
+ The purpose of the initial cmphs instruction in the expansion is to
+ set the C bit before subtracting the lo words. */
+
+(define_insn_and_split "*cskyv2_subdi3"
+ [(set (match_operand:DI 0 "register_operand" "=&b,&r")
+ (minus:DI (match_operand:DI 1 "register_operand" "0, r")
+ (match_operand:DI 2 "register_operand" "b, r")))
+ (clobber (reg:CC CSKY_CC_REGNUM))]
+ "CSKY_ISA_FEATURE (E2)"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ {
+ int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD;
+ int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0;
+ rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo);
+ rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi);
+ rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo);
+ rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi);
+ rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo);
+ rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi);
+
+ emit_insn (gen_cmpgeusi_r (copy_rtx (l1), copy_rtx (l1)));
+ emit_insn (gen_cskyv2_subc (l0, l1, l2));
+ emit_insn (gen_cskyv2_subc (h0, h1, h2));
+ DONE;
+ }
+ [(set_attr "length" "6,12")]
+)
+
+(define_insn_and_split "*ck801_subdi3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (minus:DI (match_operand:DI 1 "register_operand" "0")
+ (match_operand:DI 2 "register_operand" "r")))
+ (clobber (reg:CC CSKY_CC_REGNUM))]
+ "CSKY_ISA_FEATURE (E1)"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ {
+ int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD;
+ int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0;
+ rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo);
+ rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi);
+ rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo);
+ rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi);
+ rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo);
+ rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi);
+
+ emit_insn (gen_cmpgeusi_r (copy_rtx (l1), copy_rtx (l1)));
+ emit_insn (gen_ck801_subc (l0, l1, l2));
+ emit_insn (gen_ck801_subc (h0, h1, h2));
+ DONE;
+ }
+ [(set_attr "length" "6")]
+)
+
+;; Special case for "longlong -= 1".
+
+(define_insn_and_split "*cskyv2_subdi1_1"
+ [(set (match_operand:DI 0 "register_operand" "=&r")
+ (plus:DI (match_operand:DI 1 "register_operand" "0")
+ (const_int -1)))
+ (clobber (reg:CC CSKY_CC_REGNUM))]
+ "CSKY_ISA_FEATURE (E2)"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ {
+ int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD;
+ int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0;
+ rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo);
+ rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi);
+
+ if (TARGET_MINI_REGISTERS)
+ {
+ emit_insn (gen_smart_cmpnesi_i (copy_rtx (l0),
+ gen_int_mode (0, SImode)));
+ emit_insn (gen_cskyv2_addcc_invert (h0, copy_rtx (h0),
+ gen_int_mode (-1, SImode)));
+ emit_insn (gen_smart_subsi3 (l0, copy_rtx (l0),
+ gen_int_mode (1, SImode)));
+ }
+ else
+ {
+ emit_insn (gen_fast_cmpnesi_i (copy_rtx (l0),
+ gen_int_mode (0, SImode)));
+ emit_insn (gen_cskyv2_addcc_invert (h0, copy_rtx (h0),
+ gen_int_mode (-1, SImode)));
+ emit_insn (gen_fast_subsi3 (l0, copy_rtx (l0),
+ gen_int_mode (1, SImode)));
+ }
+ DONE;
+ }
+ [(set (attr "length")
+ (if_then_else (match_test "TARGET_MINI_REGISTERS")
+ (const_int 8)
+ (const_int 12)))]
+)
+
+;; Add with carry.
+
+(define_insn "cskyv2_addc"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (plus:SI (ne:SI (reg:CC CSKY_CC_REGNUM) (const_int 0))
+ (plus:SI (match_operand:SI 1 "register_operand" "%0,r")
+ (match_operand:SI 2 "register_operand" "r,r"))))
+ (set (reg:CC CSKY_CC_REGNUM)
+ (compare:CC
+ (plus:SI (match_dup 1) (match_dup 2))
+ (match_dup 1)))]
+ "CSKY_ISA_FEATURE (E2)"
+ "addc\t%0, %1, %2"
+ [(set_attr "length" "2,4")
+ (set_attr "type" "addsub")]
+)
+
+(define_insn "ck801_addc"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (ne:SI (reg:CC CSKY_CC_REGNUM) (const_int 0))
+ (plus:SI (match_operand:SI 1 "register_operand" "%0")
+ (match_operand:SI 2 "register_operand" "r"))))
+ (set (reg:CC CSKY_CC_REGNUM)
+ (compare:CC
+ (plus:SI (match_dup 1) (match_dup 2))
+ (match_dup 1)))]
+ "CSKY_ISA_FEATURE (E1)"
+ "addc\t%0, %1, %2"
+ [(set_attr "length" "2")
+ (set_attr "type" "addsub")]
+)
+
+;; Subtract with borrow.
+;; Note that in these insns, the sense of C bit is reversed; they subtract 1
+;; if the C bit is not set, and on output the bit is set to 0 for borrow
+;; and 1 for no borrow.
+
+(define_insn "cskyv2_subc"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (minus:SI (match_operand:SI 1 "register_operand" "0, r")
+ (plus:SI (match_operand:SI 2 "register_operand" "r, r")
+ (eq:SI (reg:CC CSKY_CC_REGNUM) (const_int 0)))))
+ (set (reg:CC CSKY_CC_REGNUM)
+ (not (compare:CC (match_dup 1) (match_dup 2))))]
+ "CSKY_ISA_FEATURE (E2)"
+ "subc\t%0, %1, %2"
+ [(set_attr "length" "2,4")
+ (set_attr "type" "addsub")]
+)
+
+(define_insn "ck801_subc"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (match_operand:SI 1 "register_operand" "0")
+ (plus:SI (match_operand:SI 2 "register_operand" "r")
+ (eq:SI (reg:CC CSKY_CC_REGNUM) (const_int 0)))))
+ (set (reg:CC CSKY_CC_REGNUM)
+ (not (compare:CC (match_dup 1) (match_dup 2))))]
+ "CSKY_ISA_FEATURE (E1)"
+ "subc\t%0, %1, %2"
+ [(set_attr "length" "2")
+ (set_attr "type" "addsub")]
+)
+
+;; ------------------------------------------------------------------------
+;; Multiplication insns
+;; ------------------------------------------------------------------------
+
+(define_expand "mulsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (mult:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "register_operand" "")))]
+ ""
+ ""
+)
+
+(define_insn "*cskyv2_mulsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mult:SI (match_operand:SI 1 "register_operand" "%r")
+ (match_operand:SI 2 "register_operand" "r")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "mult\t%0, %1, %2"
+)
+
+(define_insn "*ck801_mulsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mult:SI (match_operand:SI 1 "register_operand" "%0")
+ (match_operand:SI 2 "register_operand" "r")))]
+ "CSKY_ISA_FEATURE (E1)"
+ "mult\t%0, %1, %2"
+)
+
+(define_insn "mulhisi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%r"))
+ (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
+ "CSKY_ISA_FEATURE (2E3)"
+ "mulsh\t%0, %1, %2"
+)
+
+
+;; ------------------------------------------------------------------------
+;; Conditional add insns
+;; ------------------------------------------------------------------------
+
+(define_expand "addsicc"
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand 1 "ordered_comparison_operator" "")
+ (match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "csky_literal_K_Uh_operand" "")]
+ "CSKY_ISA_FEATURE (E2)"
+ "
+ {
+ bool invert = csky_emit_compare (GET_CODE (operands[1]),
+ XEXP (operands[1], 0),
+ XEXP (operands[1], 1));
+ if (invert)
+ emit_insn (gen_cskyv2_addcc_invert (operands[0], operands[2],
+ operands[3]));
+ else
+ emit_insn (gen_cskyv2_addcc (operands[0], operands[2], operands[3]));
+
+ DONE;
+ }"
+)
+
+(define_insn_and_split "cskyv2_addcc"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,&r,&r")
+ (if_then_else:SI
+ (ne (reg:CC CSKY_CC_REGNUM) (const_int 0))
+ (plus:SI (match_operand:SI 1 "register_operand" "0,0,r,r")
+ (match_operand:SI 2 "csky_literal_K_Uh_operand" "K,Uh,K,Uh"))
+ (match_dup 1)))]
+ "CSKY_ISA_FEATURE (E2)"
+ "@
+ inct\t%0, %1, %2
+ dect\t%0, %1, %M2
+ #
+ #"
+ "reload_completed && !rtx_equal_p (operands[0], operands[1])"
+ [(set (match_dup 0)
+ (if_then_else:SI (ne (reg:CC CSKY_CC_REGNUM) (const_int 0))
+ (plus:SI (match_dup 0) (match_dup 2))))]
+ {
+ emit_insn (gen_movf (copy_rtx (operands[0]),
+ copy_rtx (operands[1]),
+ copy_rtx (operands[0])));
+ }
+ [(set_attr "length" "4,4,8,8")
+ (set_attr "type" "addsub")]
+)
+
+(define_insn_and_split "cskyv2_addcc_invert"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+ (if_then_else:SI
+ (eq (reg:CC CSKY_CC_REGNUM) (const_int 0))
+ (plus:SI (match_operand:SI 1 "register_operand" "0,0,r,r")
+ (match_operand:SI 2 "csky_literal_K_Uh_operand" "K,Uh,K,Uh"))
+ (match_dup 1)))]
+ "CSKY_ISA_FEATURE (E2)"
+ "@
+ incf\t%0, %1, %2
+ decf\t%0, %1, %M2
+ #
+ #"
+ "reload_completed && !rtx_equal_p (operands[0], operands[1])"
+ [(set (match_dup 0)
+ (if_then_else:SI (eq (reg:CC CSKY_CC_REGNUM) (const_int 0))
+ (plus:SI (match_dup 0) (match_dup 2))))]
+ {
+ emit_insn (gen_movt (copy_rtx (operands[0]),
+ copy_rtx (operands[1]),
+ copy_rtx (operands[0])));
+ }
+ [(set_attr "length" "4,4,8,8")
+ (set_attr "type" "addsub")]
+)
+
+
+;; ------------------------------------------------------------------------
+;; Extzv insns
+;; ------------------------------------------------------------------------
+
+(define_expand "extzvsi"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")
+ (match_operand:SI 3 "const_int_operand" "")))]
+ ""
+ "{
+ /* ck802 has xtrb but not zext, so we'll use xtrb if we can. */
+ if (CSKY_ISA_FEATURE (E2) && !CSKY_ISA_FEATURE (2E3)
+ && (INTVAL (operands[2]) == 8)
+ && (INTVAL (operands[3]) % 8 == 0))
+ {
+ rtx xtrb = gen_rtx_SET (operands[0],
+ gen_rtx_ZERO_EXTRACT (SImode,
+ operands[1],
+ operands[2],
+ operands[3]));
+ emit (gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (2, xtrb,
+ gen_hard_reg_clobber (CCmode, 33))));
+ DONE;
+ }
+ else if (!CSKY_ISA_FEATURE (2E3))
+ {
+ /* Use lsri and lsli to do extzv on targets without zext. */
+ rtx lshft = GEN_INT (32 - (INTVAL (operands[2])
+ + INTVAL (operands[3])));
+ rtx rshft = GEN_INT (32 - INTVAL (operands[2]));
+ rtx tmp1 = gen_reg_rtx (SImode);
+ rtx tmp2 = gen_reg_rtx (SImode);
+
+ emit_insn (gen_rtx_SET (tmp1, operands[1]));
+ emit_insn (gen_rtx_SET (tmp2, gen_rtx_ASHIFT (SImode, tmp1, lshft)));
+ emit_insn (gen_rtx_SET (operands[0],
+ gen_rtx_LSHIFTRT (SImode, tmp2, rshft)));
+ DONE;
+ }
+ else
+ {
+ emit_insn (gen_cskyv2_extzv (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+ }
+}")
+
+(define_insn "cskyv2_extzv"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "csky_literal_K_operand" "K")
+ (match_operand:SI 3 "csky_literal_K_operand" "K")))]
+ "CSKY_ISA_FEATURE (2E3)"
+ {
+ operands[2] = GEN_INT (INTVAL (operands[3]) + INTVAL (operands[2]) - 1);
+ return \"zext\t%0, %1, %2, %3\";
+ }
+)
+
+(define_insn "*cskyv2_xtrb0"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "0,r")
+ (const_int 8)
+ (const_int 24)))
+ (clobber (reg:CC CSKY_CC_REGNUM))]
+ "CSKY_ISA_FEATURE (E2)"
+ "@
+ lsri\t%0, %0, 24
+ xtrb0\t%0, %1"
+)
+
+(define_insn "*cskyv2_xtrb1"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 8)
+ (const_int 16)))
+ (clobber (reg:CC CSKY_CC_REGNUM))]
+ "CSKY_ISA_FEATURE (E2)"
+ "xtrb1\t%0, %1"
+)
+
+(define_insn "*cskyv2_xtrb2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 8)
+ (const_int 8)))
+ (clobber (reg:CC CSKY_CC_REGNUM))]
+ "CSKY_ISA_FEATURE (E2)"
+ "xtrb2\t%0, %1"
+)
+
+
+;; -------------------------------------------------------------------------
+;; Zero extension instructions
+;; -------------------------------------------------------------------------
+
+(define_insn "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (match_operand:HI 1 "register_operand" "r")))]
+ ""
+ "zexth\t%0, %1"
+)
+
+(define_insn "*cskyv2_zextend_ldh"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (match_operand:HI 1 "csky_simple_mem_operand" "m")))]
+ ""
+ "ld.h\t%0, %1"
+ [(set_attr "length" "4")
+ (set_attr "type" "load")]
+)
+
+(define_insn "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (match_operand:QI 1 "register_operand" "r")))]
+ ""
+ "zextb\t%0, %1"
+)
+
+(define_insn "*cskyv2_zextend_ldb"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (match_operand:QI 1 "csky_simple_mem_operand" "m")))]
+ ""
+ "ld.b\t%0, %1"
+ [(set_attr "length" "4")
+ (set_attr "type" "load")]
+)
+
+(define_insn "zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (zero_extend:HI (match_operand:QI 1 "register_operand" "r")))]
+ ""
+ "zextb\t%0, %1"
+)
+
+(define_insn "*cskyv2_zextend_ldbhi"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (zero_extend:HI (match_operand:QI 1 "csky_simple_mem_operand" "m")))]
+ ""
+ "ld.b\t%0, %1"
+ [(set_attr "length" "4")
+ (set_attr "type" "load")]
+)
+
+;; -------------------------------------------------------------------------
+;; clzm2 instructions
+;; -------------------------------------------------------------------------
+
+(define_insn "clzsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (clz:SI (match_operand:SI 1 "register_operand" "r")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "ff1 %0,%1"
+)
+
+;; -------------------------------------------------------------------------
+;; one_cmplm2 instructions
+;; -------------------------------------------------------------------------
+
+(define_expand "one_cmplsi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (not:SI (match_operand:SI 1 "register_operand" "")))]
+ ""
+ ""
+)
+
+(define_insn "cskyv2_one_cmplsi2"
+ [(set (match_operand:SI 0 "register_operand" "=b,r")
+ (not:SI (match_operand:SI 1 "register_operand" "0,r")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "not %0, %1"
+ [(set_attr "length" "2,4")
+ (set_attr "type" "alu,alu")]
+)
+
+(define_insn "ck801_one_cmplsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (not:SI (match_operand:SI 1 "register_operand" "0")))]
+ "CSKY_ISA_FEATURE (E1)"
+ "not %0, %1"
+ [(set_attr "length" "2")
+ (set_attr "type" "alu")]
+)
+
+;; -------------------------------------------------------------------------
+;; Sign extension instructions
+;; -------------------------------------------------------------------------
+
+;; One test shows that the following code helps to
+;; reduce one 'load' and two 'mov'.
+(define_expand "extendsidi2"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (match_operand:SI 1 "register_operand" "r"))]
+ ""
+ "{
+ int low, high;
+
+ if (TARGET_BIG_ENDIAN)
+ low = 4, high = 0;
+ else
+ low = 0, high = 4;
+
+ emit_insn (gen_rtx_SET (gen_rtx_SUBREG (SImode, operands[0], low),
+ operands[1]));
+
+ emit_insn (gen_rtx_SET (gen_rtx_SUBREG (SImode, operands[0], high),
+ gen_rtx_ASHIFTRT (SImode,
+ gen_rtx_SUBREG (SImode,
+ operands[0],
+ low),
+ GEN_INT (31))));
+ DONE;
+ }"
+)
+
+(define_insn "extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))]
+ ""
+ "sexth %0, %1"
+)
+
+(define_insn "*cskyv2_sextend_ldhs"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (match_operand:HI 1 "csky_simple_mem_operand" "m")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "ld.hs\t%0, %1"
+ [(set_attr "length" "4")
+ (set_attr "type" "load")]
+)
+
+;; qi -> si
+(define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))]
+ ""
+ "sextb %0, %1"
+)
+
+;; qi -> hi
+(define_insn "extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (sign_extend:HI (match_operand:QI 1 "register_operand" "r")))]
+ ""
+ "sextb %0, %1"
+)
+
+;; -------------------------------------------------------------------------
+;; And instructions
+;; -------------------------------------------------------------------------
+
+(define_expand "andsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (and:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "csky_arith_any_imm_operand" "")))]
+ ""
+ "")
+
+(define_insn_and_split "cskyv2_andsi3"
+ [(set (match_operand:SI 0 "register_operand" "=b,r,r,&r")
+ (and:SI (match_operand:SI 1 "register_operand" "%0,r,r,r")
+ (match_operand:SI 2 "csky_arith_any_imm_operand" "b,r,O,i")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "@
+ and\t%0, %1, %2
+ and\t%0, %1, %2
+ andi\t%0, %1, %2
+ #"
+ "(CONST_INT_P (operands[2])
+ && (operands[2] == const0_rtx
+ || !csky_arith_O_operand (operands[2], SImode)))"
+ [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))]
+ {
+ if (csky_split_and (operands))
+ DONE;
+ }
+ [(set_attr "length" "2,4,4,8")
+ (set_attr "type" "alu,alu,alu,alu")]
+)
+
+(define_insn_and_split "ck801_andsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,&r")
+ (and:SI (match_operand:SI 1 "register_operand" "%0,r")
+ (match_operand:SI 2 "csky_arith_any_imm_operand" "r,i")))]
+ "CSKY_ISA_FEATURE (E1)"
+ "@
+ and\t%0, %1, %2
+ #"
+ "CONST_INT_P (operands[2])"
+ [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))]
+ {
+ if (csky_split_and (operands))
+ DONE;
+ }
+ [(set_attr "length" "2,4")
+ (set_attr "type" "alu,alu")]
+)
+
+;; Note that the operands for the andnsi3 patterns are reversed compared
+;; to the actual machine insn: operand 1 is the inverted operand.
+
+(define_insn "cskyv2_andnsi3"
+ [(use (and:SI (not:SI (match_operand:SI 1 "csky_arith_O_operand" "b,r,O"))
+ (match_operand:SI 2 "register_operand" "0,r,r")))
+ (set (match_operand:SI 0 "register_operand" "=b,r,r")
+ (and:SI (not:SI (match_dup 1))
+ (match_dup 2)))]
+ "CSKY_ISA_FEATURE (E2)"
+ "@
+ andn\t%0, %2, %1
+ andn\t%0, %2, %1
+ andni\t%0, %2, %1"
+ [(set_attr "length" "2,4,4")
+ (set_attr "type" "alu,alu,alu")]
+)
+
+(define_insn "ck801_andnsi3"
+ [(use (and:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" "0")))
+ (set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (not:SI (match_dup 1))
+ (match_dup 2)))]
+ "CSKY_ISA_FEATURE (E1)"
+ "andn\t%0, %2, %1"
+)
+
+(define_expand "anddi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (and:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "csky_arith_any_imm_operand" "")))]
+ ""
+ "
+ {
+ if (CONST_INT_P (operands[2]))
+ {
+ HOST_WIDE_INT ival = INTVAL (operands[2]);
+ if (ival == (HOST_WIDE_INT) 0xffffffff)
+ {
+ emit_move_insn (gen_lowpart (SImode, operands[0]),
+ gen_lowpart (SImode, operands[1]));
+ emit_move_insn (gen_highpart (SImode, operands[0]), const0_rtx);
+ DONE;
+ }
+ else if (ival == (HOST_WIDE_INT) ((unsigned HOST_WIDE_INT) -1 << 32))
+ {
+ emit_move_insn (gen_lowpart (SImode, operands[0]), const0_rtx);
+ emit_move_insn (gen_highpart (SImode, operands[0]),
+ gen_highpart (SImode, operands[1]));
+ DONE;
+ }
+ else
+ FAIL;
+ }
+ }")
+
+
+
+(define_insn_and_split "*cskyv2_anddi3"
+ [(set (match_operand:DI 0 "register_operand" "=&b,&r")
+ (and:DI (match_operand:DI 1 "register_operand" "%0,r")
+ (match_operand:DI 2 "register_operand" "b,r")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ {
+ int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD;
+ int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0;
+ rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo);
+ rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi);
+ rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo);
+ rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi);
+ rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo);
+ rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi);
+
+ emit_insn (gen_cskyv2_andsi3 (l0, l1, l2));
+ emit_insn (gen_cskyv2_andsi3 (h0, h1, h2));
+ DONE;
+ }
+ [(set_attr "length" "4,8")]
+)
+
+(define_insn_and_split "*ck801_anddi3"
+ [(set (match_operand:DI 0 "register_operand" "=&r")
+ (and:DI (match_operand:DI 1 "register_operand" "%0")
+ (match_operand:DI 2 "register_operand" "r")))]
+ "CSKY_ISA_FEATURE (E1)"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ {
+ int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD;
+ int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0;
+ rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo);
+ rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi);
+ rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo);
+ rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi);
+ rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo);
+ rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi);
+
+ emit_insn (gen_ck801_andsi3 (l0, l1, l2));
+ emit_insn (gen_ck801_andsi3 (h0, h1, h2));
+ DONE;
+ }
+ [(set_attr "length" "4")]
+)
+
+
+;; -------------------------------------------------------------------------
+;; Ior instructions
+;; -------------------------------------------------------------------------
+
+(define_expand "iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (ior:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "csky_arith_any_imm_operand" "")))]
+ ""
+ "")
+
+(define_insn_and_split "cskyv2_iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=b,r,r,&r")
+ (ior:SI (match_operand:SI 1 "register_operand" "%0,r,r,r")
+ (match_operand:SI 2 "csky_arith_any_imm_operand" "b, r,I,i")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "@
+ or\t%0, %1, %2
+ or\t%0, %1, %2
+ ori\t%0, %1, %2
+ #"
+ "(CONST_INT_P (operands[2])
+ && (operands[2] == const0_rtx
+ || !csky_literal_I_operand (operands[2], SImode)))"
+ [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))]
+ {
+ if (csky_split_ior (operands))
+ DONE;
+ }
+ [(set_attr "length" "2,4,4,8")
+ (set_attr "type" "alu,alu,alu,alu")]
+)
+
+(define_insn_and_split "ck801_iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,&r")
+ (ior:SI (match_operand:SI 1 "register_operand" "%0,r")
+ (match_operand:SI 2 "csky_arith_any_imm_operand" "r,i")))]
+ "CSKY_ISA_FEATURE (E1)"
+ "@
+ or\t%0, %1, %2
+ #"
+ "CONST_INT_P (operands[2])"
+ [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))]
+ {
+ if (csky_split_ior (operands))
+ DONE;
+ }
+ [(set_attr "length" "2,4")
+ (set_attr "type" "alu,alu")]
+)
+
+(define_expand "iordi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (ior:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "register_operand" "")))]
+ ""
+ ""
+)
+
+(define_insn_and_split "*cskyv2_iordi3"
+ [(set (match_operand:DI 0 "register_operand" "=&b,&r")
+ (ior:DI (match_operand:DI 1 "register_operand" "%0, r")
+ (match_operand:DI 2 "register_operand" "b, r")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ {
+ int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD;
+ int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0;
+ rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo);
+ rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi);
+ rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo);
+ rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi);
+ rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo);
+ rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi);
+
+ emit_insn (gen_cskyv2_iorsi3 (l0, l1, l2));
+ emit_insn (gen_cskyv2_iorsi3 (h0, h1, h2));
+ DONE;
+ }
+ [(set_attr "length" "4,8")]
+)
+
+(define_insn_and_split "*ck801_iordi3"
+ [(set (match_operand:DI 0 "register_operand" "=&r")
+ (ior:DI (match_operand:DI 1 "register_operand" "%0")
+ (match_operand:DI 2 "register_operand" "r")))]
+ "CSKY_ISA_FEATURE (E1)"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ {
+ int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD;
+ int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0;
+ rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo);
+ rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi);
+ rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo);
+ rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi);
+ rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo);
+ rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi);
+
+ emit_insn (gen_ck801_iorsi3 (l0, l1, l2));
+ emit_insn (gen_ck801_iorsi3 (h0, h1, h2));
+ DONE;
+ }
+ [(set_attr "length" "4")]
+)
+
+
+;; -------------------------------------------------------------------------
+;; Xor instructions
+;; -------------------------------------------------------------------------
+
+(define_expand "xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (xor:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "csky_arith_any_imm_operand" "")))]
+ ""
+ "")
+
+(define_insn_and_split "cskyv2_xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=b,r,r,&r")
+ (xor:SI (match_operand:SI 1 "register_operand" "%0,r,r,r")
+ (match_operand:SI 2 "csky_arith_any_imm_operand" "b, r,O,i")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "@
+ xor\t%0, %1, %2
+ xor\t%0, %1, %2
+ xori\t%0, %1, %2
+ #"
+ "(CONST_INT_P (operands[2])
+ && (operands[2] == const0_rtx
+ || !csky_arith_O_operand (operands[2], SImode)))"
+ [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))]
+ {
+ if (csky_split_xor (operands))
+ DONE;
+ }
+ [(set_attr "length" "2,4,4,8")
+ (set_attr "type" "alu,alu,alu,alu")]
+)
+
+(define_insn_and_split "ck801_xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,&r")
+ (xor:SI (match_operand:SI 1 "register_operand" "%0,r")
+ (match_operand:SI 2 "csky_arith_any_imm_operand" "r,i")))]
+ "CSKY_ISA_FEATURE (E1)"
+ "@
+ xor\t%0, %1, %2
+ #"
+ "CONST_INT_P (operands[2])"
+ [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))]
+ {
+ if (csky_split_xor (operands))
+ DONE;
+ }
+ [(set_attr "length" "2,4")
+ (set_attr "type" "alu,alu")]
+)
+
+(define_expand "xordi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (xor:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "register_operand" "")))]
+ ""
+ ""
+)
+
+(define_insn_and_split "*cskyv2_xordi3"
+ [(set (match_operand:DI 0 "register_operand" "=&b,&r")
+ (xor:DI (match_operand:DI 1 "register_operand" "%0, r")
+ (match_operand:DI 2 "register_operand" "b, r")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ {
+ int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD;
+ int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0;
+ rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo);
+ rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi);
+ rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo);
+ rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi);
+ rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo);
+ rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi);
+
+ emit_insn (gen_cskyv2_xorsi3 (l0, l1, l2));
+ emit_insn (gen_cskyv2_xorsi3 (h0, h1, h2));
+ DONE;
+ }
+ [(set_attr "length" "4,8")]
+)
+
+(define_insn_and_split "*ck801_xordi3"
+ [(set (match_operand:DI 0 "register_operand" "=&r")
+ (xor:DI (match_operand:DI 1 "register_operand" "%0")
+ (match_operand:DI 2 "register_operand" "r")))]
+ "CSKY_ISA_FEATURE (E1)"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ {
+ int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD;
+ int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0;
+ rtx l0 = simplify_gen_subreg (SImode, operands[0], DImode, lo);
+ rtx h0 = simplify_gen_subreg (SImode, operands[0], DImode, hi);
+ rtx l1 = simplify_gen_subreg (SImode, operands[1], DImode, lo);
+ rtx h1 = simplify_gen_subreg (SImode, operands[1], DImode, hi);
+ rtx l2 = simplify_gen_subreg (SImode, operands[2], DImode, lo);
+ rtx h2 = simplify_gen_subreg (SImode, operands[2], DImode, hi);
+
+ emit_insn (gen_ck801_xorsi3 (l0, l1, l2));
+ emit_insn (gen_ck801_xorsi3 (h0, h1, h2));
+ DONE;
+ }
+ [(set_attr "length" "4")]
+)
+
+;; -------------------------------------------------------------------------
+;; Div instructions
+;; -------------------------------------------------------------------------
+
+(define_insn "divsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (div:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")))]
+ "TARGET_DIV"
+ "divs\t%0, %1, %2"
+)
+
+(define_insn "udivsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (udiv:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")))]
+ "TARGET_DIV"
+ "divu\t%0, %1, %2"
+)
+
+
+;; -----------------------------------------------------------------
+;; Multiple load and store insns
+;; -----------------------------------------------------------------
+
+(define_expand "load_multiple"
+ [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
+ (match_operand:SI 1 "" ""))
+ (use (match_operand:SI 2 "" ""))])]
+ "TARGET_MULTIPLE_STLD"
+ "{
+ int regno, count, i;
+ rtx base,src;
+
+ if (GET_CODE (operands[2]) != CONST_INT
+ || INTVAL (operands[2]) < 2
+ || INTVAL (operands[2]) > CSKY_MAX_MULTIPLE_STLD
+ || GET_CODE (operands[1]) != MEM
+ || !REG_P (XEXP (operands[1], 0))
+ || XEXP (operands[1], 0) != stack_pointer_rtx
+ || GET_CODE (operands[0]) != REG
+ || (REGNO (XEXP (operands[1], 0)) > REGNO (operands[0])
+ && (REGNO (XEXP (operands[1], 0))
+ < REGNO (operands[0]) + INTVAL (operands[2]))))
+ FAIL;
+
+ count = INTVAL (operands[2]);
+ regno = REGNO (operands[0]);
+
+ operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
+
+ base = force_reg (SImode, XEXP (operands[1], 0));
+ src = replace_equiv_address (operands[1], base);
+
+ for (i = 0; i < count; i++)
+ XVECEXP (operands[3], 0, i)
+ = gen_rtx_SET (gen_rtx_REG (SImode, regno + i),
+ adjust_address_nv (src, SImode, i * 4));
+ }"
+)
+
+(define_expand "store_multiple"
+ [(match_par_dup 3 [(set (match_operand:SI 0 "")
+ (match_operand:SI 1 ""))
+ (use (match_operand:SI 2 ""))])]
+ "TARGET_MULTIPLE_STLD"
+ "{
+ int regno, count, i;
+ rtx base, dest;
+
+ /* Support only storing a constant number of registers to memory and
+ only if at least two registers. */
+ if (GET_CODE (operands[2]) != CONST_INT
+ || INTVAL (operands[2]) < 2
+ || INTVAL (operands[2]) > CSKY_MAX_MULTIPLE_STLD
+ || GET_CODE (operands[0]) != MEM
+ || !REG_P (XEXP (operands[0], 0))
+ || XEXP (operands[0], 0) != stack_pointer_rtx
+ || GET_CODE (operands[1]) != REG
+ || (REGNO (XEXP (operands[0], 0)) >= REGNO (operands[1])
+ && (REGNO (XEXP (operands[0], 0))
+ < REGNO (operands[1]) + INTVAL (operands[2]))))
+ FAIL;
+
+ count = INTVAL (operands[2]);
+ regno = REGNO (operands[1]);
+
+ operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
+
+ base = force_reg (SImode, XEXP (operands[0], 0));
+ dest = replace_equiv_address (operands[0], base);
+
+ for (i = 0; i < count; i++)
+ XVECEXP (operands[3], 0, i)
+ = gen_rtx_SET (adjust_address_nv (dest, SImode, i * 4),
+ gen_rtx_REG (SImode, regno + i));
+ }"
+)
+
+
+(define_insn "*csky_ldmsi12"
+ [(match_parallel 0 "csky_load_multiple_operation"
+ [(set (match_operand:SI 1 "register_operand" "=r")
+ (mem:SI (match_operand:SI 2 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 4))))
+ (set (match_operand:SI 4 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 8))))
+ (set (match_operand:SI 5 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 12))))
+ (set (match_operand:SI 6 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 16))))
+ (set (match_operand:SI 7 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 20))))
+ (set (match_operand:SI 8 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 24))))
+ (set (match_operand:SI 9 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 28))))
+ (set (match_operand:SI 10 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 32))))
+ (set (match_operand:SI 11 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 36))))
+ (set (match_operand:SI 12 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 40))))
+ (set (match_operand:SI 13 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 44))))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 12"
+ {
+ static char load_op[256] = {0};
+ int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[count];
+ sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz);
+ return load_op;
+ }
+)
+
+(define_insn "*csky_ldmsi11"
+ [(match_parallel 0 "csky_load_multiple_operation"
+ [(set (match_operand:SI 1 "register_operand" "=r")
+ (mem:SI (match_operand:SI 2 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 4))))
+ (set (match_operand:SI 4 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 8))))
+ (set (match_operand:SI 5 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 12))))
+ (set (match_operand:SI 6 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 16))))
+ (set (match_operand:SI 7 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 20))))
+ (set (match_operand:SI 8 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 24))))
+ (set (match_operand:SI 9 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 28))))
+ (set (match_operand:SI 10 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 32))))
+ (set (match_operand:SI 11 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 36))))
+ (set (match_operand:SI 12 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 40))))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 11"
+ {
+ static char load_op[256] = {0};
+ int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[count];
+ sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz);
+ return load_op;
+ }
+)
+
+(define_insn "*csky_ldmsi10"
+ [(match_parallel 0 "csky_load_multiple_operation"
+ [(set (match_operand:SI 1 "register_operand" "=r")
+ (mem:SI (match_operand:SI 2 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 4))))
+ (set (match_operand:SI 4 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 8))))
+ (set (match_operand:SI 5 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 12))))
+ (set (match_operand:SI 6 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 16))))
+ (set (match_operand:SI 7 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 20))))
+ (set (match_operand:SI 8 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 24))))
+ (set (match_operand:SI 9 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 28))))
+ (set (match_operand:SI 10 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 32))))
+ (set (match_operand:SI 11 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 36))))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 10"
+ {
+ static char load_op[256] = {0};
+ int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[count];
+ sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz);
+ return load_op;
+ }
+)
+
+(define_insn "*csky_ldmsi9"
+ [(match_parallel 0 "csky_load_multiple_operation"
+ [(set (match_operand:SI 1 "register_operand" "=r")
+ (mem:SI (match_operand:SI 2 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 4))))
+ (set (match_operand:SI 4 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 8))))
+ (set (match_operand:SI 5 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 12))))
+ (set (match_operand:SI 6 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 16))))
+ (set (match_operand:SI 7 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 20))))
+ (set (match_operand:SI 8 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 24))))
+ (set (match_operand:SI 9 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 28))))
+ (set (match_operand:SI 10 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 32))))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 9"
+ {
+ static char load_op[256] = {0};
+ int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[count];
+ sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz);
+ return load_op;
+ }
+)
+
+(define_insn "*csky_ldmsi8"
+ [(match_parallel 0 "csky_load_multiple_operation"
+ [(set (match_operand:SI 1 "register_operand" "=r")
+ (mem:SI (match_operand:SI 2 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 4))))
+ (set (match_operand:SI 4 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 8))))
+ (set (match_operand:SI 5 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 12))))
+ (set (match_operand:SI 6 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 16))))
+ (set (match_operand:SI 7 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 20))))
+ (set (match_operand:SI 8 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 24))))
+ (set (match_operand:SI 9 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 28))))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 8"
+ {
+ static char load_op[256] = {0};
+ int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[count];
+ sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz);
+ return load_op;
+ }
+)
+
+(define_insn "*csky_ldmsi7"
+ [(match_parallel 0 "csky_load_multiple_operation"
+ [(set (match_operand:SI 1 "register_operand" "=r")
+ (mem:SI (match_operand:SI 2 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 4))))
+ (set (match_operand:SI 4 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 8))))
+ (set (match_operand:SI 5 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 12))))
+ (set (match_operand:SI 6 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 16))))
+ (set (match_operand:SI 7 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 20))))
+ (set (match_operand:SI 8 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 24))))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 7"
+ {
+ static char load_op[256] = {0};
+ int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[count];
+ sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz);
+ return load_op;
+ }
+)
+
+(define_insn "*csky_ldmsi6"
+ [(match_parallel 0 "csky_load_multiple_operation"
+ [(set (match_operand:SI 1 "register_operand" "=r")
+ (mem:SI (match_operand:SI 2 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 4))))
+ (set (match_operand:SI 4 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 8))))
+ (set (match_operand:SI 5 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 12))))
+ (set (match_operand:SI 6 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 16))))
+ (set (match_operand:SI 7 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 20))))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 6"
+ {
+ static char load_op[256] = {0};
+ int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[count];
+ sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz);
+ return load_op;
+ }
+)
+
+
+(define_insn "*csky_ldmsi5"
+ [(match_parallel 0 "csky_load_multiple_operation"
+ [(set (match_operand:SI 1 "register_operand" "=r")
+ (mem:SI (match_operand:SI 2 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 4))))
+ (set (match_operand:SI 4 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 8))))
+ (set (match_operand:SI 5 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 12))))
+ (set (match_operand:SI 6 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 16))))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 5"
+ {
+ static char load_op[256] = {0};
+ int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[count];
+ sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz);
+ return load_op;
+ }
+)
+
+
+(define_insn "*csky_ldmsi4"
+ [(match_parallel 0 "csky_load_multiple_operation"
+ [(set (match_operand:SI 1 "register_operand" "=r")
+ (mem:SI (match_operand:SI 2 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 4))))
+ (set (match_operand:SI 4 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 8))))
+ (set (match_operand:SI 5 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 12))))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 4"
+ {
+ static char load_op[256] = {0};
+ int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[count];
+ sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz);
+ return load_op;
+ }
+)
+
+
+(define_insn "*csky_ldmsi3"
+ [(match_parallel 0 "csky_load_multiple_operation"
+ [(set (match_operand:SI 1 "register_operand" "=r")
+ (mem:SI (match_operand:SI 2 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 4))))
+ (set (match_operand:SI 4 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 8))))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 3"
+ {
+ static char load_op[256] = {0};
+ int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[count];
+ sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz);
+ return load_op;
+ }
+)
+
+
+(define_insn "*csky_ldmsi2"
+ [(match_parallel 0 "csky_load_multiple_operation"
+ [(set (match_operand:SI 1 "register_operand" "=r")
+ (mem:SI (match_operand:SI 2 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (mem:SI (plus:SI (match_dup 2) (const_int 4))))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 2"
+ {
+ static char load_op[256] = {0};
+ int count = REGNO (operands[1]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[count];
+ sprintf (load_op, \"ldm\t%%1 - %s, (%%2)\", reg_rz);
+ return load_op;
+ }
+)
+
+(define_insn "*csky_stmsi12"
+ [(match_parallel 0 "csky_store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 3 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 4 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+ (match_operand:SI 5 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+ (match_operand:SI 6 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
+ (match_operand:SI 7 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24)))
+ (match_operand:SI 8 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28)))
+ (match_operand:SI 9 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32)))
+ (match_operand:SI 10 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 36)))
+ (match_operand:SI 11 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 40)))
+ (match_operand:SI 12 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 44)))
+ (match_operand:SI 13 "register_operand" "r"))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 12"
+ {
+ static char load_op[256] = {0};
+ int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[end];
+ sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz);
+ return load_op;
+ }
+)
+
+
+(define_insn "*csky_stmsi11"
+ [(match_parallel 0 "csky_store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 3 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 4 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+ (match_operand:SI 5 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+ (match_operand:SI 6 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
+ (match_operand:SI 7 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24)))
+ (match_operand:SI 8 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28)))
+ (match_operand:SI 9 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32)))
+ (match_operand:SI 10 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 36)))
+ (match_operand:SI 11 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 40)))
+ (match_operand:SI 12 "register_operand" "r"))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 11"
+ {
+ static char load_op[256] = {0};
+ int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[end];
+ sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz);
+ return load_op;
+ }
+)
+
+
+(define_insn "*csky_stmsi10"
+ [(match_parallel 0 "csky_store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 3 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 4 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+ (match_operand:SI 5 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+ (match_operand:SI 6 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
+ (match_operand:SI 7 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24)))
+ (match_operand:SI 8 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28)))
+ (match_operand:SI 9 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32)))
+ (match_operand:SI 10 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 36)))
+ (match_operand:SI 11 "register_operand" "r"))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 10"
+ {
+ static char load_op[256] = {0};
+ int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[end];
+ sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz);
+ return load_op;
+ }
+)
+
+
+(define_insn "*csky_stmsi9"
+ [(match_parallel 0 "csky_store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 3 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 4 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+ (match_operand:SI 5 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+ (match_operand:SI 6 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
+ (match_operand:SI 7 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24)))
+ (match_operand:SI 8 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28)))
+ (match_operand:SI 9 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 32)))
+ (match_operand:SI 10 "register_operand" "r"))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 9"
+ {
+ static char load_op[256] = {0};
+ int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[end];
+ sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz);
+ return load_op;
+ }
+)
+
+
+(define_insn "*csky_stmsi8"
+ [(match_parallel 0 "csky_store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 3 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 4 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+ (match_operand:SI 5 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+ (match_operand:SI 6 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
+ (match_operand:SI 7 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24)))
+ (match_operand:SI 8 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28)))
+ (match_operand:SI 9 "register_operand" "r"))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 8"
+ {
+ static char load_op[256] = {0};
+ int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[end];
+ sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz);
+ return load_op;
+ }
+)
+
+
+(define_insn "*csky_stmsi7"
+ [(match_parallel 0 "csky_store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 3 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 4 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+ (match_operand:SI 5 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+ (match_operand:SI 6 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
+ (match_operand:SI 7 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24)))
+ (match_operand:SI 8 "register_operand" "r"))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 7"
+ {
+ static char load_op[256] = {0};
+ int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[end];
+ sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz);
+ return load_op;
+ }
+)
+
+
+(define_insn "*csky_stmsi6"
+ [(match_parallel 0 "csky_store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 3 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 4 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+ (match_operand:SI 5 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+ (match_operand:SI 6 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
+ (match_operand:SI 7 "register_operand" "r"))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 6"
+ {
+ static char load_op[256] = {0};
+ int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[end];
+ sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz);
+ return load_op;
+ }
+)
+
+(define_insn "*csky_stmsi5"
+ [(match_parallel 0 "csky_store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 3 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 4 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+ (match_operand:SI 5 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+ (match_operand:SI 6 "register_operand" "r"))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 5"
+ {
+ static char load_op[256] = {0};
+ int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[end];
+ sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz);
+ return load_op;
+ }
+)
+
+
+(define_insn "*csky_stmsi4"
+ [(match_parallel 0 "csky_store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 3 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 4 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+ (match_operand:SI 5 "register_operand" "r"))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 4"
+ {
+ static char load_op[256] = {0};
+ int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[end];
+ sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz);
+ return load_op;
+ }
+)
+
+
+(define_insn "*csky_stmsi3"
+ [(match_parallel 0 "csky_store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 3 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 4 "register_operand" "r"))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 3"
+ {
+ static char load_op[256] = {0};
+ int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[end];
+ sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz);
+ return load_op;
+ }
+)
+
+
+(define_insn "*csky_stmsi2"
+ [(match_parallel 0 "csky_store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 3 "register_operand" "r"))
+ ])]
+ "TARGET_MULTIPLE_STLD && XVECLEN (operands[0], 0) == 2"
+ {
+ static char load_op[256] = {0};
+ int end = REGNO (operands[2]) + XVECLEN (operands[0], 0) - 1;
+ const char *reg_rz = reg_names[end];
+ sprintf (load_op, \"stm\t%%2 - %s, (%%1)\", reg_rz);
+ return load_op;
+ }
+)
+
+
+;; ------------------------------------------------------------------------
+;; Jump and linkage insns
+;; ------------------------------------------------------------------------
+
+(define_expand "tablejump"
+ [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "r"))
+ (use (label_ref (match_operand 1 "" "")))])]
+ ""
+ "
+ if (flag_pic)
+ operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
+ pic_offset_table_rtx, NULL_RTX,
+ 1, OPTAB_DIRECT);
+ "
+)
+
+(define_insn "*tablejump"
+ [(set (pc) (match_operand:SI 0 "register_operand" "r"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "jmp %0"
+ [(set_attr "type" "branch_jmp")]
+)
+
+(define_expand "jump"
+ [(set (pc) (label_ref (match_operand 0 "" "")))]
+ ""
+ ""
+)
+
+(define_insn "*csky_jump"
+ [(set (pc) (label_ref (match_operand 0 "" "")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "jbr %l0"
+ [(set_attr "type" "branch")]
+)
+
+;; The length of bsr is not really 5; it's used to distinguish from br32.
+;; Since the length attribute is treated specially it doesn't seem possible
+;; to compute the far_jump attribute directly and use that.
+
+(define_insn "*ck801_ck802_jump"
+ [(set (pc) (label_ref (match_operand 0 "" "")))]
+ "CSKY_ISA_FEATURE (E1) || CSKY_ISA_FEATURE (E2)"
+ "*{
+ if (get_attr_length (insn) != 5)
+ return \"jbr\\t%l0\";
+ else
+ return \"bsr\\t%l0\\t//far jump\";
+ }"
+ [(set_attr "type" "branch")
+ (set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "5")
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 0) (pc)) (const_int -1024))
+ (le (minus (match_dup 0) (pc)) (const_int 1022)))
+ (const_int 2)
+ (if_then_else
+ (and (ge (minus (match_dup 0) (pc)) (const_int -65536))
+ (le (minus (match_dup 0) (pc)) (const_int 65534)))
+ (const_int 4)
+ (const_int 5))))]
+)
+
+(define_insn "indirect_jump"
+ [(set (pc) (match_operand:SI 0 "register_operand" "b,r"))]
+ ""
+ "@
+ jmp\t%0
+ jmp\t%0"
+ [(set_attr "length" "2,4")
+ (set_attr "type" "branch_jmp")]
+)
+
+
+;; ------------------------------------------------------------------------
+;; Conditional jump insns
+;; ------------------------------------------------------------------------
+
+(define_expand "cbranchsi4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:SI 1 "csky_compare_operand")
+ (match_operand:SI 2 "nonmemory_operand")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ ""
+ "{
+ enum rtx_code code = GET_CODE (operands[0]);
+
+ if (CSKY_ISA_FEATURE (2E3)
+ && (code == LE || code == LT || code == GT
+ || code == GE || code == EQ || code == NE)
+ && operands[2] == const0_rtx)
+ {
+ /* These cases match the jbez, jbnez, etc insns below.
+ TODO: Handling this in the expander is suboptimal since it
+ fails to detect cases where the constant 0 would fall out
+ from subsequent forward propagation or loop optimizers; maybe
+ it would be better to have a splitter here, but when to split? */
+ }
+ else
+ {
+ bool invert = csky_emit_compare (code, operands[1], operands[2]);
+
+ if (invert)
+ emit_jump_insn (gen_csky_jbf (operands[3]));
+ else
+ emit_jump_insn (gen_csky_jbt (operands[3]));
+ DONE;
+ }
+ }"
+)
+
+(define_insn "csky_jbt"
+ [(set (pc)
+ (if_then_else (ne (reg:CC CSKY_CC_REGNUM) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ "CSKY_ISA_FEATURE (2E3)"
+ "jbt\t%l0"
+ [(set_attr "type" "cbranch")]
+)
+
+(define_insn "csky_jbf"
+ [(set (pc)
+ (if_then_else (eq (reg:CC CSKY_CC_REGNUM) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ "CSKY_ISA_FEATURE (2E3)"
+ "jbf\t%l0"
+ [(set_attr "type" "cbranch")]
+)
+
+
+;;; CK802 has 32-bit jbt/jbf instructions, but no insn other
+;;; than bsr for far jumps.
+
+(define_insn "ck802_jbt"
+ [(set (pc) (if_then_else (ne (reg:CC CSKY_CC_REGNUM) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ "CSKY_ISA_FEATURE (E2)"
+ {
+ if (get_attr_length (insn) == 6)
+ return \"jbf\\t.LCB%=\;bsr\\t%l0\\t//far jump\\n.LCB%=:\";
+ else
+ return \"jbt\\t%l0\";
+ }
+ [(set_attr "type" "cbranch")
+ (set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "6")
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 0) (pc)) (const_int -1024))
+ (le (minus (match_dup 0) (pc)) (const_int 1022)))
+ (const_int 2)
+ (if_then_else
+ (and (ge (minus (match_dup 0) (pc)) (const_int -65534))
+ (le (minus (match_dup 0) (pc)) (const_int 65534)))
+ (const_int 4)
+ (const_int 6))))]
+)
+
+(define_insn "ck802_jbf"
+ [(set (pc) (if_then_else (eq (reg:CC CSKY_CC_REGNUM) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ "CSKY_ISA_FEATURE (E2)"
+ {
+ if (get_attr_length (insn) == 6)
+ return \"jbt\\t.LCB%=\;bsr\\t%l0\\t//far jump\\n.LCB%=:\";
+ else
+ return \"jbf\\t%l0\";
+ }
+ [(set_attr "type" "cbranch")
+ (set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "6")
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 0) (pc)) (const_int -1024))
+ (le (minus (match_dup 0) (pc)) (const_int 1022)))
+ (const_int 2)
+ (if_then_else
+ (and (ge (minus (match_dup 0) (pc)) (const_int -65534))
+ (le (minus (match_dup 0) (pc)) (const_int 65534)))
+ (const_int 4)
+ (const_int 6))))]
+)
+
+;; The length of the bsr case is not really 7; it's used to distinguish
+;; from br32.
+;; Note that we have to adjust the backward range of the jbr case to
+;; account for the jbf in front of it.
+(define_insn "ck801_jbt"
+ [(set (pc) (if_then_else (ne (reg:CC CSKY_CC_REGNUM) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ "CSKY_ISA_FEATURE (E1)"
+ {
+ if (get_attr_length (insn) == 6)
+ return \"jbf\\t.LCB%=\;jbr\\t%l0\\n.LCB%=:\";
+ else if (get_attr_length (insn) == 7)
+ return \"jbf\\t.LCB%=\;bsr\\t%l0\\t//far jump\\n.LCB%=:\";
+ else
+ return \"jbt\\t%l0\";
+ }
+ [(set_attr "type" "cbranch")
+ (set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "7")
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 0) (pc)) (const_int -1024))
+ (le (minus (match_dup 0) (pc)) (const_int 1022)))
+ (const_int 2)
+ (if_then_else
+ (and (ge (minus (match_dup 0) (pc)) (const_int -65534))
+ (le (minus (match_dup 0) (pc)) (const_int 65534)))
+ (const_int 6)
+ (const_int 7))))]
+)
+
+(define_insn "ck801_jbf"
+ [(set (pc)
+ (if_then_else (eq (reg:CC CSKY_CC_REGNUM) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ "CSKY_ISA_FEATURE (E1)"
+ {
+ if (get_attr_length (insn) == 6)
+ return \"jbt\\t.LCB%=\;jbr\\t%l0\\n.LCB%=:\";
+ else if (get_attr_length (insn) == 7)
+ return \"jbt\\t.LCB%=\;bsr\\t%l0\\t//far jump\\n.LCB%=:\";
+ else
+ return \"jbf\\t%l0\";
+ }
+ [(set_attr "type" "cbranch")
+ (set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "7")
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 0) (pc)) (const_int -1024))
+ (le (minus (match_dup 0) (pc)) (const_int 1022)))
+ (const_int 2)
+ (if_then_else
+ (and (ge (minus (match_dup 0) (pc)) (const_int -65534))
+ (le (minus (match_dup 0) (pc)) (const_int 65534)))
+ (const_int 6)
+ (const_int 7))))]
+)
+
+(define_code_iterator zero_cond [lt le gt ge eq ne])
+
+(define_code_attr inst [(lt "jblz") (le "jblsz") (gt "jbhz") (ge "jbhsz") (eq "jbez") (ne "jbnez")])
+
+(define_insn "*<inst>"
+ [(set (pc)
+ (if_then_else (zero_cond (match_operand:SI 0 "register_operand" "r")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "CSKY_ISA_FEATURE (2E3)"
+ "<inst>\t%0, %l1"
+ [(set_attr "type" "cbranch")]
+)
+
+;; ------------------------------------------------------------------------
+;; return insns
+;; ------------------------------------------------------------------------
+
+(define_insn "simple_return"
+ [(simple_return)]
+ "reload_completed"
+ "*
+ return csky_output_return_instruction ();
+ "
+)
+
+(define_expand "eh_return"
+ [(use (match_operand 0 "general_operand" ""))]
+ ""
+ "{
+ emit_insn (gen_csky_eh_return (operands[0]));
+ DONE;
+ }"
+)
+
+;; We can't expand this before we know where the link register is stored.
+(define_insn_and_split "csky_eh_return"
+ [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
+ VUNSPEC_EH_RETURN)
+ (clobber (match_scratch:SI 1 "=&r"))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ "{
+ csky_set_eh_return_address (operands[0], operands[1]);
+ DONE;
+ }"
+)
+
+;; -------------------------------------------------------------------------
+;; SImode signed integer comparisons
+;; -------------------------------------------------------------------------
+
+(define_insn "*cmpnesi_r"
+ [(set (reg:CC CSKY_CC_REGNUM)
+ (ne:CC (match_operand:SI 0 "register_operand" "b,r")
+ (match_operand:SI 1 "register_operand" "b,r")))]
+ ""
+ "@
+ cmpne\t%0, %1
+ cmpne\t%0, %1"
+ [(set_attr "length" "2,4")
+ (set_attr "type" "cmp")]
+)
+
+;; cmpnei range is 0-31 for Smart mode.
+(define_insn "smart_cmpnesi_i"
+ [(set (reg:CC CSKY_CC_REGNUM)
+ (ne:CC (match_operand:SI 0 "register_operand" "a")
+ (match_operand:SI 1 "csky_literal_K_operand" "K")))]
+ "TARGET_MINI_REGISTERS"
+ "cmpnei\t%0, %1"
+ [(set_attr "type" "cmp")]
+)
+
+;; cmpnei range is 0 - 65536 for Fast mode.
+(define_insn "fast_cmpnesi_i"
+ [(set (reg:CC CSKY_CC_REGNUM)
+ (ne:CC (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "csky_literal_I_operand" "I")))]
+ "!TARGET_MINI_REGISTERS && CSKY_ISA_FEATURE (E2)"
+ "cmpnei\t%0, %1"
+ [(set_attr "type" "cmp")]
+)
+
+(define_insn "*cmpgtsi"
+ [(set (reg:CC CSKY_CC_REGNUM)
+ (gt:CC (match_operand:SI 0 "register_operand" "b,r")
+ (match_operand:SI 1 "register_operand" "b,r")))]
+ ""
+ "cmplt\t%1, %0"
+ [(set_attr "length" "2,4")
+ (set_attr "type" "cmp")]
+)
+
+(define_insn "cmpltsi_r"
+ [(set (reg:CC CSKY_CC_REGNUM)
+ (lt:CC (match_operand:SI 0 "register_operand" "b,r")
+ (match_operand:SI 1 "register_operand" "b,r")))]
+ ""
+ "cmplt\t%0, %1"
+ [(set_attr "length" "2,4")
+ (set_attr "type" "cmp")]
+)
+
+;; cmplti range is 1-32 for Smart mode.
+(define_insn "*smart_cmpltsi_i"
+ [(set (reg:CC CSKY_CC_REGNUM)
+ (lt:CC (match_operand:SI 0 "register_operand" "a")
+ (match_operand:SI 1 "csky_literal_J_operand" "J")))]
+ "TARGET_MINI_REGISTERS"
+ "cmplti\t%0, %1"
+ [(set_attr "length" "2")
+ (set_attr "type" "cmp")]
+)
+
+
+;; cmplti range is 1-65536 for Fast mode.
+(define_insn "*fast_cmpltsi_i"
+ [(set (reg:CC CSKY_CC_REGNUM)
+ (lt:CC (match_operand:SI 0 "register_operand" "a,r")
+ (match_operand:SI 1 "csky_literal_Uk_operand" "J,Uk")))]
+ "!TARGET_MINI_REGISTERS && CSKY_ISA_FEATURE (E2)"
+ "cmplti\t%0, %1"
+ [(set_attr "length" "2,4")
+ (set_attr "type" "cmp")]
+)
+
+; Covers cmplti x,0.
+(define_insn "*cskyv2_cmpltsi_0"
+ [(set (reg:CC CSKY_CC_REGNUM)
+ (lt:CC (match_operand:SI 0 "register_operand" "a,r")
+ (const_int 0)))]
+ "CSKY_ISA_FEATURE (E2)"
+ "btsti\t%0, 31"
+ [(set_attr "length" "2,4")
+ (set_attr "type" "cmp")]
+)
+
+(define_insn "*ck801_cmpltsi_0"
+ [(set (reg:CC CSKY_CC_REGNUM)
+ (lt:CC (match_operand:SI 0 "register_operand" "a")
+ (const_int 0)))]
+ "CSKY_ISA_FEATURE (E1)"
+ "btsti\t%0, 31"
+ [(set_attr "type" "cmp")]
+)
+
+;; Decrement and test instructions.
+;; In theory decne could be used in conjunction with jbt to implement
+;; doloop_end, but that seems to encourage the loop optimizer to introduce
+;; an additional induction variable and doesn't actually result in tighter
+;; loop code for that reason.
+
+(define_insn "*cskyv2_declt"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "Uh")))
+ (set (reg:CC CSKY_CC_REGNUM)
+ (lt:CC (plus:SI (match_dup 1) (match_dup 2))
+ (const_int 0)))]
+ "CSKY_ISA_FEATURE (2E3)"
+ "declt\t%0, %1, %M2"
+)
+
+(define_insn "*cskyv2_decgt"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "Uh")))
+ (set (reg:CC CSKY_CC_REGNUM)
+ (gt:CC (plus:SI (match_dup 1) (match_dup 2))
+ (const_int 0)))]
+ "CSKY_ISA_FEATURE (2E3)"
+ "decgt\t%0, %1, %M2"
+)
+
+(define_insn "*cskyv2_decne"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "Uh")))
+ (set (reg:CC CSKY_CC_REGNUM)
+ (ne:CC (plus:SI (match_dup 1) (match_dup 2))
+ (const_int 0)))]
+ "CSKY_ISA_FEATURE (2E3)"
+ "decne\t%0, %1, %M2"
+)
+
+;; -------------------------------------------------------------------------
+;; SImode unsigned integer comparisons
+;; -------------------------------------------------------------------------
+
+(define_insn "cmpgeusi_r"
+ [(set (reg:CC CSKY_CC_REGNUM)
+ (geu:CC (match_operand:SI 0 "register_operand" "b,r")
+ (match_operand:SI 1 "register_operand" "b,r")))]
+ ""
+ "cmphs\t%0, %1"
+ [(set_attr "length" "2,4")
+ (set_attr "type" "cmp")]
+)
+
+(define_insn "*smart_cmpgeusi_i"
+ [(set (reg:CC CSKY_CC_REGNUM)
+ (geu:CC (match_operand:SI 0 "register_operand" "a")
+ (match_operand:SI 1 "csky_literal_J_operand" "J")))]
+ "TARGET_MINI_REGISTERS"
+ "cmphsi\t%0, %1"
+ [(set_attr "length" "2")
+ (set_attr "type" "cmp")]
+)
+
+(define_insn "*fast_cmpgeusi_i"
+ [(set (reg:CC CSKY_CC_REGNUM)
+ (geu:CC (match_operand:SI 0 "register_operand" "a,r")
+ (match_operand:SI 1 "csky_literal_Uk_operand" "J,Uk")))]
+ "!TARGET_MINI_REGISTERS && CSKY_ISA_FEATURE (E2)"
+ "cmphsi\t%0, %1"
+ [(set_attr "length" "2,4")
+ (set_attr "type" "cmp")]
+)
+
+(define_insn "*cmpleusi"
+ [(set (reg:CC CSKY_CC_REGNUM)
+ (leu:CC (match_operand:SI 0 "register_operand" "b,r")
+ (match_operand:SI 1 "register_operand" "b,r")))]
+ ""
+ "cmphs\t%1, %0"
+ [(set_attr "length" "2,4")
+ (set_attr "type" "cmp")]
+)
+
+;; -------------------------------------------------------------------------
+;; Function call insns
+;; -------------------------------------------------------------------------
+
+(define_expand "call"
+ [(parallel [(call (match_operand:SI 0 "" "") (match_operand 1 "" ""))
+ (clobber (reg:SI CSKY_LR_REGNUM))])]
+ ""
+ "
+ {
+ rtx pic_ref;
+ rtx addr_ref = XEXP (operands[0], 0);
+
+ if (flag_pic
+ && (CONSTANT_P (addr_ref)
+ || csky_symbol_mentioned_p (addr_ref)
+ || csky_label_mentioned_p (addr_ref)))
+ {
+ pic_ref = csky_legitimize_pic_address (addr_ref, 0, false);
+ operands[0] = gen_rtx_MEM (GET_MODE (pic_ref), pic_ref);
+ }
+
+ if (GET_CODE (operands[0]) == MEM
+ && ! register_operand (XEXP (operands[0], 0), SImode)
+ && ! csky_symbolic_address_p (XEXP (operands[0], 0))
+ && ! (flag_pic
+ && csky_unspec_operand (XEXP (operands[0], 0), SImode)))
+ operands[0] = gen_rtx_MEM (GET_MODE (operands[0]),
+ force_reg (Pmode, XEXP (operands[0], 0)));
+ }"
+)
+
+
+(define_insn "*call_internal"
+ [(call (mem:SI (match_operand:SI 0 "csky_call_address_operand" "b,r,S"))
+ (match_operand 1 "" ""))
+ (clobber (reg:SI CSKY_LR_REGNUM))]
+ ""
+ "@
+ jsr\t%0
+ jsr\t%0
+ jbsr\t%0"
+ [(set_attr "length" "2,4,4")
+ (set_attr "type" "call_jsr,call_jsr,call")]
+)
+
+(define_insn "*call_internal_pic"
+ [(call (mem:SI (match_operand:SI 0 "csky_unspec_operand" "X"))
+ (match_operand 1 "" ""))
+ (clobber (reg:SI CSKY_LR_REGNUM))]
+ "flag_pic"
+ "* return csky_output_call (operands, 0);"
+ [(set_attr "length" "4")]
+)
+
+(define_expand "call_value"
+ [(parallel [(set (match_operand 0 "register_operand" "")
+ (call (match_operand:SI 1 "" "") (match_operand 2 "" "")))
+ (clobber (reg:SI CSKY_LR_REGNUM))])]
+ ""
+ "{
+ rtx pic_ref;
+ rtx addr_ref = XEXP (operands[1], 0);
+
+ if (flag_pic
+ && (CONSTANT_P (addr_ref)
+ || csky_symbol_mentioned_p (addr_ref)
+ || csky_label_mentioned_p (addr_ref)))
+ {
+ pic_ref = csky_legitimize_pic_address (addr_ref, 0, false);
+ operands[1] = gen_rtx_MEM (GET_MODE (pic_ref), pic_ref);
+ }
+
+ if (GET_CODE (operands[1]) == MEM
+ && ! register_operand (XEXP (operands[1], 0), SImode)
+ && ! csky_symbolic_address_p (XEXP (operands[1], 0))
+ && ! (flag_pic
+ && csky_unspec_operand (XEXP (operands[1], 0), SImode)))
+ operands[1] = gen_rtx_MEM (GET_MODE (operands[1]),
+ force_reg (Pmode, XEXP (operands[1], 0)));
+ }")
+
+
+(define_insn "*call_value_internal"
+ [(set (match_operand 0 "register_operand" "=r,r,r")
+ (call (mem:SI (match_operand:SI 1 "csky_call_address_operand" "b, r,S"))
+ (match_operand 2 "" "")))
+ (clobber (reg:SI CSKY_LR_REGNUM))]
+ ""
+ "@
+ jsr\t%1
+ jsr\t%1
+ jbsr\t%1"
+ [(set_attr "length" "2,4,4")
+ (set_attr "type" "call_jsr,call_jsr,call")]
+)
+
+(define_insn "*call_value_internal_pic"
+ [(set (match_operand 0 "register_operand" "=r")
+ (call (mem:SI (match_operand:SI 1 "csky_unspec_operand" "X"))
+ (match_operand 2 "" "")))
+ (clobber (reg:SI CSKY_LR_REGNUM))]
+ "flag_pic"
+ "* return csky_output_call (operands, 1);"
+)
+
+(define_insn "*call_value_struct"
+ [(set (match_parallel 0 ""
+ [(expr_list (match_operand 3 "register_operand" "")
+ (match_operand 4 "immediate_operand" ""))
+ (expr_list (match_operand 5 "register_operand" "")
+ (match_operand 6 "immediate_operand" ""))])
+ (call (mem:SI (match_operand:SI 1 "csky_call_address_operand" "b,r,S"))
+ (match_operand 2 "" "")))
+ (clobber (reg:SI CSKY_LR_REGNUM))]
+ ""
+ "@
+ jsr\t%1
+ jsr\t%1
+ jbsr\t%1"
+ [(set_attr "length" "2,4,4")
+ (set_attr "type" "call_jsr,call_jsr,call")]
+)
+
+(define_insn "*call_value_struct_pic"
+ [(set (match_parallel 0 ""
+ [(expr_list (match_operand 3 "register_operand" "")
+ (match_operand 4 "immediate_operand" ""))
+ (expr_list (match_operand 5 "register_operand" "")
+ (match_operand 6 "immediate_operand" ""))])
+ (call (mem:SI (match_operand:SI 1 "csky_unspec_operand" "X"))
+ (match_operand 2 "" "")))
+ (clobber (reg:SI CSKY_LR_REGNUM))]
+ "flag_pic"
+ "* return csky_output_call (operands, 1);"
+)
+
+
+;; -------------------------------------------------------------
+;; prologue & epilogue
+;; -------------------------------------------------------------
+
+(define_expand "prologue"
+ [(clobber (const_int 0))]
+ ""
+ "
+ {
+ csky_expand_prologue ();
+ DONE;
+ }"
+)
+
+(define_expand "epilogue"
+ [(clobber (const_int 0))]
+ ""
+ "
+ {
+ csky_expand_epilogue ();
+ DONE;
+ }"
+)
+
+/* TODO: pushpop */
+;; Push multiple registers to the stack. Registers are in parallel (use ...)
+;; expressions. For simplicity, the first register is also in the unspec
+;; part.
+(define_insn "*push_multi"
+ [(match_parallel 2 "registers_push"
+ [(set (match_operand:BLK 0 "push_memory_operand" "")
+ (unspec:BLK [(match_operand:SI 1 "register_operand" "")]
+ UNSPEC_PUSHPOP_MULT))])]
+ ""
+ {
+ int num_saves = XVECLEN (operands[2], 0);
+ int i;
+ char pattern[100];
+
+ strcpy (pattern, \"push\\t%1\");
+
+ for (i = 1; i < num_saves; i++)
+ {
+ strcat (pattern, \", \");
+ strcat (pattern,
+ reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
+ }
+
+ output_asm_insn (pattern, operands);
+
+ return \"\";
+ }
+ [(set (attr "length")
+ (symbol_ref "csky_compute_pushpop_length (operands)"))]
+)
+
+;; Pop (as used in epilogue RTL)
+;;
+(define_insn "*pop_multi"
+ [(match_parallel 2 "registers_pop"
+ [(return)
+ (set (match_operand:SI 1 "register_operand" "")
+ (unspec:SI [(match_operand:SI 0 "pop_memory_operand" "")]
+ UNSPEC_PUSHPOP_MULT))])]
+ ""
+ {
+ int num_saves = XVECLEN (operands[2], 0);
+ int i;
+ char pattern[100];
+
+ strcpy (pattern, \"pop\\t%1\");
+
+ for (i = 2; i < num_saves; i++)
+ {
+ strcat (pattern, \", \");
+ strcat (pattern,
+ reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
+ }
+
+ output_asm_insn (pattern, operands);
+
+ return \"\";
+ }
+ [(set (attr "length")
+ (symbol_ref "csky_compute_pushpop_length (operands)"))]
+)
+
+
+;; -------------------------------------------------------------------------
+;; PIC related insns
+;; -------------------------------------------------------------------------
+
+(define_insn "prologue_get_pc"
+ [(set (reg:SI 28)
+ (match_operand:SI 0 "" "X"))]
+ "(GET_CODE (operands[0]) == UNSPEC)
+ && (XINT (operands[0], 1) == UNSPEC_PIC_SYMBOL_GOTPC_GRS)"
+ {
+ operands[0] = XVECEXP (operands[0], 0, 0);
+ output_asm_insn (\"grs\tgb, %0\", operands);
+ default_internal_label (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (XEXP (operands[0], 0)));
+ return \"\";
+ }
+)
+
+(define_insn "*pic_got_pc"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC_SYMBOL_GOTPC))]
+ "flag_pic"
+ "lrw\t%0, %1@GOTPC"
+)
+
+(define_insn "*pic_symbol_gotoff"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC_SYMBOL_GOTOFF))]
+ "flag_pic"
+ "lrw\t%0, %1@GOTOFF"
+)
+
+(define_insn "*pic_symbol_got"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC_SYMBOL_GOT))]
+ "flag_pic"
+ "lrw\t%0, %1@GOT"
+)
+
+(define_insn "*pic_symbol_plt"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC_SYMBOL_PLT))]
+ "flag_pic"
+ "lrw\t%0, %1@PLT"
+)
+
+(define_insn "*pic_symbol_grs"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC_SYMBOL_GRS))]
+ "flag_pic"
+ "grs\t%0, %1"
+)
+
+(define_expand "builtin_setjmp_receiver"
+ [(label_ref (match_operand 0 "" ""))]
+ "flag_pic"
+ "{
+ rtx l1 = gen_label_rtx();
+ rtx grs_label = gen_rtx_LABEL_REF (SImode, l1);
+ rtx reg_gb = gen_rtx_REG (SImode, PIC_OFFSET_TABLE_REGNUM);
+ rtx reg_temp = gen_rtx_REG (SImode, 12);
+
+ rtx tmp0_unspec = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (1, grs_label),
+ UNSPEC_PIC_SYMBOL_GOTPC_GRS);
+ rtx tmp1_unspec = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (1, grs_label),
+ UNSPEC_PIC_SYMBOL_GOTPC);
+
+ emit_insn (gen_prologue_get_pc (tmp0_unspec));
+ emit_move_insn (reg_temp, tmp1_unspec);
+ emit_insn (gen_addsi3 (reg_gb, reg_gb, reg_temp));
+ emit_use (reg_gb);
+
+ DONE;
+ }"
+)
+
+;; -------------------------------------------------------------------------
+;; TLS related insns
+;; -------------------------------------------------------------------------
+
+
+;; UNSPEC_TLS can take either 2 or 3 operands. Operand 0 is the symbol_ref,
+;; operand 1 is a CONST_INT identifying the TLS model, and the optional
+;; operand 3 is an UNSPEC_TLS_LABEL.
+;; The 3-operand case is for TLS_GD32, TLS_LDM32, and TLS_IE32.
+;; The 2-operand case is for TLS_LE32 and TLS_LDO32.
+
+;; Move PC-relative TLS label to reg. This is used for the TLS_GD32
+;; and TLS_GD32 models (when setting up a call to tls_get_addr) and
+;; also TLS_IE32.
+
+(define_insn "*tls_pcrel_label"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "const_int_operand" "")]
+ UNSPEC_TLS_LABEL))]
+ "TARGET_TLS"
+ "grs\t%0, .LTLS%1"
+ [(set_attr "length" "4")]
+)
+
+;; This pattern is used to load the TLS base for the same models as above.
+;; The embedded UNSPEC_TLS_LABEL only identifies the label to emit and
+;; doesn't generate a reference to it; that's handled by the *tls_pcrel_label
+;; pattern above. The label offset needs to be added to the result stored
+;; in operand 0 by this insn.
+
+(define_insn "*tls_get_symbol_1"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand 1 "" "")
+ (match_operand 2 "" "")
+ (unspec:SI [(match_operand 3 "" "")] UNSPEC_TLS_LABEL)]
+ UNSPEC_TLS))]
+ "TARGET_TLS"
+ {
+ default_internal_label (asm_out_file, \"LTLS\", INTVAL (operands[3]));
+ switch (INTVAL (operands[2]))
+ {
+ case TLS_GD32:
+ return \"lrw\t%0, %1@TLSGD32\";
+ case TLS_LDM32:
+ return \"lrw\t%0, %1@TLSLDM32\";
+ case TLS_IE32:
+ return \"lrw\t%0, %1@GOTTPOFF\";
+ default:
+ return \"\";
+ }
+ }
+)
+
+;; This pattern matches the two-operand form of UNSPEC_TLS.
+
+(define_insn "*tls_get_symbol_2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand 1 "" "")
+ (match_operand 2 "" "")]
+ UNSPEC_TLS))]
+ "TARGET_TLS"
+ {
+ switch (INTVAL (operands[2]))
+ {
+ case TLS_LE32:
+ return \"lrw\t%0, %1@TPOFF\";
+ case TLS_LDO32:
+ return \"lrw\t%0, %1@TLSLDO32\";
+ default:
+ return \"\";
+ }
+ }
+)
+
+
+;; -------------------------------------------------------------
+;; Misc insns
+;; -------------------------------------------------------------
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop"
+ [(set_attr "length" "2")]
+)
+
+(define_insn "trap"
+ [(trap_if (const_int 1) (const_int 0))]
+ ""
+ "bkpt"
+ [(set (attr "length") (const_int 2))
+ (set_attr "type" "alu")]
+)
+
+
+;; -------------------------------------------------------------
+;; Special patterns for dealing with the constant pool
+;; -------------------------------------------------------------
+
+(define_insn "align_4"
+ [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
+ ""
+ {
+ assemble_align(32);
+ return \"\";
+ }
+ [(set_attr "length" "0")]
+)
+
+(define_insn "csky_constpool_label"
+ [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_LABEL)]
+ ""
+ {
+ char tmp_label[15];
+ ASM_GENERATE_INTERNAL_LABEL (tmp_label, \"LCP\", INTVAL (operands[0]));
+ assemble_label (asm_out_file, tmp_label);
+ return \"\";
+ }
+ [(set_attr "length" "0")]
+)
+
+(define_insn "consttable_4"
+ [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
+ ""
+ {
+ if (CONST_DOUBLE_P (operands[0]))
+ assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
+ SFmode, BITS_PER_WORD);
+ else
+ {
+ assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
+ mark_symbol_refs_as_used (operands[0]);
+ }
+ return \"\";
+ }
+ [(set_attr "length" "4")]
+)
+
+(define_insn "consttable_8"
+ [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
+ ""
+ {
+ if (CONST_DOUBLE_P (operands[0]))
+ assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
+ DFmode, BITS_PER_WORD);
+ else
+ assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
+ return \"\";
+ }
+ [(set_attr "length" "8")]
+)
+
+;;FIXME record the deferred symbol_ref information with use insn
+(define_insn "*cskyv2_use_symbol_ref"
+ [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_SYMBOL_REF)]
+ ""
+ ""
+ [(set_attr "length" "0")]
+)
+
+
+;; ------------------------------------------------------------
+;; switch case optimize
+;; ------------------------------------------------------------
+
+(define_expand "casesi"
+ [(match_operand:SI 0 "register_operand" "") ; index to jump on
+ (match_operand:SI 1 "const_int_operand" "") ; lower bound
+ (match_operand:SI 2 "const_int_operand" "") ; total range (max - min)
+ (match_operand:SI 3 "" "") ; table label
+ (match_operand:SI 4 "" "")] ; Out of range label (default:)
+ "TARGET_CASESI"
+ "
+ {
+ enum insn_code code;
+ if (operands[1] != const0_rtx)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+ emit_insn (gen_subsi3 (reg,
+ operands[0],
+ GEN_INT (INTVAL (operands[1]))));
+ operands[0] = reg;
+ }
+
+ code = CODE_FOR_csky_casesi_internal;
+
+ if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
+ operands[2] = force_reg (SImode,operands[2]);
+
+ emit_jump_insn (GEN_FCN ((int) code) (operands[0],operands[2],
+ operands[3],operands[4]));
+ DONE;
+ }"
+)
+
+(define_expand "csky_casesi_internal"
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "csky_literal_Uk_operand" "")
+ (match_operand 2 "" "")
+ (match_operand 3 "" "")]
+ ""
+ {
+ rtx reg0;
+ rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
+ emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
+ operands[3]));
+ reg0 = gen_rtx_REG (SImode, 0);
+ emit_move_insn (reg0, operands[0]);
+ emit_jump_insn (gen_csky_casesi_dispatch (operands[2]));
+ DONE;
+ }
+)
+
+(define_insn "csky_casesi_dispatch"
+ [(parallel [(set (pc) (unspec [(reg:SI 0)
+ (label_ref (match_operand 0 "" ""))]
+ UNSPEC_CSKY_CASESI))
+ (clobber (reg:SI CSKY_LR_REGNUM))])]
+ ""
+ "*return csky_output_casesi (operands);"
+ [(set_attr "length" "4")]
+)
+
+;; ------------------------------------------------------------------------
+;; index insns
+;; ------------------------------------------------------------------------
+
+(define_insn "*cskyv2_indexsi_t"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 4))
+ (match_operand:SI 2 "register_operand" "r")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "ixw\t%0, %2, %1"
+)
+
+(define_insn "*cskyv2_indexhi_t"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 2))
+ (match_operand:SI 2 "register_operand" "r")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "ixh\t%0, %2, %1"
+)
+
+(define_insn "*cskyv2_indexdi_t"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 8))
+ (match_operand:SI 2 "register_operand" "r")))]
+ "CSKY_ISA_FEATURE (2E3)"
+ "ixd\t%0, %2, %1"
+)
+
+;; ------------------------------------------------------------------------
+;; swap insns
+;; ------------------------------------------------------------------------
+
+(define_insn "bswapsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (bswap:SI (match_operand:SI 1 "register_operand" "r")))]
+ "CSKY_ISA_FEATURE (E2)"
+ "revb\t%0, %1"
+)
diff --git a/gcc/config/csky/csky.opt b/gcc/config/csky/csky.opt
new file mode 100644
index 0000000..55d2659
--- /dev/null
+++ b/gcc/config/csky/csky.opt
@@ -0,0 +1,173 @@
+;; Command-line options for the C-SKY back end.
+;; Copyright (C) 2018 Free Software Foundation, Inc.
+;; Contributed by C-SKY Microsystems and Mentor Graphics.
+;;
+;; 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/>.
+
+
+HeaderInclude
+config/csky/csky_opts.h
+
+;; Architecture/CPU options.
+;; Normal CPU and arch enums are loaded from csky_tables.opt.
+
+; For backward compatibility only.
+march=ck803s
+Target Report Var(flag_arch_ck803s) Undocumented
+
+march=
+Target RejectNegative ToLower Joined Enum(csky_arch) Var(csky_arch_option) Save
+Specify the target architecture.
+
+mcpu=
+Target RejectNegative ToLower Joined Enum(csky_processor_type) Var(csky_cpu_option) Init(TARGET_CPU_csky_none) Save
+Specify the target processor.
+
+;; Endianness options.
+
+mbig-endian
+Target RejectNegative Report Mask(BIG_ENDIAN)
+Generate big-endian code.
+
+EB
+Target RejectNegative Report Alias(mbig-endian) Undocumented
+
+mlittle-endian
+Target RejectNegative Report InverseMask(BIG_ENDIAN)
+Generate little-endian code.
+
+EL
+Target RejectNegative Report Alias(mlittle-endian) Undocumented
+
+;; Floating point options. These affect code generation but not
+;; assembly.
+
+mhard-float
+Target Report RejectNegative Mask(HARD_FLOAT)
+Enable hardware floating-point instructions.
+
+msoft-float
+Target Report RejectNegative InverseMask(HARD_FLOAT)
+Use library calls to perform floating-point operations (default).
+
+mfpu=
+Target RejectNegative Joined Enum(csky_fpu) Var(csky_fpu_index) Init(TARGET_FPU_auto) Save
+Specify the target floating-point hardware/format.
+
+mdouble-float
+Target Report Var(TARGET_DOUBLE_FLOAT) Init(-1)
+Generate C-SKY FPU double float instructions (default for hard float).
+
+mfdivdu
+Target Report Var(TARGET_FDIVDU) Init(-1)
+Generate frecipd/fsqrtd/fdivd instructions (default for hard float).
+
+;; Instruction set extensions. Most of these don't affect code
+;; generation, and are passed through to the assembler.
+;; There are builtin preprocessor defines for each of these.
+
+melrw
+Target Report Var(TARGET_ELRW) Init(-1)
+Enable the extended LRW instruction (default for CK801).
+
+mistack
+Target Report Mask(ISTACK)
+Enable interrupt stack instructions.
+
+mmp
+Target Report RejectNegative Mask(MP)
+Enable multiprocessor instructions.
+
+mcp
+Target Report RejectNegative Mask(CP)
+Enable coprocessor instructions.
+
+mcache
+Target Report RejectNegative Mask(CACHE)
+Enable cache prefetch instructions.
+
+msecurity
+Target Report RejectNegative Mask(SECURITY)
+Enable C-SKY SECURE instructions.
+
+mmac
+Target Report RejectNegative Alias(msecurity) Undocumented
+
+mtrust
+Target Report RejectNegative Mask(TRUST)
+Enable C-SKY TRUST instructions.
+
+mdsp
+Target Report RejectNegative Var(TARGET_DSP)
+Enable C-SKY DSP instructions.
+
+medsp
+Target Report RejectNegative Mask(EDSP)
+Enable C-SKY Enhanced DSP instructions.
+
+mvdsp
+Target Report RejectNegative Mask(VDSP)
+Enable C-SKY Vector DSP instructions.
+
+;; Code generation options not passed to the assembler.
+
+mdiv
+Target Report Var(TARGET_DIV) Init(-1)
+Generate divide instructions.
+
+msmart
+Target Report Var(TARGET_MINI_REGISTERS) Init(-1)
+Generate code for Smart Mode.
+
+mhigh-registers
+Target Report Var(TARGET_HIGH_REGISTERS) Init(-1)
+Enable use of R16-R31 (default).
+
+manchor
+Target Report Var(TARGET_ANCHOR)
+Generate code using global anchor symbol addresses.
+
+mpushpop
+Target Report Var(TARGET_PUSHPOP) Init(1)
+Generate push/pop instructions (default).
+
+mmultiple-stld
+Target Report Var(TARGET_MULTIPLE_STLD) Init(-1)
+Generate stm/ldm instructions (default).
+
+mstm
+Target Report Alias(mmultiple-stld) Undocumented
+
+mconstpool
+Target Report Var(TARGET_CONSTANT_POOL) Init(-1)
+Generate constant pools in the compiler instead of assembler.
+
+mstack-size
+Target Report Var(TARGET_STACK_SIZE) Init(0)
+Emit .stack_size directives.
+
+mccrt
+Target Report Var(TARGET_LIBCCRT) Init(0)
+Generate code for C-SKY compiler runtime instead of libgcc.
+
+mbranch-cost=
+Target Report Joined RejectNegative UInteger Var(csky_branch_cost) Init(1)
+Set the branch costs to roughly the specified number of instructions.
+
+msched-prolog
+Target Report Var(flag_sched_prolog) Init(0)
+Permit scheduling of function prologue and epilogue sequences.
diff --git a/gcc/config/csky/csky_cores.def b/gcc/config/csky/csky_cores.def
new file mode 100644
index 0000000..5159a07
--- /dev/null
+++ b/gcc/config/csky/csky_cores.def
@@ -0,0 +1,199 @@
+/* Architecture and core descriptions for the C-SKY back end.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ Contributed by C-SKY Microsystems and Mentor Graphics.
+
+ 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/>. */
+
+/* Before using #include to read this file, define a macro:
+
+ CSKY_ARCH(NAME, CORE, ARCH, ISA)
+
+ The NAME is the name of the architecture, represented as a string
+ constant. The CORE is the identifier for a core representative of
+ this architecture. ARCH is the architecture revision. ISA is the
+ detailed architectural capabilities of the core. */
+
+#ifdef CSKY_ARCH
+CSKY_ARCH ("ck801", ck801, CK801,
+ CSKY_ISA_FEAT (CSKY_ISA_CK801))
+CSKY_ARCH ("ck802", ck802, CK802,
+ CSKY_ISA_FEAT (CSKY_ISA_CK802))
+CSKY_ARCH ("ck803", ck803, CK803,
+ CSKY_ISA_FEAT (CSKY_ISA_CK803))
+CSKY_ARCH ("ck807", ck807, CK807,
+ CSKY_ISA_FEAT (CSKY_ISA_CK807) CSKY_ISA_FEAT (CSKY_ISA_DSP))
+CSKY_ARCH ("ck810", ck810, CK810,
+ CSKY_ISA_FEAT (CSKY_ISA_CK810) CSKY_ISA_FEAT (CSKY_ISA_DSP))
+#endif
+
+
+/* Before using #include to read this file, define a macro:
+
+ CSKY_CORE(CORE_NAME, INTERNAL_IDENT, TUNE_IDENT, ARCH, ISA)
+
+ The isa features of core will inherit the ARCH.
+
+ The CORE_NAME is the name of the core, represented as a string constant.
+ The INTERNAL_IDENT is the name of the core represented as an identifier.
+ This must be unique for each entry in this table.
+ The TUNE_IDENT is the name of the core for which scheduling decisions
+ should be made, represented as an identifier.
+ The ARCH is the architecture revision implemented by the chip.
+ The ISA is the detailed architectural capabilities of the core. */
+
+#ifdef CSKY_CORE
+/* ck801 Architecture Processors */
+CSKY_CORE ("ck801", ck801, ck801, CK801,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck801t", ck801t, ck801t, CK801,
+ CSKY_ISA_FEAT_NONE)
+
+/* ck802 Architecture Processors */
+CSKY_CORE ("ck802", ck802, ck802, CK802,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck802t", ck802t, ck802t, CK802,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck802j", ck802j, ck802j, CK802,
+ CSKY_ISA_FEAT (isa_bit_java))
+
+/* ck803 Architecture Processors */
+CSKY_CORE ("ck803", ck803, ck803, CK803,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck803h", ck803h, ck803h, CK803,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck803t", ck803t, ck803t, CK803,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck803ht", ck803ht, ck803ht, CK803,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck803f", ck803f, ck803f, CK803,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck803fh", ck803fh, ck803fh, CK803,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck803e", ck803e, ck803e, CK803,
+ CSKY_ISA_FEAT (CSKY_ISA_DSP))
+CSKY_CORE ("ck803eh", ck803eh, ck803eh, CK803,
+ CSKY_ISA_FEAT (CSKY_ISA_DSP))
+CSKY_CORE ("ck803et", ck803et, ck803et, CK803,
+ CSKY_ISA_FEAT (CSKY_ISA_DSP))
+CSKY_CORE ("ck803eht", ck803eht, ck803eht, CK803,
+ CSKY_ISA_FEAT (CSKY_ISA_DSP))
+CSKY_CORE ("ck803ef", ck803ef, ck803ef, CK803,
+ CSKY_ISA_FEAT (CSKY_ISA_DSP))
+CSKY_CORE ("ck803efh", ck803efh, ck803efh, CK803,
+ CSKY_ISA_FEAT (CSKY_ISA_DSP))
+CSKY_CORE ("ck803ft", ck803ft, ck803ft, CK803,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck803eft", ck803eft, ck803eft, CK803,
+ CSKY_ISA_FEAT (CSKY_ISA_DSP))
+CSKY_CORE ("ck803efht", ck803efht, ck803efht, CK803,
+ CSKY_ISA_FEAT (CSKY_ISA_DSP))
+CSKY_CORE ("ck803r1", ck803r1, ck803r1, CK803,
+ CSKY_ISA_FEAT (isa_bit_3E3r1))
+CSKY_CORE ("ck803hr1", ck803hr1, ck803hr1, CK803,
+ CSKY_ISA_FEAT (isa_bit_3E3r1))
+CSKY_CORE ("ck803tr1", ck803tr1, ck803tr1, CK803,
+ CSKY_ISA_FEAT (isa_bit_3E3r1))
+CSKY_CORE ("ck803htr1", ck803htr1, ck803htr1, CK803,
+ CSKY_ISA_FEAT (isa_bit_3E3r1))
+CSKY_CORE ("ck803fr1", ck803fr1, ck803fr1, CK803,
+ CSKY_ISA_FEAT (isa_bit_3E3r1))
+CSKY_CORE ("ck803fhr1", ck803fhr1, ck803fhr1, CK803,
+ CSKY_ISA_FEAT (isa_bit_3E3r1))
+CSKY_CORE ("ck803er1", ck803er1, ck803er1, CK803,
+ CSKY_ISA_FEAT (isa_bit_3E3r1))
+CSKY_CORE ("ck803ehr1", ck803ehr1, ck803ehr1, CK803,
+ CSKY_ISA_FEAT (isa_bit_3E3r1))
+CSKY_CORE ("ck803etr1", ck803etr1, ck803etr1, CK803,
+ CSKY_ISA_FEAT (isa_bit_3E3r1))
+CSKY_CORE ("ck803ehtr1", ck803ehtr1, ck803ehtr1, CK803,
+ CSKY_ISA_FEAT (isa_bit_3E3r1))
+CSKY_CORE ("ck803efr1", ck803efr1, ck803efr1, CK803,
+ CSKY_ISA_FEAT (isa_bit_3E3r1))
+CSKY_CORE ("ck803efhr1", ck803efhr1, ck803efhr1, CK803,
+ CSKY_ISA_FEAT (isa_bit_3E3r1))
+CSKY_CORE ("ck803ftr1", ck803ftr1, ck803ftr1, CK803,
+ CSKY_ISA_FEAT (isa_bit_3E3r1))
+CSKY_CORE ("ck803eftr1", ck803eftr1, ck803eftr1, CK803,
+ CSKY_ISA_FEAT (isa_bit_3E3r1))
+CSKY_CORE ("ck803efhtr1", ck803efhtr1, ck803efhtr1, CK803,
+ CSKY_ISA_FEAT (isa_bit_3E3r1))
+
+/* ck803s Architecture Processors */
+CSKY_CORE ("ck803s", ck803s, ck803s, CK803,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck803st", ck803st, ck803st, CK803,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck803se", ck803se, ck803se, CK803,
+ CSKY_ISA_FEAT (CSKY_ISA_DSP))
+CSKY_CORE ("ck803sf", ck803sf, ck803sf, CK803,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck803sef", ck803sef, ck803sef, CK803,
+ CSKY_ISA_FEAT (CSKY_ISA_DSP))
+CSKY_CORE ("ck803seft", ck803seft, ck803seft, CK803,
+ CSKY_ISA_FEAT (CSKY_ISA_DSP))
+
+/* ck807 Architecture Processors */
+CSKY_CORE ("ck807e", ck807e, ck807e, CK807,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck807ef", ck807ef, ck807ef, CK807,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck807", ck807, ck807, CK807,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck807f", ck807f, ck807f, CK807,
+ CSKY_ISA_FEAT_NONE)
+
+/* ck810 Architecture Processors */
+CSKY_CORE ("ck810e", ck810e, ck810e, CK810,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck810et", ck810et, ck810et, CK810,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck810ef", ck810ef, ck810ef, CK810,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck810eft", ck810eft, ck810eft, CK810,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck810", ck810, ck810, CK810,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck810v", ck810v, ck810v, CK810,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck810f", ck810f, ck810f, CK810,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck810t", ck810t, ck810t, CK810,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck810fv", ck810fv, ck810fv, CK810,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck810tv", ck810tv, ck810tv, CK810,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck810ft", ck810ff, ck810ft, CK810,
+ CSKY_ISA_FEAT_NONE)
+CSKY_CORE ("ck810ftv", ck810ftv, ck810ftv, CK810,
+ CSKY_ISA_FEAT_NONE)
+#endif
+
+
+/* Before using #include to read this file, define a macro:
+
+ CSKY_FPU(NAME, CNAME, ISA)
+
+ NAME is the publicly visible option name.
+ CNAME is a C-compatible variable name substring.
+ ISA is the list of feature bits that this FPU provides. */
+
+#ifdef CSKY_FPU
+CSKY_FPU ("fpv2_sf", fpv2_sf, CSKY_ISA_FEAT (CSKY_ISA_FPv2_SF))
+CSKY_FPU ("fpv2", fpv2, CSKY_ISA_FEAT (CSKY_ISA_FPv2))
+CSKY_FPU ("fpv2_divd", fpv2_divd, CSKY_ISA_FEAT (CSKY_ISA_FPv2_DIVD))
+#endif
diff --git a/gcc/config/csky/csky_genopt.sh b/gcc/config/csky/csky_genopt.sh
new file mode 100644
index 0000000..bf145a4
--- /dev/null
+++ b/gcc/config/csky/csky_genopt.sh
@@ -0,0 +1,97 @@
+#!/bin/sh
+# Generate csky_tables.opt from the lists in *.def.
+# Copyright (C) 2018 Free Software Foundation, Inc.
+# Contributed by C-SKY Microsystems and Mentor Graphics.
+#
+# 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/>.
+
+cat <<EOF
+; -*- buffer-read-only: t -*-
+; Generated automatically by csky_genopt.sh from csky_cores.def.
+
+; Copyright (C) 2018 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/>.
+
+Enum
+Name(csky_processor_type) Type(enum csky_processor_type)
+Known CSKY CPUs (for use with the -mcpu= options):
+
+EOF
+
+awk -F'[(, ]+' '/^CSKY_CORE/ {
+ name = $2
+ enum = $3
+ gsub("\"", "", name)
+ print "EnumValue"
+ print "Enum(csky_processor_type) String(" name ") Value( TARGET_CPU_" enum ")"
+ print ""
+}' $1/csky_cores.def
+
+cat <<EOF
+Enum
+Name(csky_arch) Type(int)
+Known CSKY architectures (for use with the -march= option):
+
+EOF
+
+awk -F'[(, ]+' 'BEGIN {
+ value = 0
+}
+/^CSKY_ARCH/ {
+ name = $2
+ gsub("\"", "", name)
+ print "EnumValue"
+ print "Enum(csky_arch) String(" name ") Value(" value ")"
+ print ""
+ value++
+}' $1/csky_cores.def
+
+cat <<EOF
+Enum
+Name(csky_fpu) Type(enum csky_fpu_type)
+Known CSKY FPUs (for use with the -mfpu= option):
+
+EOF
+
+awk -F'[(, ]+' '
+/^CSKY_FPU/ {
+ name = $2
+ enum = $3
+ gsub("\"", "", name)
+ print "EnumValue"
+ print "Enum(csky_fpu) String(" name ") Value(TARGET_FPU_" enum ")"
+ print ""
+}
+END {
+ print "EnumValue"
+ print "Enum(csky_fpu) String(auto) Value(TARGET_FPU_auto)"
+}' $1/csky_cores.def
diff --git a/gcc/config/csky/csky_insn_dsp.md b/gcc/config/csky/csky_insn_dsp.md
new file mode 100644
index 0000000..8b972d1
--- /dev/null
+++ b/gcc/config/csky/csky_insn_dsp.md
@@ -0,0 +1,95 @@
+;; C-SKY DSP instruction descriptions.
+;; Copyright (C) 2018 Free Software Foundation, Inc.
+;; Contributed by C-SKY Microsystems and Mentor Graphics.
+;;
+;; 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/>. */
+
+;; ------------------------------------------------------------
+;; DSP insns
+;; ------------------------------------------------------------
+
+(define_insn "mulsidi3"
+ [(set (match_operand:DI 0 "register_operand" "=y")
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
+ (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
+ "TARGET_DSP"
+ "muls\t%1, %2"
+)
+
+(define_insn "umulsidi3"
+ [(set (match_operand:DI 0 "register_operand" "=y")
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
+ (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
+ "TARGET_DSP"
+ "mulu\t%1, %2"
+)
+
+(define_insn "maddsidi4"
+ [(set (match_operand:DI 0 "register_operand" "=y")
+ (plus:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
+ (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
+ (match_operand:DI 3 "register_operand" "0")))]
+ "TARGET_DSP"
+ "mulsa\t%1, %2"
+)
+
+(define_insn "umaddsidi4"
+ [(set (match_operand:DI 0 "register_operand" "=y")
+ (plus:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
+ (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
+ (match_operand:DI 3 "register_operand" "0")))]
+ "TARGET_DSP"
+ "mulua\t%1, %2"
+)
+
+(define_insn "msubsidi4"
+ [(set (match_operand:DI 0 "register_operand" "=y")
+ (minus:DI (match_operand:DI 3 "register_operand" "0")
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
+ (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))))]
+ "TARGET_DSP"
+ "mulss\t%1, %2"
+)
+
+(define_insn "umsubsidi4"
+ [(set (match_operand:DI 0 "register_operand" "=y")
+ (minus:DI (match_operand:DI 3 "register_operand" "0")
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
+ (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))))]
+ "TARGET_DSP"
+ "mulus\t%1, %2"
+)
+
+(define_insn "*mulall_s16_0"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 3 "register_operand" " 0")
+ (mult:SI (match_operand:SI 1 "register_operand" " r")
+ (match_operand:SI 2 "register_operand" " r"))))]
+ "CSKY_ISA_FEATURE (3E3r1)"
+ "mula.32.l\t%0, %1, %2"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+(define_insn "*mulall_s16_1"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" " r")
+ (match_operand:SI 2 "register_operand" " r"))
+ (match_operand:SI 3 "register_operand" " 0")))]
+ "CSKY_ISA_FEATURE (3E3r1)"
+ "mula.32.l\t%0, %1, %2"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
diff --git a/gcc/config/csky/csky_insn_fpu.md b/gcc/config/csky/csky_insn_fpu.md
new file mode 100644
index 0000000..d188ef2
--- /dev/null
+++ b/gcc/config/csky/csky_insn_fpu.md
@@ -0,0 +1,567 @@
+;; C-SKY FPU instruction descriptions.
+;; Copyright (C) 2018 Free Software Foundation, Inc.
+;; Contributed by C-SKY Microsystems and Mentor Graphics.
+;;
+;; 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/>. */
+
+;; -------------------------------------------------------------------------
+;; Float Abs instructions
+;; -------------------------------------------------------------------------
+
+(define_insn "abssf2"
+ [(set (match_operand:SF 0 "register_operand" "=v,r")
+ (abs:SF (match_operand:SF 1 "register_operand" "v, r")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "@
+ fabss\t%0, %1
+ bclri\t%0, %1, 31")
+
+(define_insn "absdf2"
+ [(set (match_operand:DF 0 "register_operand" "=v")
+ (abs:DF (match_operand:DF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fabsd\t%0, %1")
+
+
+;; -------------------------------------------------------------------------
+;; Float Neg instructions
+;; -------------------------------------------------------------------------
+
+(define_insn "negsf2"
+ [(set (match_operand:SF 0 "register_operand" "=v")
+ (neg:SF (match_operand:SF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fnegs\t%0, %1")
+
+(define_insn "negdf2"
+ [(set (match_operand:DF 0 "register_operand" "=v")
+ (neg:DF (match_operand:DF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fnegd\t%0, %1")
+
+
+;; -------------------------------------------------------------------------
+;; Float Sqrt instructions
+;; -------------------------------------------------------------------------
+
+(define_insn "sqrtsf2"
+ [(set (match_operand:SF 0 "register_operand" "=v")
+ (sqrt:SF (match_operand:SF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fsqrts\t%0, %1")
+
+(define_insn "sqrtdf2"
+ [(set (match_operand:DF 0 "register_operand" "=v")
+ (sqrt:DF (match_operand:DF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_divd)"
+ "fsqrtd\t%0, %1")
+
+
+;; -------------------------------------------------------------------------
+;; Float Add instructions
+;; -------------------------------------------------------------------------
+
+(define_insn "addsf3"
+ [(set (match_operand:SF 0 "register_operand" "=v")
+ (plus:SF (match_operand:SF 1 "register_operand" "v")
+ (match_operand:SF 2 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fadds\t%0, %1, %2")
+
+(define_insn "adddf3"
+ [(set (match_operand:DF 0 "register_operand" "=v")
+ (plus:DF (match_operand:DF 1 "register_operand" "v")
+ (match_operand:DF 2 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "faddd\t%0, %1, %2")
+
+
+;; -------------------------------------------------------------------------
+;; Float Sub instructions
+;; -------------------------------------------------------------------------
+
+(define_insn "subsf3"
+ [(set (match_operand:SF 0 "register_operand" "=v")
+ (minus:SF (match_operand:SF 1 "register_operand" "v")
+ (match_operand:SF 2 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fsubs\t%0, %1, %2")
+
+(define_insn "subdf3"
+ [(set (match_operand:DF 0 "register_operand" "=v")
+ (minus:DF (match_operand:DF 1 "register_operand" "v")
+ (match_operand:DF 2 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fsubd\t%0, %1, %2")
+
+
+;; -------------------------------------------------------------------------
+;; Float Mul instructions
+;; -------------------------------------------------------------------------
+
+(define_insn "mulsf3"
+ [(set (match_operand:SF 0 "register_operand" "=v")
+ (mult:SF (match_operand:SF 1 "register_operand" "v")
+ (match_operand:SF 2 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fmuls\t%0, %1, %2")
+
+(define_insn "muldf3"
+ [(set (match_operand:DF 0 "register_operand" "=v")
+ (mult:DF (match_operand:DF 1 "register_operand" "v")
+ (match_operand:DF 2 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fmuld\t%0, %1, %2")
+
+(define_insn "*fpuv2_nmulsf3_1"
+ [(set (match_operand:SF 0 "register_operand" "=v")
+ (mult:SF (neg:SF (match_operand:SF 1 "register_operand" "%v"))
+ (match_operand:SF 2 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fnmuls\t%0, %1, %2")
+
+(define_insn "*fpuv2_nmulsf3_2"
+ [(set (match_operand:SF 0 "register_operand" "=v")
+ (neg:SF (mult:SF (match_operand:SF 1 "register_operand" "v")
+ (match_operand:SF 2 "register_operand" "v"))))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fnmuls\t%0, %1, %2")
+
+(define_insn "*fpuv2_nmuldf3_1"
+ [(set (match_operand:DF 0 "register_operand" "=v")
+ (mult:DF (neg:DF (match_operand:DF 1 "register_operand" "%v"))
+ (match_operand:DF 2 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fnmuld\t%0, %1, %2")
+
+(define_insn "*fpuv2_nmuldf3_2"
+ [(set (match_operand:DF 0 "register_operand" "=v")
+ (neg:DF (mult:DF (match_operand:DF 1 "register_operand" "v")
+ (match_operand:DF 2 "register_operand" "v"))))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fnmuld\t%0, %1, %2")
+
+
+;; -------------------------------------------------------------------------
+;; Float Div instructions
+;; -------------------------------------------------------------------------
+
+(define_expand "divsf3"
+ [(set (match_operand:SF 0 "register_operand" "")
+ (div:SF (match_operand:SF 1 "csky_arith_float1_operand" "")
+ (match_operand:SF 2 "register_operand" "")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "")
+
+(define_insn "*fpuv2_divsf3"
+ [(set (match_operand:SF 0 "register_operand" "=v")
+ (div:SF (match_operand:SF 1 "register_operand" "v")
+ (match_operand:SF 2 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fdivs\t%0, %1, %2")
+
+(define_insn "*fpuv2_1_divsf3"
+ [(set (match_operand:SF 0 "register_operand" "=v")
+ (div:SF (match_operand:SF 1 "csky_const_float1_operand" "i")
+ (match_operand:SF 2 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "frecips\t%0, %2")
+
+
+(define_expand "divdf3"
+ [(set (match_operand:DF 0 "register_operand" "")
+ (div:DF (match_operand:DF 1 "csky_arith_float1_operand" "")
+ (match_operand:DF 2 "register_operand" "")))]
+ "CSKY_ISA_FEATURE (fpv2_divd)"
+ "")
+
+(define_insn "*fpuv2_divdf3"
+ [(set (match_operand:DF 0 "register_operand" "=v")
+ (div:DF (match_operand:DF 1 "register_operand" "v")
+ (match_operand:DF 2 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_divd)"
+ "fdivd\t%0, %1, %2")
+
+(define_insn "*fpuv2_1_divdf3"
+ [(set (match_operand:DF 0 "register_operand" "=v")
+ (div:DF (match_operand:DF 1 "csky_const_float1_operand" "i")
+ (match_operand:DF 2 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_divd)"
+ "frecipd\t%0, %2")
+
+
+;; -------------------------------------------------------------------------
+;; Float add(sub) with mult instructions
+;; -------------------------------------------------------------------------
+
+;; vrz <= vrz + vrx * vry
+(define_insn "*fpuv2_fmacs"
+ [(set (match_operand:SF 0 "register_operand" "=v")
+ (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "v")
+ (match_operand:SF 2 "register_operand" "v"))
+ (match_operand:SF 3 "register_operand" "0")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fmacs\t%0, %1, %2")
+
+(define_insn "*fpuv2_fmacd"
+ [(set (match_operand:DF 0 "register_operand" "=v")
+ (plus:DF (mult:DF (match_operand:DF 1 "register_operand" "v")
+ (match_operand:DF 2 "register_operand" "v"))
+ (match_operand:DF 3 "register_operand" "0")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fmacd\t%0, %1, %2")
+
+;; vrz <= vrz - vrx * vry
+(define_insn "*fpuv2_fnmacs"
+ [(set (match_operand:SF 0 "register_operand" "=v")
+ (minus:SF (match_operand:SF 1 "register_operand" "0")
+ (mult:SF (match_operand:SF 2 "register_operand" "v")
+ (match_operand:SF 3 "register_operand" "v"))))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fnmacs\t%0, %2, %3")
+
+(define_insn "*fpuv2_fnmacd"
+ [(set (match_operand:DF 0 "register_operand" "=v")
+ (minus:DF (match_operand:DF 1 "register_operand" "0")
+ (mult:DF (match_operand:DF 2 "register_operand" "v")
+ (match_operand:DF 3 "register_operand" "v"))))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fnmacd\t%0, %2, %3")
+
+;; vrz <= vrx * vry - vrz
+(define_insn "*fpuv2_fmscs"
+ [(set (match_operand:SF 0 "register_operand" "=v")
+ (minus:SF (mult:SF (match_operand:SF 1 "register_operand" "v")
+ (match_operand:SF 2 "register_operand" "v"))
+ (match_operand:SF 3 "register_operand" "0")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fmscs\t%0, %1, %2")
+
+(define_insn "*fpuv2_fmscd"
+ [(set (match_operand:DF 0 "register_operand" "=v")
+ (minus:DF (mult:DF (match_operand:DF 1 "register_operand" "v")
+ (match_operand:DF 2 "register_operand" "v"))
+ (match_operand:DF 3 "register_operand" "0")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fmscd\t%0, %1, %2")
+
+;; vrz = - (vrz + vrx * vry)
+(define_insn "*fpuv2_fnmscs_1"
+ [(set (match_operand:SF 0 "register_operand" "=v")
+ (minus:SF (mult:SF (neg:SF (match_operand:SF 1 "register_operand" "%v"))
+ (match_operand:SF 2 "register_operand" "v"))
+ (match_operand:SF 3 "register_operand" "0")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fnmscs\t%0, %1, %2")
+
+(define_insn "*fpuv2_fnmscs_2"
+ [(set (match_operand:SF 0 "register_operand" "=v")
+ (neg:SF (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "v")
+ (match_operand:SF 2 "register_operand" "v"))
+ (match_operand:SF 3 "register_operand" "0"))))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fnmscs\t%0, %1, %2")
+
+(define_insn "*fpuv2_fnmscd_1"
+ [(set (match_operand:DF 0 "register_operand" "=v")
+ (minus:DF (mult:DF (neg:DF (match_operand:DF 1 "register_operand" "%v"))
+ (match_operand:DF 2 "register_operand" "v"))
+ (match_operand:DF 3 "register_operand" "0")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fnmscd\t%0, %1, %2")
+
+(define_insn "*fpuv2_fnmscd_2"
+ [(set (match_operand:DF 0 "register_operand" "=v")
+ (neg:DF (plus:DF (mult:DF (match_operand:DF 1 "register_operand" "v")
+ (match_operand:DF 2 "register_operand" "v"))
+ (match_operand:DF 3 "register_operand" "0"))))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fnmscd\t%0, %1, %2")
+
+
+;; -------------------------------------------------------------------------
+;; Float compare instructions
+;; -------------------------------------------------------------------------
+
+(define_expand "cbranchsf4"
+ [(set (pc) (if_then_else (match_operator 0 "csky_float_comparison_operator"
+ [(match_operand:SF 1 "register_operand")
+ (match_operand:SF 2 "csky_compare_operand_float")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "
+ {
+ enum rtx_code code = GET_CODE (operands[0]);
+ bool invert = csky_emit_compare_float (code, operands[1], operands[2]);
+
+ if (invert)
+ emit_jump_insn (gen_csky_jbf (operands[3]));
+ else
+ emit_jump_insn (gen_csky_jbt (operands[3]));
+
+ DONE;
+ }")
+
+(define_insn "*fpuv2_unordered"
+ [(set (reg:CC 33) (unordered:CC (match_operand:SF 0 "register_operand" "v")
+ (match_operand:SF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fcmpuos\t%0, %1")
+
+(define_insn "*fpuv2_unordered_zero"
+ [(set (reg:CC 33) (unordered:CC (match_operand:SF 0 "register_operand" "v")
+ (match_operand:SF 1 "csky_const_float0_operand" "i")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fcmpuos\t%0, %0")
+
+(define_insn "*fpuv2_ne"
+ [(set (reg:CC 33) (ne:CC (match_operand:SF 0 "register_operand" "v")
+ (match_operand:SF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fcmpnes\t%0, %1")
+
+(define_insn "*fpuv2_gt"
+ [(set (reg:CC 33) (gt:CC (match_operand:SF 0 "register_operand" "v")
+ (match_operand:SF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fcmplts\t%1, %0")
+
+(define_insn "*fpuv2_ge"
+ [(set (reg:CC 33) (ge:CC (match_operand:SF 0 "register_operand" "v")
+ (match_operand:SF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fcmphss\t%0, %1")
+
+(define_insn "*fpuv2_lt"
+ [(set (reg:CC 33) (lt:CC (match_operand:SF 0 "register_operand" "v")
+ (match_operand:SF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fcmplts\t%0, %1")
+
+(define_insn "*fpuv2_le"
+ [(set (reg:CC 33) (le:CC (match_operand:SF 0 "register_operand" "v")
+ (match_operand:SF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fcmphss\t%1, %0")
+
+(define_insn "*fpuv2_gez"
+ [(set (reg:CC 33) (ge:CC (match_operand:SF 0 "register_operand" "v")
+ (match_operand:SF 1 "csky_const_float0_operand" "i")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fcmpzhss\t%0")
+
+(define_insn "*fpuv2_nez"
+ [(set (reg:CC 33) (ne:CC (match_operand:SF 0 "register_operand" "v")
+ (match_operand:SF 1 "csky_const_float0_operand" "i")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fcmpznes\t%0")
+
+
+(define_expand "cbranchdf4"
+ [(set (pc) (if_then_else (match_operator 0 "csky_float_comparison_operator"
+ [(match_operand:DF 1 "register_operand")
+ (match_operand:DF 2 "csky_compare_operand_float")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "
+ {
+ enum rtx_code code = GET_CODE (operands[0]);
+ bool invert = csky_emit_compare_float (code, operands[1], operands[2]);
+
+ if (invert)
+ emit_jump_insn (gen_csky_jbf (operands[3]));
+ else
+ emit_jump_insn (gen_csky_jbt (operands[3]));
+
+ DONE;
+}")
+
+(define_insn "*fpuv2_dunordered"
+ [(set (reg:CC 33) (unordered:CC (match_operand:DF 0 "register_operand" "v")
+ (match_operand:DF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fcmpuod\t%0, %1")
+
+(define_insn "*fpuv2_dunordered_zero"
+ [(set (reg:CC 33) (unordered:CC (match_operand:DF 0 "register_operand" "v")
+ (match_operand:DF 1 "csky_const_float0_operand" "i")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fcmpuod\t%0, %0")
+
+(define_insn "*fpuv2_dne"
+ [(set (reg:CC 33) (ne:CC (match_operand:DF 0 "register_operand" "v")
+ (match_operand:DF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fcmpned\t%0, %1")
+
+(define_insn "*fpuv2_dgt"
+ [(set (reg:CC 33) (gt:CC (match_operand:DF 0 "register_operand" "v")
+ (match_operand:DF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fcmpltd\t%1, %0")
+
+(define_insn "*fpuv2_dge"
+ [(set (reg:CC 33) (ge:CC (match_operand:DF 0 "register_operand" "v")
+ (match_operand:DF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fcmphsd\t%0, %1")
+
+(define_insn "*fpuv2_dlt"
+ [(set (reg:CC 33) (lt:CC (match_operand:DF 0 "register_operand" "v")
+ (match_operand:DF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fcmpltd\t%0, %1")
+
+(define_insn "*fpuv2_dle"
+ [(set (reg:CC 33) (le:CC (match_operand:DF 0 "register_operand" "v")
+ (match_operand:DF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fcmphsd\t%1, %0")
+
+(define_insn "*fpuv2_dgez"
+ [(set (reg:CC 33) (ge:CC (match_operand:DF 0 "register_operand" "v")
+ (match_operand:DF 1 "csky_const_float0_operand" "i")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fcmpzhsd\t%0")
+
+(define_insn "*fpuv2_dnez"
+ [(set (reg:CC 33) (ne:CC (match_operand:DF 0 "register_operand" "v")
+ (match_operand:DF 1 "csky_const_float0_operand" "i")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fcmpzned\t%0")
+
+
+;; -------------------------------------------------------------------------
+;; Float convert instructions
+;; -------------------------------------------------------------------------
+
+;; DF <- SF
+(define_insn "extendsfdf2"
+ [(set (match_operand:DF 0 "register_operand" "=v")
+ (float_extend:DF (match_operand:SF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fstod\t%0, %1")
+
+;; SF <- DF
+(define_insn "truncdfsf2"
+ [(set (match_operand:SF 0 "register_operand" "=v")
+ (float_truncate:SF (match_operand:DF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fdtos\t%0, %1")
+
+;; SF <- SI
+(define_insn "floatsisf2"
+ [(set (match_operand:SF 0 "register_operand" "=v")
+ (float:SF (match_operand:SI 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fsitos\t%0, %1")
+
+;; DF <- SI
+(define_insn "floatsidf2"
+ [(set (match_operand:DF 0 "register_operand" "=v")
+ (float:DF (match_operand:SI 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fsitod\t%0, %1")
+
+;; SF <- unsigned SI
+(define_insn "floatunssisf2"
+ [(set (match_operand:SF 0 "register_operand" "=v")
+ (unsigned_float:SF (match_operand:SI 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fuitos\t%0, %1")
+
+;; DF <- unsigned SI
+(define_insn "floatunssidf2"
+ [(set (match_operand:DF 0 "register_operand" "=v")
+ (unsigned_float:DF (match_operand:SI 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fuitod\t%0, %1")
+
+;; SI <- SF
+(define_insn "fix_truncsfsi2"
+ [(set (match_operand:SI 0 "register_operand" "=v")
+ (fix:SI (match_operand:SF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fstosi.rz\t%0, %1")
+
+;; SI <- DF
+(define_insn "fix_truncdfsi2"
+ [(set (match_operand:SI 0 "register_operand" "=v")
+ (fix:SI (match_operand:DF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fdtosi.rz\t%0, %1")
+
+;; unsigned SI <- SF
+(define_insn "fixuns_truncsfsi2"
+ [(set (match_operand:SI 0 "register_operand" "=v")
+ (unsigned_fix:SI (match_operand:SF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "fstoui.rz\t%0, %1")
+
+;; unsigned SI <- DF
+(define_insn "fixuns_truncdfsi2"
+ [(set (match_operand:SI 0 "register_operand" "=v")
+ (unsigned_fix:SI (match_operand:DF 1 "register_operand" "v")))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "fdtoui.rz\t%0, %1")
+
+
+;; -------------------------------------------------------------------------
+;; Float mov instructions
+;; -------------------------------------------------------------------------
+
+;; Note: movsf and movdf patterns are in csky.md.
+
+;; cstore SF
+(define_expand "cstoresf4"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operator 1 "ordered_comparison_operator"
+ [(match_operand:SF 2 "register_operand" "")
+ (match_operand:SF 3 "csky_compare_operand_float" "")]))]
+ "CSKY_ISA_FEATURE (fpv2_sf)"
+ "
+ {
+ bool invert = csky_emit_compare_float (GET_CODE (operands[1]),
+ operands[2], operands[3]);
+ if (invert)
+ emit_insn (gen_mvcv (operands[0]));
+ else
+ emit_insn (gen_mvc (operands[0]));
+ DONE;
+ }"
+)
+
+;; cstore DF
+(define_expand "cstoredf4"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operator 1 "ordered_comparison_operator"
+ [(match_operand:DF 2 "register_operand" "")
+ (match_operand:DF 3 "csky_compare_operand_float" "")]))]
+ "CSKY_ISA_FEATURE (fpv2_df)"
+ "
+ {
+ bool invert = csky_emit_compare_float (GET_CODE (operands[1]),
+ operands[2], operands[3]);
+ if (invert)
+ emit_insn (gen_mvcv (operands[0]));
+ else
+ emit_insn (gen_mvc (operands[0]));
+ DONE;
+ }"
+)
diff --git a/gcc/config/csky/csky_isa.def b/gcc/config/csky/csky_isa.def
new file mode 100644
index 0000000..d99940e
--- /dev/null
+++ b/gcc/config/csky/csky_isa.def
@@ -0,0 +1,59 @@
+/* ISA feature descriptions for the C-SKY back end.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ Contributed by C-SKY Microsystems and Mentor Graphics.
+
+ 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/>. */
+
+/* Before using #include to read this file, define a macro:
+ CSKY_ISA(CNAME, DESCRIPTION)
+ */
+
+/* Common insns */
+CSKY_ISA (E1, "Extended insns for arch ck801 from base")
+CSKY_ISA (E2, "Extended insns for arch ck802 from base")
+CSKY_ISA (2E3, "Extended insns for arch ck803 from ck802")
+CSKY_ISA (3E3r1, "Extended insns for cpu ck803n from ck803")
+CSKY_ISA (3E7, "Extended insns for arch ck807 from ck803")
+CSKY_ISA (7E10, "Extended insns for arch ck810 from ck807")
+
+/* Special insns */
+CSKY_ISA (div, "divide insns")
+
+/* Extended insns */
+CSKY_ISA (dsp, "Extended insns for DSP")
+CSKY_ISA (java, "Extended insns for Java")
+
+CSKY_ISA (fpv2_sf, "Single precision operations supported")
+CSKY_ISA (fpv2_df, "Double precision operations supported")
+CSKY_ISA (fpv2_divd, "Double precision div operations supported")
+
+/* Specific insns mode */
+#ifdef CSKY_ISA_MACRO
+#define CSKY_ISA_CK801 CSKY_ISA_FEATURE_GET (E1)
+#define CSKY_ISA_CK802 CSKY_ISA_FEATURE_GET (E2)
+#define CSKY_ISA_CK803 CSKY_ISA_CK802, CSKY_ISA_FEATURE_GET (2E3), \
+ CSKY_ISA_FEATURE_GET (div)
+#define CSKY_ISA_CK803R1 CSKY_ISA_CK803, CSKY_ISA_FEATURE_GET (3E3r1)
+#define CSKY_ISA_CK807 CSKY_ISA_CK803, CSKY_ISA_FEATURE_GET (3E7)
+#define CSKY_ISA_CK810 CSKY_ISA_CK807, CSKY_ISA_FEATURE_GET (7E10)
+
+#define CSKY_ISA_DSP CSKY_ISA_FEATURE_GET (dsp)
+
+#define CSKY_ISA_FPv2_SF CSKY_ISA_FEATURE_GET (fpv2_sf)
+#define CSKY_ISA_FPv2 CSKY_ISA_FPv2_SF, CSKY_ISA_FEATURE_GET (fpv2_df)
+#define CSKY_ISA_FPv2_DIVD CSKY_ISA_FPv2, CSKY_ISA_FEATURE_GET (fpv2_divd)
+#endif
diff --git a/gcc/config/csky/csky_isa.h b/gcc/config/csky/csky_isa.h
new file mode 100644
index 0000000..24578d7
--- /dev/null
+++ b/gcc/config/csky/csky_isa.h
@@ -0,0 +1,47 @@
+/* ISA feature enumerations for C-SKY targets.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ Contributed by C-SKY Microsystems and Mentor Graphics.
+
+ 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_CSKY_ISA_FEATURE_H
+#define GCC_CSKY_ISA_FEATURE_H
+
+
+#ifndef CSKY_ISA_MACRO
+#define CSKY_ISA_MACRO
+#endif
+
+#define CSKY_ISA_FEATURE_DEFINE(x) isa_bit_ ## x
+#define CSKY_ISA_FEATURE_GET(x) CSKY_ISA_FEATURE_DEFINE (x)
+
+enum csky_isa_feature
+ {
+ CSKY_ISA_FEATURE_DEFINE (none),
+#undef CSKY_ISA
+#define CSKY_ISA(IDENT, DESC) \
+ CSKY_ISA_FEATURE_DEFINE (IDENT),
+#include "csky_isa.def"
+#undef CSKY_ISA
+ CSKY_ISA_FEATURE_DEFINE (max)
+ };
+
+#define CSKY_ISA_FEAT(x) x,
+#define CSKY_ISA_FEAT_NONE CSKY_ISA_FEAT (isa_bit_none)
+
+
+#endif /* GCC_CSKY_ISA_FEATURE_H */
diff --git a/gcc/config/csky/csky_opts.h b/gcc/config/csky/csky_opts.h
new file mode 100644
index 0000000..f206537
--- /dev/null
+++ b/gcc/config/csky/csky_opts.h
@@ -0,0 +1,63 @@
+/* Processor and arch enumerations for C-SKY targets.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ Contributed by C-SKY Microsystems and Mentor Graphics.
+
+ 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 CSKY_OPTS_H
+#define CSKY_OPTS_H
+
+
+/* The various CSKY cores. */
+enum csky_processor_type
+{
+#undef CSKY_CORE
+#define CSKY_CORE(NAME, INTERNAL_IDENT, IDENT, ARCH, ISA) \
+ TARGET_CPU_##INTERNAL_IDENT,
+#include "csky_cores.def"
+#undef CSKY_CORE
+ /* Used to indicate that no processor has been specified. */
+ TARGET_CPU_csky_none
+};
+#define CSKY_TARGET_CORE_GET(name) TARGET_CPU_ ## name
+
+/* The various CSKY architectures. */
+enum csky_base_architecture
+{
+#undef CSKY_ARCH
+#define CSKY_ARCH(NAME, CORE_IDENT, ARCH, ISA) \
+ CSKY_BASE_ARCH_##ARCH,
+#include "csky_cores.def"
+#undef CSKY_ARCH
+ CSKY_BASE_ARCH_NONE
+};
+#define CSKY_TARGET_ARCH_GET(name) CSKY_BASE_ARCH_ ## name
+
+/* The various CSKY FPUs. */
+enum csky_fpu_type
+{
+#undef CSKY_FPU
+#define CSKY_FPU(NAME, CNAME, ISA) TARGET_FPU_##CNAME,
+#include "csky_cores.def"
+ TARGET_FPU_auto
+#undef CSKY_FPU
+};
+#define CSKY_TARGET_FPU_GET(name) TARGET_FPU_ ## name
+
+
+#endif /* CSKY_OPTS_H */
diff --git a/gcc/config/csky/csky_pipeline_ck801.md b/gcc/config/csky/csky_pipeline_ck801.md
new file mode 100644
index 0000000..00fc465
--- /dev/null
+++ b/gcc/config/csky/csky_pipeline_ck801.md
@@ -0,0 +1,54 @@
+;; Scheduler information for C-SKY CK801 processors.
+;; Copyright (C) 2018 Free Software Foundation, Inc.
+;; Contributed by C-SKY Microsystems and Mentor Graphics.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>. */
+
+;; This is just a placeholder for a more accurate pipeline
+;; description for CK801.
+
+(define_automaton "ck801")
+
+(define_cpu_unit "ck801_ex1" "ck801")
+(define_cpu_unit "ck801_exit" "ck801")
+
+(define_insn_reservation "ck801_generic" 1
+ (and (match_test "CSKY_TARGET_ARCH (CK801)")
+ (eq_attr "type" "alu,cmp,branch,cbranch,addsub,alu_ix,branch_jmp,call_jsr,call"))
+ "ck801_ex1+ck801_exit")
+
+(define_insn_reservation "ck801_load" 1
+ (and (match_test "CSKY_TARGET_ARCH (CK801)")
+ (and (eq_attr "type" "load")
+ (match_test "!csky_minipool_load_p (insn)")))
+ "ck801_ex1+ck801_exit")
+
+(define_insn_reservation "ck801_pool" 1
+ (and (match_test "CSKY_TARGET_ARCH (CK801)")
+ (and (eq_attr "type" "load")
+ (match_test "csky_minipool_load_p (insn)")))
+ "ck801_ex1+ck801_exit")
+
+(define_insn_reservation "ck801_store" 1
+ (and (match_test "CSKY_TARGET_ARCH (CK801)")
+ (eq_attr "type" "store"))
+ "ck801_ex1+ck801_exit")
+
+;; Switching between constant pool loads and loads/stores in the data section
+;; carries an extra penalty.
+(define_bypass 2 "ck801_load,ck801_store" "ck801_pool")
+(define_bypass 2 "ck801_pool" "ck801_load,ck801_store")
diff --git a/gcc/config/csky/csky_pipeline_ck802.md b/gcc/config/csky/csky_pipeline_ck802.md
new file mode 100644
index 0000000..f185d8c
--- /dev/null
+++ b/gcc/config/csky/csky_pipeline_ck802.md
@@ -0,0 +1,77 @@
+;; Instruction scheduling information for C-SKY CK802 processors.
+;; Copyright (C) 2018 Free Software Foundation, Inc.
+;; Contributed by C-SKY Microsystems and Mentor Graphics.
+;;
+;; 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/>. */
+
+(define_automaton "csky_ck802")
+
+(define_cpu_unit "csky_ck802_ex" "csky_ck802")
+(define_cpu_unit "csky_ck802_wb" "csky_ck802")
+
+(define_insn_reservation "ck802_alu" 2
+ (and (match_test "CSKY_TARGET_ARCH (CK802)")
+ (eq_attr "type" "alu"))
+ "csky_ck802_ex, csky_ck802_wb")
+
+(define_insn_reservation "ck802_branch" 2
+ (and (match_test "CSKY_TARGET_ARCH (CK802)")
+ (eq_attr "type" "branch, branch_jmp"))
+ "csky_ck802_ex, csky_ck802_wb")
+
+(define_insn_reservation "ck802_cmp" 2
+ (and (match_test "CSKY_TARGET_ARCH (CK802)")
+ (eq_attr "type" "cmp"))
+ "csky_ck802_ex, csky_ck802_wb")
+
+(define_insn_reservation "ck802_cbranch" 2
+ (and (match_test "CSKY_TARGET_ARCH (CK802)")
+ (eq_attr "type" "cbranch"))
+ "csky_ck802_ex, csky_ck802_wb")
+
+(define_insn_reservation "ck802_call" 2
+ (and (match_test "CSKY_TARGET_ARCH (CK802)")
+ (eq_attr "type" "call, call_jsr"))
+ "csky_ck802_ex, csky_ck802_wb")
+
+(define_insn_reservation "ck802_load" 2
+ (and (match_test "CSKY_TARGET_ARCH (CK802)")
+ (and (eq_attr "type" "load")
+ (match_test "!csky_minipool_load_p (insn)")))
+ "csky_ck802_ex, csky_ck802_wb")
+
+(define_insn_reservation "ck802_pool" 2
+ (and (match_test "CSKY_TARGET_ARCH (CK802)")
+ (and (eq_attr "type" "load")
+ (match_test "csky_minipool_load_p (insn)")))
+ "csky_ck802_ex, csky_ck802_wb")
+
+(define_insn_reservation "ck802_store" 2
+ (and (match_test "CSKY_TARGET_ARCH (CK802)")
+ (eq_attr "type" "store"))
+ "csky_ck802_ex, csky_ck802_wb")
+
+;; Switching between constant pool loads and loads/stores in the data section
+;; carries an extra penalty.
+(define_bypass 3 "ck802_load,ck802_store" "ck802_pool")
+(define_bypass 3 "ck802_pool" "ck802_load,ck802_store")
+
+(define_bypass 1 "*" "ck802_alu")
+
+(define_bypass 1 "*" "ck802_branch")
+
+(define_bypass 2 "ck802_cmp" "ck802_cbranch")
diff --git a/gcc/config/csky/csky_pipeline_ck803.md b/gcc/config/csky/csky_pipeline_ck803.md
new file mode 100644
index 0000000..f140cf6
--- /dev/null
+++ b/gcc/config/csky/csky_pipeline_ck803.md
@@ -0,0 +1,64 @@
+;; Scheduler information for C-SKY CK803 processors.
+;; Copyright (C) 2018 Free Software Foundation, Inc.
+;; Contributed by C-SKY Microsystems and Mentor Graphics.
+;;
+;; 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/>. */
+
+(define_automaton "ck803")
+
+(define_cpu_unit "ck803_ex1" "ck803")
+(define_cpu_unit "ck803_exit" "ck803")
+
+(define_insn_reservation "ck803_3cycle" 1
+ (and (match_test "CSKY_TARGET_ARCH (CK803)")
+ (eq_attr "type" "alu,cmp,branch,branch_jmp,call_jsr,call"))
+ "ck803_ex1+ck803_exit")
+
+(define_insn_reservation "ck803_alu1" 1
+ (and (match_test "CSKY_TARGET_ARCH (CK803)")
+ (eq_attr "type" "addsub,alu_ix"))
+ "ck803_ex1+ck803_exit")
+
+(define_insn_reservation "ck803_cbranch" 1
+ (and (match_test "CSKY_TARGET_ARCH (CK803)")
+ (eq_attr "type" "cbranch"))
+ "ck803_ex1+ck803_exit")
+
+(define_insn_reservation "ck803_load" 1
+ (and (match_test "CSKY_TARGET_ARCH (CK803)")
+ (and (eq_attr "type" "load")
+ (match_test "!csky_minipool_load_p (insn)")))
+ "ck803_ex1+ck803_exit")
+
+(define_insn_reservation "ck803_pool" 1
+ (and (match_test "CSKY_TARGET_ARCH (CK803)")
+ (and (eq_attr "type" "load")
+ (match_test "csky_minipool_load_p (insn)")))
+ "ck803_ex1+ck803_exit")
+
+(define_insn_reservation "ck803_store" 1
+ (and (match_test "CSKY_TARGET_ARCH (CK803)")
+ (eq_attr "type" "store"))
+ "ck803_ex1+ck803_exit")
+
+;; Switching between constant pool loads and loads/stores in the data section
+;; carries an extra penalty.
+(define_bypass 2 "ck803_load,ck803_store" "ck803_pool")
+(define_bypass 2 "ck803_pool" "ck803_load,ck803_store")
+
+(define_bypass 2 "ck803_3cycle,ck803_cbranch,ck803_load,ck803_store,ck803_pool"
+ "ck803_cbranch")
diff --git a/gcc/config/csky/csky_pipeline_ck810.md b/gcc/config/csky/csky_pipeline_ck810.md
new file mode 100644
index 0000000..aaba00b
--- /dev/null
+++ b/gcc/config/csky/csky_pipeline_ck810.md
@@ -0,0 +1,34 @@
+;; Instruction scheduling information for C-SKY CK810 processors.
+;; Copyright (C) 2018 Free Software Foundation, Inc.
+;; Contributed by C-SKY Microsystems and Mentor Graphics.
+;;
+;; 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/>. */
+
+
+;;-------------------------------------------------------------
+;; Pipeline descriptions for ck810
+;;-------------------------------------------------------------
+
+(define_attr "cycle" "1,2,not_used_yet"
+ (const_string "1"))
+(define_automaton "cskyv2_ck810")
+(define_cpu_unit "pipeline_alu0" "cskyv2_ck810")
+(define_insn_reservation "alu_one_cycle" 1
+ (and (eq_attr "cycle" "1")
+ (not (ior (match_test "CSKY_TARGET_ARCH (CK803)")
+ (match_test "CSKY_TARGET_ARCH (CK802)"))))
+ "pipeline_alu0")
diff --git a/gcc/config/csky/csky_tables.opt b/gcc/config/csky/csky_tables.opt
new file mode 100644
index 0000000..ae3438d
--- /dev/null
+++ b/gcc/config/csky/csky_tables.opt
@@ -0,0 +1,230 @@
+; -*- buffer-read-only: t -*-
+; Generated automatically by csky_genopt.sh from csky_cores.def.
+
+; Copyright (C) 2018 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/>.
+
+Enum
+Name(csky_processor_type) Type(enum csky_processor_type)
+Known CSKY CPUs (for use with the -mcpu= options):
+
+EnumValue
+Enum(csky_processor_type) String(ck801) Value( TARGET_CPU_ck801)
+
+EnumValue
+Enum(csky_processor_type) String(ck801t) Value( TARGET_CPU_ck801t)
+
+EnumValue
+Enum(csky_processor_type) String(ck802) Value( TARGET_CPU_ck802)
+
+EnumValue
+Enum(csky_processor_type) String(ck802t) Value( TARGET_CPU_ck802t)
+
+EnumValue
+Enum(csky_processor_type) String(ck802j) Value( TARGET_CPU_ck802j)
+
+EnumValue
+Enum(csky_processor_type) String(ck803) Value( TARGET_CPU_ck803)
+
+EnumValue
+Enum(csky_processor_type) String(ck803h) Value( TARGET_CPU_ck803h)
+
+EnumValue
+Enum(csky_processor_type) String(ck803t) Value( TARGET_CPU_ck803t)
+
+EnumValue
+Enum(csky_processor_type) String(ck803ht) Value( TARGET_CPU_ck803ht)
+
+EnumValue
+Enum(csky_processor_type) String(ck803f) Value( TARGET_CPU_ck803f)
+
+EnumValue
+Enum(csky_processor_type) String(ck803fh) Value( TARGET_CPU_ck803fh)
+
+EnumValue
+Enum(csky_processor_type) String(ck803e) Value( TARGET_CPU_ck803e)
+
+EnumValue
+Enum(csky_processor_type) String(ck803eh) Value( TARGET_CPU_ck803eh)
+
+EnumValue
+Enum(csky_processor_type) String(ck803et) Value( TARGET_CPU_ck803et)
+
+EnumValue
+Enum(csky_processor_type) String(ck803eht) Value( TARGET_CPU_ck803eht)
+
+EnumValue
+Enum(csky_processor_type) String(ck803ef) Value( TARGET_CPU_ck803ef)
+
+EnumValue
+Enum(csky_processor_type) String(ck803efh) Value( TARGET_CPU_ck803efh)
+
+EnumValue
+Enum(csky_processor_type) String(ck803ft) Value( TARGET_CPU_ck803ft)
+
+EnumValue
+Enum(csky_processor_type) String(ck803eft) Value( TARGET_CPU_ck803eft)
+
+EnumValue
+Enum(csky_processor_type) String(ck803efht) Value( TARGET_CPU_ck803efht)
+
+EnumValue
+Enum(csky_processor_type) String(ck803r1) Value( TARGET_CPU_ck803r1)
+
+EnumValue
+Enum(csky_processor_type) String(ck803hr1) Value( TARGET_CPU_ck803hr1)
+
+EnumValue
+Enum(csky_processor_type) String(ck803tr1) Value( TARGET_CPU_ck803tr1)
+
+EnumValue
+Enum(csky_processor_type) String(ck803htr1) Value( TARGET_CPU_ck803htr1)
+
+EnumValue
+Enum(csky_processor_type) String(ck803fr1) Value( TARGET_CPU_ck803fr1)
+
+EnumValue
+Enum(csky_processor_type) String(ck803fhr1) Value( TARGET_CPU_ck803fhr1)
+
+EnumValue
+Enum(csky_processor_type) String(ck803er1) Value( TARGET_CPU_ck803er1)
+
+EnumValue
+Enum(csky_processor_type) String(ck803ehr1) Value( TARGET_CPU_ck803ehr1)
+
+EnumValue
+Enum(csky_processor_type) String(ck803etr1) Value( TARGET_CPU_ck803etr1)
+
+EnumValue
+Enum(csky_processor_type) String(ck803ehtr1) Value( TARGET_CPU_ck803ehtr1)
+
+EnumValue
+Enum(csky_processor_type) String(ck803efr1) Value( TARGET_CPU_ck803efr1)
+
+EnumValue
+Enum(csky_processor_type) String(ck803efhr1) Value( TARGET_CPU_ck803efhr1)
+
+EnumValue
+Enum(csky_processor_type) String(ck803ftr1) Value( TARGET_CPU_ck803ftr1)
+
+EnumValue
+Enum(csky_processor_type) String(ck803eftr1) Value( TARGET_CPU_ck803eftr1)
+
+EnumValue
+Enum(csky_processor_type) String(ck803efhtr1) Value( TARGET_CPU_ck803efhtr1)
+
+EnumValue
+Enum(csky_processor_type) String(ck803s) Value( TARGET_CPU_ck803s)
+
+EnumValue
+Enum(csky_processor_type) String(ck803st) Value( TARGET_CPU_ck803st)
+
+EnumValue
+Enum(csky_processor_type) String(ck803se) Value( TARGET_CPU_ck803se)
+
+EnumValue
+Enum(csky_processor_type) String(ck803sf) Value( TARGET_CPU_ck803sf)
+
+EnumValue
+Enum(csky_processor_type) String(ck803sef) Value( TARGET_CPU_ck803sef)
+
+EnumValue
+Enum(csky_processor_type) String(ck803seft) Value( TARGET_CPU_ck803seft)
+
+EnumValue
+Enum(csky_processor_type) String(ck807e) Value( TARGET_CPU_ck807e)
+
+EnumValue
+Enum(csky_processor_type) String(ck807ef) Value( TARGET_CPU_ck807ef)
+
+EnumValue
+Enum(csky_processor_type) String(ck807) Value( TARGET_CPU_ck807)
+
+EnumValue
+Enum(csky_processor_type) String(ck807f) Value( TARGET_CPU_ck807f)
+
+EnumValue
+Enum(csky_processor_type) String(ck810e) Value( TARGET_CPU_ck810e)
+
+EnumValue
+Enum(csky_processor_type) String(ck810et) Value( TARGET_CPU_ck810et)
+
+EnumValue
+Enum(csky_processor_type) String(ck810ef) Value( TARGET_CPU_ck810ef)
+
+EnumValue
+Enum(csky_processor_type) String(ck810eft) Value( TARGET_CPU_ck810eft)
+
+EnumValue
+Enum(csky_processor_type) String(ck810) Value( TARGET_CPU_ck810)
+
+EnumValue
+Enum(csky_processor_type) String(ck810v) Value( TARGET_CPU_ck810v)
+
+EnumValue
+Enum(csky_processor_type) String(ck810f) Value( TARGET_CPU_ck810f)
+
+EnumValue
+Enum(csky_processor_type) String(ck810t) Value( TARGET_CPU_ck810t)
+
+EnumValue
+Enum(csky_processor_type) String(ck810fv) Value( TARGET_CPU_ck810fv)
+
+EnumValue
+Enum(csky_processor_type) String(ck810tv) Value( TARGET_CPU_ck810tv)
+
+EnumValue
+Enum(csky_processor_type) String(ck810ft) Value( TARGET_CPU_ck810ff)
+
+EnumValue
+Enum(csky_processor_type) String(ck810ftv) Value( TARGET_CPU_ck810ftv)
+
+Enum
+Name(csky_arch) Type(int)
+Known CSKY architectures (for use with the -march= option):
+
+EnumValue
+Enum(csky_arch) String(ck801) Value(0)
+
+EnumValue
+Enum(csky_arch) String(ck802) Value(1)
+
+EnumValue
+Enum(csky_arch) String(ck803) Value(2)
+
+EnumValue
+Enum(csky_arch) String(ck807) Value(3)
+
+EnumValue
+Enum(csky_arch) String(ck810) Value(4)
+
+Enum
+Name(csky_fpu) Type(enum csky_fpu_type)
+Known CSKY FPUs (for use with the -mfpu= option):
+
+EnumValue
+Enum(csky_fpu) String(fpv2_sf) Value(TARGET_FPU_fpv2_sf)
+
+EnumValue
+Enum(csky_fpu) String(fpv2) Value(TARGET_FPU_fpv2)
+
+EnumValue
+Enum(csky_fpu) String(fpv2_divd) Value(TARGET_FPU_fpv2_divd)
+
+EnumValue
+Enum(csky_fpu) String(auto) Value(TARGET_FPU_auto)
diff --git a/gcc/config/csky/predicates.md b/gcc/config/csky/predicates.md
new file mode 100644
index 0000000..2899f0b
--- /dev/null
+++ b/gcc/config/csky/predicates.md
@@ -0,0 +1,298 @@
+;; Predicates for C-SKY.
+;; Copyright (C) 2018 Free Software Foundation, Inc.
+;; Contributed by C-SKY Microsystems and Mentor Graphics.
+;;
+;; 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/>. */
+
+;; Return 1 if OP is a load multiple operation.
+
+(define_predicate "csky_load_multiple_operation"
+ (match_code "parallel")
+{
+ int count = XVECLEN (op, 0);
+ int dest_regno;
+ rtx src_addr;
+ int i;
+
+ /* Perform a quick check so we don't blow up below. */
+ if (count <= 1
+ || GET_CODE (XVECEXP (op, 0, 0)) != SET
+ || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM
+ || GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0)) != REG
+ || XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0) != stack_pointer_rtx)
+ return 0;
+
+ dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
+ src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
+
+ for (i = 1; i < count; i++)
+ {
+ rtx elt = XVECEXP (op, 0, i);
+
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != SImode
+ || REGNO (SET_DEST (elt)) != (unsigned) (dest_regno + i)
+ || GET_CODE (SET_SRC (elt)) != MEM
+ || GET_MODE (SET_SRC (elt)) != SImode
+ || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
+ || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
+ || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
+ || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != i * 4)
+ return 0;
+ }
+ return 1;
+})
+
+;; Similar, for store multiple.
+
+(define_predicate "csky_store_multiple_operation"
+ (match_code "parallel")
+{
+ int count = XVECLEN (op, 0);
+ int src_regno;
+ rtx dest_addr;
+ int i;
+
+ /* Perform a quick check so we don't blow up below. */
+ if (count <= 1
+ || GET_CODE (XVECEXP (op, 0, 0)) != SET
+ || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
+ || GET_CODE (XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0)) != REG
+ || XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0) != stack_pointer_rtx
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
+ return 0;
+
+ src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
+ dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
+
+ for (i = 1; i < count; i++)
+ {
+ rtx elt = XVECEXP (op, 0, i);
+
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_SRC (elt)) != REG
+ || GET_MODE (SET_SRC (elt)) != SImode
+ || REGNO (SET_SRC (elt)) != (unsigned) (src_regno + i)
+ || GET_CODE (SET_DEST (elt)) != MEM
+ || GET_MODE (SET_DEST (elt)) != SImode
+ || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
+ || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
+ || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
+ || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != i * 4)
+ return 0;
+ }
+ return 1;
+})
+
+
+(define_predicate "csky_arith_K_operand"
+ (match_code "reg,subreg,const_int")
+ {
+ if (register_operand (op, mode))
+ return 1;
+ if (CONST_INT_P (op) && CSKY_CONST_OK_FOR_K (INTVAL (op)))
+ return 1;
+ return 0;
+ })
+
+(define_predicate "csky_literal_K_operand"
+ (match_code "const_int")
+ {
+ if (CONST_INT_P (op) && CSKY_CONST_OK_FOR_K (INTVAL (op)))
+ return 1;
+ return 0;
+ })
+
+(define_predicate "csky_literal_I_operand"
+ (match_code "const_int")
+ {
+ if (CONST_INT_P (op) && CSKY_CONST_OK_FOR_I (INTVAL (op)))
+ return 1;
+ return 0;
+ })
+
+(define_predicate "csky_literal_J_operand"
+ (match_code "const_int")
+ {
+ if (CONST_INT_P (op) && CSKY_CONST_OK_FOR_J (INTVAL (op)))
+ return 1;
+ return 0;
+ })
+
+(define_predicate "csky_literal_Uk_operand"
+ (match_code "const_int")
+ {
+ if (CONST_INT_P (op) && CSKY_CONST_OK_FOR_Uk (INTVAL (op)))
+ return 1;
+ return 0;
+ })
+
+;; Nonzero if OP is a register or constant value of 1
+
+(define_predicate "csky_arith_int1_operand"
+ (match_code "reg,subreg,const_int")
+ {
+ if (register_operand (op, mode))
+ return 1;
+ if (op == const1_rtx)
+ return 1;
+ return 0;
+ })
+
+
+;; Nonzero if OP is legal address for function call
+
+(define_predicate "csky_call_address_operand"
+ (match_code "reg,subreg,symbol_ref")
+ {
+ if (!flag_pic && (GET_CODE (op) == SYMBOL_REF))
+ return 1;
+ if (register_operand (op, mode))
+ return 1;
+ return 0;
+ })
+
+;; Nonzero if OP is a valid source operand for a compare operation.
+
+(define_predicate "csky_compare_operand"
+ (match_code "const_int,reg,subreg")
+ {
+ if (register_operand (op, mode))
+ return 1;
+ if (GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
+ return 1;
+ return 0;
+ })
+
+(define_predicate "csky_literal_K_Uh_operand"
+ (match_code "const_int")
+ {
+ if (CONST_INT_P (op)
+ && (CSKY_CONST_OK_FOR_K (INTVAL (op))
+ || CSKY_CONST_OK_FOR_Uh (INTVAL (op))))
+ return 1;
+ return 0;
+ })
+
+;; True if OP is a mem with an reg + optional displacement address.
+
+(define_predicate "csky_simple_mem_operand"
+ (and (match_operand 0 "memory_operand")
+ (match_test "csky_simple_addr_operand_p (XEXP (op, 0))")))
+
+(define_predicate "csky_arith_any_imm_operand"
+ (match_code "const_int,reg,subreg")
+ {
+ if (register_operand (op, mode))
+ return 1;
+ if (CONST_INT_P (op))
+ return 1;
+ return 0;
+ })
+
+(define_predicate "csky_arith_O_operand"
+ (match_code "reg,subreg,const_int")
+ {
+ if (register_operand (op, mode))
+ return 1;
+ if (CONST_INT_P (op) && CSKY_CONST_OK_FOR_O (INTVAL (op)))
+ return 1;
+ return 0;
+ })
+
+(define_predicate "csky_unspec_operand"
+ (match_code "unspec")
+ {
+ if (op == NULL || GET_CODE(op) != UNSPEC)
+ return 0;
+ return 1;
+ }
+)
+
+(define_predicate "csky_const_float1_operand"
+ (and (match_code "const_double")
+ (match_test "(op == CONST1_RTX (mode))")))
+
+(define_predicate "csky_arith_float1_operand"
+ (ior (match_operand 0 "register_operand")
+ (match_operand 0 "csky_const_float1_operand")))
+
+(define_predicate "csky_const_float0_operand"
+ (and (match_code "const_double")
+ (match_test "(op == CONST0_RTX (mode))")))
+
+(define_predicate "csky_compare_operand_float"
+ (ior (match_operand 0 "register_operand")
+ (match_operand 0 "csky_const_float0_operand")))
+
+(define_special_predicate "registers_push"
+ (match_code "parallel")
+{
+ if ((GET_CODE (XVECEXP (op, 0, 0)) != SET)
+ || (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC)
+ || (XINT (SET_SRC (XVECEXP (op, 0, 0)), 1) != UNSPEC_PUSHPOP_MULT))
+ return false;
+ return true;
+})
+
+(define_special_predicate "registers_pop"
+ (match_code "parallel")
+{
+ if ((GET_CODE (XVECEXP (op, 0, 1)) != SET)
+ || (GET_CODE (SET_SRC (XVECEXP (op, 0, 1))) != UNSPEC)
+ || (XINT (SET_SRC (XVECEXP (op, 0, 1)), 1) != UNSPEC_PUSHPOP_MULT))
+ return false;
+ return true;
+})
+
+(define_predicate "push_memory_operand"
+ (match_code "mem")
+{
+ rtx x = XEXP (op, 0);
+ if (GET_CODE (x) != PRE_MODIFY)
+ return false;
+ if (XEXP (x, 0) != stack_pointer_rtx)
+ return false;
+ x = XEXP (x, 1);
+ if (GET_CODE (x) != PLUS)
+ return false;
+ if (XEXP (x, 0) != stack_pointer_rtx)
+ return false;
+ return CONST_INT_P (XEXP (x, 1));
+})
+
+(define_predicate "pop_memory_operand"
+ (match_code "mem")
+{
+ rtx x = XEXP (op, 0);
+ if (GET_CODE (x) != POST_MODIFY)
+ return false;
+ if (XEXP (x, 0) != stack_pointer_rtx)
+ return false;
+ x = XEXP (x, 1);
+ if (GET_CODE (x) != PLUS)
+ return false;
+ if (XEXP (x, 0) != stack_pointer_rtx)
+ return false;
+ return CONST_INT_P (XEXP (x, 1));
+})
+
+(define_special_predicate "csky_float_comparison_operator"
+ (match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu,
+ unordered,ordered"))
diff --git a/gcc/config/csky/print-sysroot-suffix.sh b/gcc/config/csky/print-sysroot-suffix.sh
new file mode 100644
index 0000000..5cbdc3f
--- /dev/null
+++ b/gcc/config/csky/print-sysroot-suffix.sh
@@ -0,0 +1,147 @@
+#! /bin/sh
+# Script to generate SYSROOT_SUFFIX_SPEC equivalent to MULTILIB_OSDIRNAMES
+# Arguments are MULTILIB_OSDIRNAMES, MULTILIB_OPTIONS and MULTILIB_MATCHES.
+
+# Copyright (C) 2018 Free Software Foundation, Inc.
+# Contributed by C-SKY Microsystems and Mentor Graphics.
+
+# This file is part of GCC.
+
+# GCC is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 3, or (at your option) any later
+# version.
+
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# This shell script produces a header file fragment that defines
+# SYSROOT_SUFFIX_SPEC. It assumes that the sysroots will have the same
+# structure and names used by the multilibs.
+
+# Invocation:
+# print-sysroot-suffix.sh \
+# MULTILIB_OSDIRNAMES \
+# MULTILIB_OPTIONS \
+# MULTILIB_MATCHES \
+# > t-sysroot-suffix.h
+
+# The three options exactly correspond to the variables of the same
+# names defined in the tmake_file fragments.
+
+# Example:
+# sh ./gcc/config/print-sysroot-suffix.sh "a=A" "a b/c/d" ""
+# =>
+# #undef SYSROOT_SUFFIX_SPEC
+# #define SYSROOT_SUFFIX_SPEC "" \
+# "%{a:" \
+# "%{b:A/b/;" \
+# "c:A/c/;" \
+# "d:A/d/;" \
+# ":A/};" \
+# ":}"
+
+# The script uses temporary subscripts in order to permit a recursive
+# algorithm without the use of functions.
+
+set -e
+
+dirnames="$1"
+options="$2"
+matches="$3"
+
+cat > print-sysroot-suffix3.sh <<\EOF
+#! /bin/sh
+# Print all the multilib matches for this option
+result="$1"
+EOF
+for x in $matches; do
+ l=`echo $x | sed -e 's/=.*$//' -e 's/?/=/g'`
+ r=`echo $x | sed -e 's/^.*=//' -e 's/?/=/g'`
+ echo "[ \"\$1\" = \"$l\" ] && result=\"\$result|$r\"" >> print-sysroot-suffix3.sh
+done
+echo 'echo $result' >> print-sysroot-suffix3.sh
+chmod +x print-sysroot-suffix3.sh
+
+cat > print-sysroot-suffix2.sh <<\EOF
+#! /bin/sh
+# Recursive script to enumerate all multilib combinations, match against
+# multilib directories and output a spec string of the result.
+# Will fold identical trees.
+
+padding="$1"
+optstring="$2"
+shift 2
+n="\" \\
+$padding\""
+if [ $# = 0 ]; then
+EOF
+
+pat=
+for x in $dirnames; do
+# p=`echo $x | sed -e 's,=!,/$=/,'`
+ p=`echo $x | sed -e 's/=//g'`
+# pat="$pat -e 's=^//$p='"
+ pat="$pat -e 's/$p/g'"
+done
+echo ' optstring=`echo "/$optstring" | sed '"$pat\`" >> print-sysroot-suffix2.sh
+cat >> print-sysroot-suffix2.sh <<\EOF
+ case $optstring in
+ //*)
+ ;;
+ *)
+ echo "$optstring"
+ ;;
+ esac
+else
+ thisopt="$1"
+ shift
+ bit=
+ lastcond=
+ result=
+ for x in `echo "$thisopt" | sed -e 's,/, ,g'`; do
+ case $x in
+EOF
+for x in `echo "$options" | sed -e 's,/, ,g'`; do
+ match=`./print-sysroot-suffix3.sh "$x"`
+ echo "$x) optmatch=\"$match\" ;;" >> print-sysroot-suffix2.sh
+done
+cat >> print-sysroot-suffix2.sh <<\EOF
+ esac
+ bit=`"$0" "$padding " "$optstring$x/" "$@"`
+ if [ -z "$lastopt" ]; then
+ lastopt="$optmatch"
+ else
+ if [ "$lastbit" = "$bit" ]; then
+ lastopt="$lastopt|$optmatch"
+ else
+ result="$result$lastopt:$lastbit;$n"
+ lastopt="$optmatch"
+ fi
+ fi
+ lastbit="$bit"
+ done
+ bit=`"$0" "$padding " "$optstring" "$@"`
+ if [ "$bit" = "$lastbit" ]; then
+ if [ -z "$result" ]; then
+ echo "$bit"
+ else
+ echo "$n%{$result:$bit}"
+ fi
+ else
+ echo "$n%{$result$lastopt:$lastbit;$n:$bit}"
+ fi
+fi
+EOF
+chmod +x ./print-sysroot-suffix2.sh
+result=`./print-sysroot-suffix2.sh \"\" \"\" $options`
+echo "#undef SYSROOT_SUFFIX_SPEC"
+echo "#define SYSROOT_SUFFIX_SPEC \"$result\""
+rm print-sysroot-suffix2.sh
+rm print-sysroot-suffix3.sh
diff --git a/gcc/config/rs6000/t-aix43 b/gcc/config/csky/t-csky
index 5c243d4..ab9be18 100644
--- a/gcc/config/rs6000/t-aix43
+++ b/gcc/config/csky/t-csky
@@ -1,4 +1,7 @@
-# Copyright (C) 1998-2018 Free Software Foundation, Inc.
+# Make rules for all C-SKY targets.
+#
+# Copyright (C) 2018 Free Software Foundation, Inc.
+# Contributed by C-SKY Microsystems and Mentor Graphics.
#
# This file is part of GCC.
#
@@ -16,24 +19,11 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# Build the libraries for pthread and all of the
-# different processor models
-
-MULTILIB_OPTIONS = pthread \
- mcpu=common/mcpu=powerpc/maix64
+TM_H += $(srcdir)/config/csky/csky_cores.def
+OPTIONS_H_EXTRA += $(srcdir)/config/csky/csky_cores.def
-MULTILIB_DIRNAMES = pthread \
- common powerpc ppc64
-MULTILIB_MATCHES = mcpu?powerpc=mcpu?power3 \
- mcpu?powerpc=mcpu?power4 \
- mcpu?powerpc=mcpu?powerpc \
- mcpu?powerpc=mcpu?rs64a \
- mcpu?powerpc=mcpu?601 \
- mcpu?powerpc=mcpu?602 \
- mcpu?powerpc=mcpu?603 \
- mcpu?powerpc=mcpu?603e \
- mcpu?powerpc=mcpu?604 \
- mcpu?powerpc=mcpu?604e \
- mcpu?powerpc=mcpu?620 \
- mcpu?powerpc=mcpu?630
+$(srcdir)/config/csky/csky_tables.opt: $(srcdir)/config/csky/csky_genopt.sh \
+ $(srcdir)/config/csky/csky_cores.def
+ $(SHELL) $(srcdir)/config/csky/csky_genopt.sh $(srcdir)/config/csky > \
+ $(srcdir)/config/csky/csky_tables.opt
diff --git a/gcc/config/csky/t-csky-elf b/gcc/config/csky/t-csky-elf
new file mode 100644
index 0000000..6864544
--- /dev/null
+++ b/gcc/config/csky/t-csky-elf
@@ -0,0 +1,107 @@
+# Multilib configuration for csky*-elf.
+#
+# Copyright (C) 2018 Free Software Foundation, Inc.
+# Contributed by C-SKY Microsystems and Mentor Graphics.
+#
+# 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/>.
+
+# Endiannesses.
+MULTILIB_OPTIONS = mlittle-endian/mbig-endian
+MULTILIB_DIRNAMES = little big
+MULTILIB_MATCHES = mlittle-endian=EL
+MULTILIB_MATCHES = mbig-endian=EB
+MULTILIB_EXCEPTIONS =
+
+# Arch variants.
+MULTILIB_OPTIONS += mcpu=ck802/mcpu=ck801/mcpu=ck803f/mcpu=ck807f/mcpu=ck810f
+MULTILIB_DIRNAMES += ck802 ck801 ck803 ck807 ck810
+
+# For arch ck802.
+MULTILIB_MATCHES += mcpu?ck802=march?ck802
+MULTILIB_MATCHES += mcpu?ck802=mcpu?ck802t
+MULTILIB_MATCHES += mcpu?ck802=mcpu?ck802j
+
+# For arch ck801.
+MULTILIB_MATCHES += mcpu?ck801=march?ck801
+MULTILIB_MATCHES += mcpu?ck801=mcpu?ck801t
+
+# For arch ck803.
+MULTILIB_MATCHES += mcpu?ck803f=march?ck803
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803fh
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803h
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803t
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803ht
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803e
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803eh
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803et
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803eht
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803ef
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803efh
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803ft
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803eft
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803efht
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803r1
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803fr1
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803fhr1
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803hr1
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803tr1
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803htr1
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803er1
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803ehr1
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803etr1
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803ehtr1
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803efr1
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803efhr1
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803ftr1
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803eftr1
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803efhtr1
+
+# For arch ck803s.
+MULTILIB_MATCHES += mcpu?ck803f=march?ck803s
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803s
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803st
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803se
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803sf
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803sef
+MULTILIB_MATCHES += mcpu?ck803f=mcpu?ck803seft
+
+# For arch ck810.
+MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810e
+MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810et
+MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810ef
+MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810eft
+MULTILIB_MATCHES += mcpu?ck810f=march?ck810
+MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810
+MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810v
+MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810t
+MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810vf
+MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810tv
+MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810ft
+MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810ftv
+
+# For arch ck807.
+MULTILIB_MATCHES += mcpu?ck807f=march?ck807e
+MULTILIB_MATCHES += mcpu?ck807f=march?ck807ef
+MULTILIB_MATCHES += mcpu?ck807f=march?ck807
+MULTILIB_MATCHES += mcpu?ck807f=mcpu?ck807
+
+# For option -msoft-float/-mhard-float.
+MULTILIB_OPTIONS += msoft-float/mhard-float
+MULTILIB_DIRNAMES += soft-fp hard-fp
+MULTILIB_EXCEPTIONS += *mcpu=ck801/*mhard-float*
+MULTILIB_EXCEPTIONS += *mcpu=ck802/*mhard-float*
diff --git a/gcc/config/csky/t-csky-linux b/gcc/config/csky/t-csky-linux
new file mode 100644
index 0000000..4a145a6
--- /dev/null
+++ b/gcc/config/csky/t-csky-linux
@@ -0,0 +1,52 @@
+# Multilib configuration for csky*-linux-*.
+#
+# Copyright (C) 2018 Free Software Foundation, Inc.
+# Contributed by C-SKY Microsystems and Mentor Graphics.
+#
+# 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/>.
+
+
+# Endiannesses.
+MULTILIB_OPTIONS = mlittle-endian/mbig-endian
+MULTILIB_DIRNAMES = little big
+MULTILIB_MATCHES = mlittle-endian=EL
+MULTILIB_MATCHES = mbig-endian=EB
+
+MULTILIB_EXCEPTIONS =
+CSKY_MULTILIB_OSDIRNAMES = mbig-endian=/big mlittle-endian=/. mhard-float=/hard-fp msoft-float=/. mcpu.ck810f=/. mcpu.ck807f=/ck807
+
+# Arch variants.
+MULTILIB_OPTIONS += mcpu=ck810f/mcpu=ck807f
+MULTILIB_DIRNAMES += ck810 ck807
+
+# For ck807.
+MULTILIB_MATCHES += mcpu?ck807f=march?ck807
+MULTILIB_MATCHES += mcpu?ck807f=mcpu?ck807
+
+# For arch ck810.
+MULTILIB_MATCHES += mcpu?ck810f=march?ck810
+MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810
+MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810v
+MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810t
+MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810vt
+MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810vf
+MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810ft
+MULTILIB_MATCHES += mcpu?ck810f=mcpu?ck810vft
+
+# For option -msoft-float/-mhard-float.
+MULTILIB_OPTIONS += msoft-float/mhard-float
+MULTILIB_DIRNAMES += soft-fp hard-fp
diff --git a/gcc/config/csky/t-sysroot-suffix b/gcc/config/csky/t-sysroot-suffix
new file mode 100644
index 0000000..97c03d3
--- /dev/null
+++ b/gcc/config/csky/t-sysroot-suffix
@@ -0,0 +1,28 @@
+# Makefile fragment for C-SKY sysroot suffix.
+#
+# Copyright (C) 2018 Free Software Foundation, Inc.
+# Contributed by C-SKY Microsystems and Mentor Graphics.
+#
+# 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/>.
+
+# Generate SYSROOT_SUFFIX_SPEC from MULTILIB_OSDIRNAMES.
+
+sysroot-suffix.h: $(srcdir)/config/csky/print-sysroot-suffix.sh
+ $(SHELL) $(srcdir)/config/csky/print-sysroot-suffix.sh \
+ "$(CSKY_MULTILIB_OSDIRNAMES)" "$(MULTILIB_OPTIONS)" \
+ "$(MULTILIB_MATCHES)" > tmp-sysroot-suffix.h
+ mv tmp-sysroot-suffix.h $@
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index 3a08aea..aa2ef91 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -824,8 +824,7 @@ machopic_legitimize_pic_address (rtx orig, machine_mode mode, rtx reg)
/* First handle a simple SYMBOL_REF or LABEL_REF */
if (GET_CODE (orig) == LABEL_REF
- || (GET_CODE (orig) == SYMBOL_REF
- ))
+ || GET_CODE (orig) == SYMBOL_REF)
{
/* addr(foo) = &func+(foo-func) */
orig = machopic_indirect_data_reference (orig, reg);
@@ -1024,10 +1023,6 @@ machopic_legitimize_pic_address (rtx orig, machine_mode mode, rtx reg)
return pic_ref;
}
}
-
- else if (GET_CODE (orig) == SYMBOL_REF)
- return orig;
-
else if (GET_CODE (orig) == PLUS
&& (GET_CODE (XEXP (orig, 0)) == MEM
|| GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
@@ -1057,12 +1052,10 @@ machopic_legitimize_pic_address (rtx orig, machine_mode mode, rtx reg)
}
/* Likewise, should we set special REG_NOTEs here? */
}
-
else if (GET_CODE (orig) == CONST)
{
return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
}
-
else if (GET_CODE (orig) == MEM
&& GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
{
@@ -3176,6 +3169,14 @@ darwin_override_options (void)
if (!global_options_set.x_dwarf_version)
dwarf_version = 2;
+ if (global_options_set.x_dwarf_split_debug_info)
+ {
+ inform (input_location,
+ "-gsplit-dwarf is not supported on this platform, ignored");
+ dwarf_split_debug_info = 0;
+ global_options_set.x_dwarf_split_debug_info = 0;
+ }
+
/* Do not allow unwind tables to be generated by default for m32.
fnon-call-exceptions will override this, regardless of what we do. */
if (generating_for_darwin_version < 10
@@ -3711,19 +3712,4 @@ default_function_sections:
: text_section;
}
-/* When a function is partitioned between sections, we need to insert a label
- at the start of each new chunk - so that it may become a valid 'atom' for
- eh and debug purposes. Without this the linker will emit warnings if one
- tries to add line location information (since the switched fragment will
- be anonymous). */
-
-void
-darwin_function_switched_text_sections (FILE *fp, tree decl, bool new_is_cold)
-{
- /* Make sure we pick up all the relevant quotes etc. */
- assemble_name_raw (fp, new_is_cold ? "__cold_sect_of_" : "__hot_sect_of_");
- assemble_name_raw (fp, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
- fputs (":\n", fp);
-}
-
#include "gt-darwin.h"
diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
index 980ad9b..87f6102 100644
--- a/gcc/config/darwin.h
+++ b/gcc/config/darwin.h
@@ -122,7 +122,9 @@ extern GTY(()) int darwin_ms_struct;
"%{gfull:-g -fno-eliminate-unused-debug-symbols} %<gfull", \
"%{gused:-g -feliminate-unused-debug-symbols} %<gused", \
"%{fapple-kext|mkernel:-static}", \
- "%{shared:-Zdynamiclib} %<shared"
+ "%{shared:-Zdynamiclib} %<shared", \
+ "%{gsplit-dwarf:%ngsplit-dwarf is not supported on this platform } \
+ %<gsplit-dwarf"
#define DARWIN_CC1_SPEC \
"%{findirect-virtual-calls: -fapple-kext} %<findirect-virtual-calls " \
@@ -173,25 +175,25 @@ extern GTY(()) int darwin_ms_struct;
%(linker)" \
LINK_PLUGIN_SPEC \
"%{flto*:%<fcompare-debug*} \
- %{flto*} \
+ %{flto} %{fno-lto} %{flto=*} \
%l " LINK_COMPRESS_DEBUG_SPEC \
"%X %{s} %{t} %{Z} %{u*} \
%{e*} %{r} \
%{o*}%{!o:-o a.out} \
- %{!nostdlib:%{!nostartfiles:%S}} \
+ %{!nostdlib:%{!r:%{!nostartfiles:%S}}} \
%{L*} %(link_libgcc) %o %{fprofile-arcs|fprofile-generate*|coverage:-lgcov} \
%{fopenacc|fopenmp|%:gt(%{ftree-parallelize-loops=*:%*} 1): \
%{static|static-libgcc|static-libstdc++|static-libgfortran: libgomp.a%s; : -lgomp } } \
%{fgnu-tm: \
%{static|static-libgcc|static-libstdc++|static-libgfortran: libitm.a%s; : -litm } } \
- %{!nostdlib:%{!nodefaultlibs:\
+ %{!nostdlib:%{!r:%{!nodefaultlibs:\
%{%:sanitize(address): -lasan } \
%{%:sanitize(undefined): -lubsan } \
%(link_ssp) \
" DARWIN_EXPORT_DYNAMIC " %<rdynamic \
%(link_gcc_c_sequence) \
- }}\
- %{!nostdlib:%{!nostartfiles:%E}} %{T*} %{F*} }}}}}}}"
+ }}}\
+ %{!nostdlib:%{!r:%{!nostartfiles:%E}}} %{T*} %{F*} }}}}}}}"
#define DSYMUTIL "\ndsymutil"
@@ -421,6 +423,8 @@ extern GTY(()) int darwin_ms_struct;
debugging data. */
#define ASM_DEBUG_SPEC "%{g*:%{%:debug-level-gt(0):%{!gdwarf*:--gstabs}}}"
+#define ASM_FINAL_SPEC \
+ "%{gsplit-dwarf:%ngsplit-dwarf is not supported on this platform } %<gsplit-dwarf"
/* We still allow output of STABS if the assembler supports it. */
#ifdef HAVE_AS_STABS_DIRECTIVE
@@ -430,18 +434,20 @@ extern GTY(()) int darwin_ms_struct;
#define DWARF2_DEBUGGING_INFO 1
-#define DEBUG_FRAME_SECTION "__DWARF,__debug_frame,regular,debug"
-#define DEBUG_INFO_SECTION "__DWARF,__debug_info,regular,debug"
-#define DEBUG_ABBREV_SECTION "__DWARF,__debug_abbrev,regular,debug"
-#define DEBUG_ARANGES_SECTION "__DWARF,__debug_aranges,regular,debug"
-#define DEBUG_MACINFO_SECTION "__DWARF,__debug_macinfo,regular,debug"
-#define DEBUG_LINE_SECTION "__DWARF,__debug_line,regular,debug"
-#define DEBUG_LOC_SECTION "__DWARF,__debug_loc,regular,debug"
-#define DEBUG_PUBNAMES_SECTION "__DWARF,__debug_pubnames,regular,debug"
-#define DEBUG_PUBTYPES_SECTION "__DWARF,__debug_pubtypes,regular,debug"
-#define DEBUG_STR_SECTION "__DWARF,__debug_str,regular,debug"
-#define DEBUG_RANGES_SECTION "__DWARF,__debug_ranges,regular,debug"
-#define DEBUG_MACRO_SECTION "__DWARF,__debug_macro,regular,debug"
+#define DEBUG_FRAME_SECTION "__DWARF,__debug_frame,regular,debug"
+#define DEBUG_INFO_SECTION "__DWARF,__debug_info,regular,debug"
+#define DEBUG_ABBREV_SECTION "__DWARF,__debug_abbrev,regular,debug"
+#define DEBUG_ARANGES_SECTION "__DWARF,__debug_aranges,regular,debug"
+#define DEBUG_MACINFO_SECTION "__DWARF,__debug_macinfo,regular,debug"
+#define DEBUG_LINE_SECTION "__DWARF,__debug_line,regular,debug"
+#define DEBUG_LOC_SECTION "__DWARF,__debug_loc,regular,debug"
+#define DEBUG_LOCLISTS_SECTION "__DWARF,__debug_loclists,regular,debug"
+
+#define DEBUG_STR_SECTION "__DWARF,__debug_str,regular,debug"
+#define DEBUG_STR_OFFSETS_SECTION "__DWARF,__debug_str_offs,regular,debug"
+#define DEBUG_RANGES_SECTION "__DWARF,__debug_ranges,regular,debug"
+#define DEBUG_RNGLISTS_SECTION "__DWARF,__debug_rnglists,regular,debug"
+#define DEBUG_MACRO_SECTION "__DWARF,__debug_macro,regular,debug"
#define DEBUG_LTO_INFO_SECTION "__GNU_DWARF_LTO,__debug_info,regular,debug"
#define DEBUG_LTO_ABBREV_SECTION "__GNU_DWARF_LTO,__debug_abbrev,regular,debug"
@@ -451,6 +457,13 @@ extern GTY(()) int darwin_ms_struct;
#define DEBUG_LTO_MACRO_SECTION "__GNU_DWARF_LTO,__debug_macro,regular,debug"
#define TARGET_WANT_DEBUG_PUB_SECTIONS true
+#define DEBUG_PUBNAMES_SECTION ((debug_generate_pub_sections == 2) \
+ ? "__DWARF,__debug_gnu_pubn,regular,debug" \
+ : "__DWARF,__debug_pubnames,regular,debug")
+
+#define DEBUG_PUBTYPES_SECTION ((debug_generate_pub_sections == 2) \
+ ? "__DWARF,__debug_gnu_pubt,regular,debug" \
+ : "__DWARF,__debug_pubtypes,regular,debug")
/* When generating stabs debugging, use N_BINCL entries. */
@@ -708,10 +721,6 @@ extern GTY(()) section * darwin_sections[NUM_DARWIN_SECTIONS];
#undef TARGET_ASM_FUNCTION_SECTION
#define TARGET_ASM_FUNCTION_SECTION darwin_function_section
-#undef TARGET_ASM_FUNCTION_SWITCHED_TEXT_SECTIONS
-#define TARGET_ASM_FUNCTION_SWITCHED_TEXT_SECTIONS \
- darwin_function_switched_text_sections
-
#undef TARGET_ASM_SELECT_RTX_SECTION
#define TARGET_ASM_SELECT_RTX_SECTION machopic_select_rtx_section
#undef TARGET_ASM_UNIQUE_SECTION
diff --git a/gcc/config/darwin10.h b/gcc/config/darwin10.h
index d61eb40..df69429 100644
--- a/gcc/config/darwin10.h
+++ b/gcc/config/darwin10.h
@@ -25,10 +25,12 @@ along with GCC; see the file COPYING3. If not see
#undef LINK_GCC_C_SEQUENCE_SPEC
#define LINK_GCC_C_SEQUENCE_SPEC \
"%:version-compare(>= 10.6 mmacosx-version-min= -no_compact_unwind) \
- %{!static:%{!static-libgcc: \
- %:version-compare(>= 10.6 mmacosx-version-min= -lSystem) } } \
- %{fno-pic|fno-PIC|fno-pie|fno-PIE|fapple-kext|mkernel|static|mdynamic-no-pic: \
- %:version-compare(>= 10.7 mmacosx-version-min= -no_pie) } %G %{!nolibc:%L}"
+ %{!static:%{!static-libgcc: \
+ %:version-compare(>= 10.6 mmacosx-version-min= -lSystem) } } \
+ %{fno-pic|fno-PIC|fno-pie|fno-PIE|fapple-kext|mkernel|static|mdynamic-no-pic: \
+ %:version-compare(>= 10.7 mmacosx-version-min= -no_pie) } \
+ %{!nostdlib:%:version-compare(>< 10.6 10.7 mmacosx-version-min= -ld10-uwfef.o)} \
+ %G %{!nolibc:%L}"
#undef DEF_MIN_OSX_VERSION
#define DEF_MIN_OSX_VERSION "10.6"
diff --git a/gcc/config/darwin12.h b/gcc/config/darwin12.h
index e1e1eb0..adc9a78 100644
--- a/gcc/config/darwin12.h
+++ b/gcc/config/darwin12.h
@@ -18,14 +18,6 @@ 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/>. */
-#undef LINK_GCC_C_SEQUENCE_SPEC
-#define LINK_GCC_C_SEQUENCE_SPEC \
-"%:version-compare(>= 10.6 mmacosx-version-min= -no_compact_unwind) \
- %{!static:%{!static-libgcc: \
- %:version-compare(>= 10.6 mmacosx-version-min= -lSystem) } } \
- %{fno-pic|fno-PIC|fno-pie|fno-PIE|fapple-kext|mkernel|static|mdynamic-no-pic: \
- %:version-compare(>= 10.7 mmacosx-version-min= -no_pie) } %G %{!nolibc:%L}"
-
#undef DEF_MIN_OSX_VERSION
#define DEF_MIN_OSX_VERSION "10.8"
diff --git a/gcc/config/fr30/fr30.c b/gcc/config/fr30/fr30.c
index d49429b..9d8bc38 100644
--- a/gcc/config/fr30/fr30.c
+++ b/gcc/config/fr30/fr30.c
@@ -195,6 +195,9 @@ static int fr30_num_arg_regs (machine_mode, const_tree);
#undef TARGET_CONSTANT_ALIGNMENT
#define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
struct gcc_target targetm = TARGET_INITIALIZER;
diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c
index 6920e6d..f031bfa 100644
--- a/gcc/config/frv/frv.c
+++ b/gcc/config/frv/frv.c
@@ -528,6 +528,9 @@ static bool frv_modes_tieable_p (machine_mode, machine_mode);
#undef TARGET_CONSTANT_ALIGNMENT
#define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
struct gcc_target targetm = TARGET_INITIALIZER;
#define FRV_SYMBOL_REF_TLS_P(RTX) \
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index 01c765d..596f2fd 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -6148,4 +6148,7 @@ h8300_push_rounding (poly_int64 bytes)
#undef TARGET_MODE_DEPENDENT_ADDRESS_P
#define TARGET_MODE_DEPENDENT_ADDRESS_P h8300_mode_dependent_address_p
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
struct gcc_target targetm = TARGET_INITIALIZER;
diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index 1323657..5456564 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -78,10 +78,10 @@
"TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387 ? FP_SECOND_REG : NO_REGS"
"Second from top of 80387 floating-point stack (@code{%st(1)}).")
-(define_register_constraint "Yk" "TARGET_AVX512F ? MASK_EVEX_REGS : NO_REGS"
+(define_register_constraint "Yk" "TARGET_AVX512F ? MASK_REGS : NO_REGS"
"@internal Any mask register that can be used as predicate, i.e. k1-k7.")
-(define_register_constraint "k" "TARGET_AVX512F ? MASK_REGS : NO_REGS"
+(define_register_constraint "k" "TARGET_AVX512F ? ALL_MASK_REGS : NO_REGS"
"@internal Any mask register.")
;; Vector registers (also used for plain floating point nowadays).
@@ -146,9 +146,6 @@
"TARGET_AVX512VL ? ALL_SSE_REGS : TARGET_SSE ? SSE_REGS : NO_REGS"
"@internal For AVX512VL, any EVEX encodable SSE register (@code{%xmm0-%xmm31}), otherwise any SSE register.")
-(define_register_constraint "Yh" "TARGET_AVX512F ? MOD4_SSE_REGS : NO_REGS"
- "@internal Any EVEX encodable SSE register, which has number factor of four.")
-
;; We use the B prefix to denote any number of internal operands:
;; f FLAGS_REG
;; g GOT memory operand.
diff --git a/gcc/config/i386/djgpp.c b/gcc/config/i386/djgpp.c
index f168eed..d187c3a 100644
--- a/gcc/config/i386/djgpp.c
+++ b/gcc/config/i386/djgpp.c
@@ -47,3 +47,20 @@ i386_djgpp_asm_named_section(const char *name, unsigned int flags,
fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars);
}
+
+/* Kludge because of missing COFF support for early LTO debug. */
+
+static enum debug_info_levels saved_debug_info_level;
+
+void
+i386_djgpp_asm_lto_start (void)
+{
+ saved_debug_info_level = debug_info_level;
+ debug_info_level = DINFO_LEVEL_NONE;
+}
+
+void
+i386_djgpp_asm_lto_end (void)
+{
+ debug_info_level = saved_debug_info_level;
+}
diff --git a/gcc/config/i386/djgpp.h b/gcc/config/i386/djgpp.h
index 01774ce..dd8c71b 100644
--- a/gcc/config/i386/djgpp.h
+++ b/gcc/config/i386/djgpp.h
@@ -157,8 +157,19 @@ along with GCC; see the file COPYING3. If not see
#undef MAKE_DECL_ONE_ONLY
#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
+#undef TARGET_COFF
+#define TARGET_COFF 1
+
+/* Kludge because of missing COFF support for early LTO debug. */
+#undef TARGET_ASM_LTO_START
+#define TARGET_ASM_LTO_START i386_djgpp_asm_lto_start
+#undef TARGET_ASM_LTO_END
+#define TARGET_ASM_LTO_END i386_djgpp_asm_lto_end
+
/* Function protypes for gcc/i386/djgpp.c */
void
i386_djgpp_asm_named_section(const char *name, unsigned int flags,
tree decl);
+void i386_djgpp_asm_lto_start (void);
+void i386_djgpp_asm_lto_end (void);
diff --git a/gcc/config/i386/emmintrin.h b/gcc/config/i386/emmintrin.h
index b940a39..7a6ff80 100644
--- a/gcc/config/i386/emmintrin.h
+++ b/gcc/config/i386/emmintrin.h
@@ -113,7 +113,7 @@ _mm_setzero_pd (void)
extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_move_sd (__m128d __A, __m128d __B)
{
- return (__m128d) __builtin_ia32_movsd ((__v2df)__A, (__v2df)__B);
+ return __extension__ (__m128d) __builtin_shuffle ((__v2df)__A, (__v2df)__B, (__v2di){2, 1});
}
/* Load two DPFP values from P. The address must be 16-byte aligned. */
diff --git a/gcc/config/i386/i386-modes.def b/gcc/config/i386/i386-modes.def
index 08c79a5..12c17ce 100644
--- a/gcc/config/i386/i386-modes.def
+++ b/gcc/config/i386/i386-modes.def
@@ -98,9 +98,6 @@ VECTOR_MODE (INT, QI, 14); /* V14QI */
VECTOR_MODE (INT, HI, 6); /* V6HI */
VECTOR_MODE (INT, SI, 64); /* V64SI */
-POINTER_BOUNDS_MODE (BND32, 8);
-POINTER_BOUNDS_MODE (BND64, 16);
-
INT_MODE (OI, 32);
INT_MODE (XI, 64);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index ee409cf..052ca63 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -75,7 +75,6 @@ along with GCC; see the file COPYING3. If not see
#include "tree-iterator.h"
#include "dbgcnt.h"
#include "case-cfn-macros.h"
-#include "regrename.h"
#include "dojump.h"
#include "fold-const-call.h"
#include "tree-vrp.h"
@@ -245,25 +244,25 @@ enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER] =
/* flags, fpsr, fpcr, frame */
NO_REGS, NO_REGS, NO_REGS, NON_Q_REGS,
/* SSE registers */
- SSE_FIRST_REG, SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS,
- SSE_REGS, SSE_REGS,
+ SSE_FIRST_REG, SSE_REGS, SSE_REGS, SSE_REGS,
+ SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS,
/* MMX registers */
- MMX_REGS, MMX_REGS, MMX_REGS, MMX_REGS, MMX_REGS, MMX_REGS,
- MMX_REGS, MMX_REGS,
+ MMX_REGS, MMX_REGS, MMX_REGS, MMX_REGS,
+ MMX_REGS, MMX_REGS, MMX_REGS, MMX_REGS,
/* REX registers */
- NON_Q_REGS, NON_Q_REGS, NON_Q_REGS, NON_Q_REGS,
- NON_Q_REGS, NON_Q_REGS, NON_Q_REGS, NON_Q_REGS,
+ GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
+ GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
/* SSE REX registers */
- SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS,
- SSE_REGS, SSE_REGS,
+ SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS,
+ SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS,
/* AVX-512 SSE registers */
- EVEX_SSE_REGS, EVEX_SSE_REGS, EVEX_SSE_REGS, EVEX_SSE_REGS,
- EVEX_SSE_REGS, EVEX_SSE_REGS, EVEX_SSE_REGS, EVEX_SSE_REGS,
- EVEX_SSE_REGS, EVEX_SSE_REGS, EVEX_SSE_REGS, EVEX_SSE_REGS,
- EVEX_SSE_REGS, EVEX_SSE_REGS, EVEX_SSE_REGS, EVEX_SSE_REGS,
+ ALL_SSE_REGS, ALL_SSE_REGS, ALL_SSE_REGS, ALL_SSE_REGS,
+ ALL_SSE_REGS, ALL_SSE_REGS, ALL_SSE_REGS, ALL_SSE_REGS,
+ ALL_SSE_REGS, ALL_SSE_REGS, ALL_SSE_REGS, ALL_SSE_REGS,
+ ALL_SSE_REGS, ALL_SSE_REGS, ALL_SSE_REGS, ALL_SSE_REGS,
/* Mask registers. */
- MASK_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS,
- MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS,
+ ALL_MASK_REGS, MASK_REGS, MASK_REGS, MASK_REGS,
+ MASK_REGS, MASK_REGS, MASK_REGS, MASK_REGS
};
/* The "default" register map used in 32bit mode. */
@@ -279,8 +278,7 @@ int const dbx_register_map[FIRST_PSEUDO_REGISTER] =
-1, -1, -1, -1, -1, -1, -1, -1, /* extended SSE registers */
-1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 16-23*/
-1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 24-31*/
- 93, 94, 95, 96, 97, 98, 99, 100, /* Mask registers */
- 101, 102, 103, 104, /* bound registers */
+ 93, 94, 95, 96, 97, 98, 99, 100 /* Mask registers */
};
/* The "default" register map used in 64bit mode. */
@@ -296,8 +294,7 @@ int const dbx64_register_map[FIRST_PSEUDO_REGISTER] =
25, 26, 27, 28, 29, 30, 31, 32, /* extended SSE registers */
67, 68, 69, 70, 71, 72, 73, 74, /* AVX-512 registers 16-23 */
75, 76, 77, 78, 79, 80, 81, 82, /* AVX-512 registers 24-31 */
- 118, 119, 120, 121, 122, 123, 124, 125, /* Mask registers */
- 126, 127, 128, 129, /* bound registers */
+ 118, 119, 120, 121, 122, 123, 124, 125 /* Mask registers */
};
/* Define the register numbers to be used in Dwarf debugging information.
@@ -365,8 +362,7 @@ int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER] =
-1, -1, -1, -1, -1, -1, -1, -1, /* extended SSE registers */
-1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 16-23*/
-1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 24-31*/
- 93, 94, 95, 96, 97, 98, 99, 100, /* Mask registers */
- 101, 102, 103, 104, /* bound registers */
+ 93, 94, 95, 96, 97, 98, 99, 100 /* Mask registers */
};
/* Define parameter passing and return registers. */
@@ -832,63 +828,46 @@ static tree (*ix86_veclib_handler) (combined_fn, tree, tree);
static tree ix86_veclibabi_svml (combined_fn, tree, tree);
static tree ix86_veclibabi_acml (combined_fn, tree, tree);
-/* Processor target table, indexed by processor number */
-struct ptt
-{
- const char *const name; /* processor name */
- const struct processor_costs *cost; /* Processor costs */
-
- /* Default alignments. */
- const char *const align_loop;
- const char *const align_jump;
- const char *const align_label;
- const char *const align_func;
-};
-
/* This table must be in sync with enum processor_type in i386.h. */
-static const struct ptt processor_target_table[PROCESSOR_max] =
-{
-/* The "0:0:8" label alignment specified for some processors generates
- secondary 8-byte alignment only for those label/jump/loop targets
- which have primary alignment. */
-
- {"generic", &generic_cost, "16:11:8", "16:11:8", "0:0:8", "16"},
- {"i386", &i386_cost, "4", "4", NULL, "4" },
- {"i486", &i486_cost, "16", "16", "0:0:8", "16"},
- {"pentium", &pentium_cost, "16:8:8", "16:8:8", "0:0:8", "16"},
- {"lakemont", &lakemont_cost, "16:8:8", "16:8:8", "0:0:8", "16"},
- {"pentiumpro", &pentiumpro_cost, "16", "16:11:8", "0:0:8", "16"},
- {"pentium4", &pentium4_cost, NULL, NULL, NULL, NULL},
- {"nocona", &nocona_cost, NULL, NULL, NULL, NULL},
- {"core2", &core_cost, "16:11:8", "16:11:8", "0:0:8", "16"},
- {"nehalem", &core_cost, "16:11:8", "16:11:8", "0:0:8", "16"},
- {"sandybridge", &core_cost, "16:11:8", "16:11:8", "0:0:8", "16"},
- {"haswell", &core_cost, "16:11:8", "16:11:8", "0:0:8", "16"},
- {"bonnell", &atom_cost, "16", "16:8:8", "0:0:8", "16"},
- {"silvermont", &slm_cost, "16", "16:8:8", "0:0:8", "16"},
- {"goldmont", &slm_cost, "16", "16:8:8", "0:0:8", "16"},
- {"goldmont-plus", &slm_cost, "16", "16:8:8", "0:0:8", "16"},
- {"tremont", &slm_cost, "16", "16:8:8", "0:0:8", "16"},
- {"knl", &slm_cost, "16", "16:8:8", "0:0:8", "16"},
- {"knm", &slm_cost, "16", "16:8:8", "0:0:8", "16"},
- {"skylake", &skylake_cost, "16:11:8", "16:11:8", "0:0:8", "16"},
- {"skylake-avx512", &skylake_cost, "16:11:8", "16:11:8", "0:0:8", "16"},
- {"cannonlake", &skylake_cost, "16:11:8", "16:11:8", "0:0:8", "16"},
- {"icelake-client", &skylake_cost, "16:11:8", "16:11:8", "0:0:8", "16"},
- {"icelake-server", &skylake_cost, "16:11:8", "16:11:8", "0:0:8", "16"},
- {"intel", &intel_cost, "16", "16:8:8", "0:0:8", "16"},
- {"geode", &geode_cost, NULL, NULL, NULL, NULL},
- {"k6", &k6_cost, "32:8:8", "32:8:8", "0:0:8", "32"},
- {"athlon", &athlon_cost, "16:8:8", "16:8:8", "0:0:8", "16"},
- {"k8", &k8_cost, "16:8:8", "16:8:8", "0:0:8", "16"},
- {"amdfam10", &amdfam10_cost, "32:25:8", "32:8:8", "0:0:8", "32"},
- {"bdver1", &bdver1_cost, "16:11:8", "16:8:8", "0:0:8", "11"},
- {"bdver2", &bdver2_cost, "16:11:8", "16:8:8", "0:0:8", "11"},
- {"bdver3", &bdver3_cost, "16:11:8", "16:8:8", "0:0:8", "11"},
- {"bdver4", &bdver4_cost, "16:11:8", "16:8:8", "0:0:8", "11"},
- {"btver1", &btver1_cost, "16:11:8", "16:8:8", "0:0:8", "11"},
- {"btver2", &btver2_cost, "16:11:8", "16:8:8", "0:0:8", "11"},
- {"znver1", &znver1_cost, "16", "16", "0:0:8", "16"}
+static const struct processor_costs *processor_cost_table[PROCESSOR_max] =
+{
+ &generic_cost,
+ &i386_cost,
+ &i486_cost,
+ &pentium_cost,
+ &lakemont_cost,
+ &pentiumpro_cost,
+ &pentium4_cost,
+ &nocona_cost,
+ &core_cost,
+ &core_cost,
+ &core_cost,
+ &core_cost,
+ &atom_cost,
+ &slm_cost,
+ &slm_cost,
+ &slm_cost,
+ &slm_cost,
+ &slm_cost,
+ &slm_cost,
+ &skylake_cost,
+ &skylake_cost,
+ &skylake_cost,
+ &skylake_cost,
+ &skylake_cost,
+ &intel_cost,
+ &geode_cost,
+ &k6_cost,
+ &athlon_cost,
+ &k8_cost,
+ &amdfam10_cost,
+ &bdver1_cost,
+ &bdver2_cost,
+ &bdver3_cost,
+ &bdver4_cost,
+ &btver1_cost,
+ &btver2_cost,
+ &znver1_cost,
};
static unsigned int
@@ -2614,11 +2593,17 @@ rest_of_insert_endbranch (void)
TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl)))
&& !cgraph_node::get (cfun->decl)->only_called_directly_p ())
{
- cet_eb = gen_nop_endbr ();
+ /* Queue ENDBR insertion to x86_function_profiler. */
+ if (crtl->profile && flag_fentry)
+ cfun->machine->endbr_queued_at_entrance = true;
+ else
+ {
+ cet_eb = gen_nop_endbr ();
- bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
- insn = BB_HEAD (bb);
- emit_insn_before (cet_eb, insn);
+ bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
+ insn = BB_HEAD (bb);
+ emit_insn_before (cet_eb, insn);
+ }
}
bb = 0;
@@ -3135,15 +3120,6 @@ ix86_debug_options (void)
return;
}
-/* Return true if T is one of the bytes we should avoid with
- -mmitigate-rop. */
-
-static bool
-ix86_rop_should_change_byte_p (int t)
-{
- return t == 0xc2 || t == 0xc3 || t == 0xca || t == 0xcb;
-}
-
static const char *stringop_alg_names[] = {
#define DEF_ENUM
#define DEF_ALG(alg, name) #name,
@@ -3382,13 +3358,13 @@ ix86_default_align (struct gcc_options *opts)
{
/* -falign-foo without argument: supply one. */
if (opts->x_flag_align_loops && !opts->x_str_align_loops)
- opts->x_str_align_loops = processor_target_table[ix86_tune].align_loop;
+ opts->x_str_align_loops = processor_cost_table[ix86_tune]->align_loop;
if (opts->x_flag_align_jumps && !opts->x_str_align_jumps)
- opts->x_str_align_jumps = processor_target_table[ix86_tune].align_jump;
+ opts->x_str_align_jumps = processor_cost_table[ix86_tune]->align_jump;
if (opts->x_flag_align_labels && !opts->x_str_align_labels)
- opts->x_str_align_labels = processor_target_table[ix86_tune].align_label;
+ opts->x_str_align_labels = processor_cost_table[ix86_tune]->align_label;
if (opts->x_flag_align_functions && !opts->x_str_align_functions)
- opts->x_str_align_functions = processor_target_table[ix86_tune].align_func;
+ opts->x_str_align_functions = processor_cost_table[ix86_tune]->align_func;
}
/* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE hook. */
@@ -3399,6 +3375,8 @@ ix86_override_options_after_change (void)
ix86_default_align (&global_options);
}
+
+
/* Override various settings based on options. If MAIN_ARGS_P, the
options are from the command line, otherwise they are from
attributes. Return true if there's an error related to march
@@ -3413,317 +3391,6 @@ ix86_option_override_internal (bool main_args_p,
unsigned HOST_WIDE_INT ix86_arch_mask;
const bool ix86_tune_specified = (opts->x_ix86_tune_string != NULL);
- const wide_int_bitmask PTA_3DNOW (HOST_WIDE_INT_1U << 0);
- const wide_int_bitmask PTA_3DNOW_A (HOST_WIDE_INT_1U << 1);
- const wide_int_bitmask PTA_64BIT (HOST_WIDE_INT_1U << 2);
- const wide_int_bitmask PTA_ABM (HOST_WIDE_INT_1U << 3);
- const wide_int_bitmask PTA_AES (HOST_WIDE_INT_1U << 4);
- const wide_int_bitmask PTA_AVX (HOST_WIDE_INT_1U << 5);
- const wide_int_bitmask PTA_BMI (HOST_WIDE_INT_1U << 6);
- const wide_int_bitmask PTA_CX16 (HOST_WIDE_INT_1U << 7);
- const wide_int_bitmask PTA_F16C (HOST_WIDE_INT_1U << 8);
- const wide_int_bitmask PTA_FMA (HOST_WIDE_INT_1U << 9);
- const wide_int_bitmask PTA_FMA4 (HOST_WIDE_INT_1U << 10);
- const wide_int_bitmask PTA_FSGSBASE (HOST_WIDE_INT_1U << 11);
- const wide_int_bitmask PTA_LWP (HOST_WIDE_INT_1U << 12);
- const wide_int_bitmask PTA_LZCNT (HOST_WIDE_INT_1U << 13);
- const wide_int_bitmask PTA_MMX (HOST_WIDE_INT_1U << 14);
- const wide_int_bitmask PTA_MOVBE (HOST_WIDE_INT_1U << 15);
- const wide_int_bitmask PTA_NO_SAHF (HOST_WIDE_INT_1U << 16);
- const wide_int_bitmask PTA_PCLMUL (HOST_WIDE_INT_1U << 17);
- const wide_int_bitmask PTA_POPCNT (HOST_WIDE_INT_1U << 18);
- const wide_int_bitmask PTA_PREFETCH_SSE (HOST_WIDE_INT_1U << 19);
- const wide_int_bitmask PTA_RDRND (HOST_WIDE_INT_1U << 20);
- const wide_int_bitmask PTA_SSE (HOST_WIDE_INT_1U << 21);
- const wide_int_bitmask PTA_SSE2 (HOST_WIDE_INT_1U << 22);
- const wide_int_bitmask PTA_SSE3 (HOST_WIDE_INT_1U << 23);
- const wide_int_bitmask PTA_SSE4_1 (HOST_WIDE_INT_1U << 24);
- const wide_int_bitmask PTA_SSE4_2 (HOST_WIDE_INT_1U << 25);
- const wide_int_bitmask PTA_SSE4A (HOST_WIDE_INT_1U << 26);
- const wide_int_bitmask PTA_SSSE3 (HOST_WIDE_INT_1U << 27);
- const wide_int_bitmask PTA_TBM (HOST_WIDE_INT_1U << 28);
- const wide_int_bitmask PTA_XOP (HOST_WIDE_INT_1U << 29);
- const wide_int_bitmask PTA_AVX2 (HOST_WIDE_INT_1U << 30);
- const wide_int_bitmask PTA_BMI2 (HOST_WIDE_INT_1U << 31);
- const wide_int_bitmask PTA_RTM (HOST_WIDE_INT_1U << 32);
- const wide_int_bitmask PTA_HLE (HOST_WIDE_INT_1U << 33);
- const wide_int_bitmask PTA_PRFCHW (HOST_WIDE_INT_1U << 34);
- const wide_int_bitmask PTA_RDSEED (HOST_WIDE_INT_1U << 35);
- const wide_int_bitmask PTA_ADX (HOST_WIDE_INT_1U << 36);
- const wide_int_bitmask PTA_FXSR (HOST_WIDE_INT_1U << 37);
- const wide_int_bitmask PTA_XSAVE (HOST_WIDE_INT_1U << 38);
- const wide_int_bitmask PTA_XSAVEOPT (HOST_WIDE_INT_1U << 39);
- const wide_int_bitmask PTA_AVX512F (HOST_WIDE_INT_1U << 40);
- const wide_int_bitmask PTA_AVX512ER (HOST_WIDE_INT_1U << 41);
- const wide_int_bitmask PTA_AVX512PF (HOST_WIDE_INT_1U << 42);
- const wide_int_bitmask PTA_AVX512CD (HOST_WIDE_INT_1U << 43);
- /* Hole after PTA_MPX was removed. */
- const wide_int_bitmask PTA_SHA (HOST_WIDE_INT_1U << 45);
- const wide_int_bitmask PTA_PREFETCHWT1 (HOST_WIDE_INT_1U << 46);
- const wide_int_bitmask PTA_CLFLUSHOPT (HOST_WIDE_INT_1U << 47);
- const wide_int_bitmask PTA_XSAVEC (HOST_WIDE_INT_1U << 48);
- const wide_int_bitmask PTA_XSAVES (HOST_WIDE_INT_1U << 49);
- const wide_int_bitmask PTA_AVX512DQ (HOST_WIDE_INT_1U << 50);
- const wide_int_bitmask PTA_AVX512BW (HOST_WIDE_INT_1U << 51);
- const wide_int_bitmask PTA_AVX512VL (HOST_WIDE_INT_1U << 52);
- const wide_int_bitmask PTA_AVX512IFMA (HOST_WIDE_INT_1U << 53);
- const wide_int_bitmask PTA_AVX512VBMI (HOST_WIDE_INT_1U << 54);
- const wide_int_bitmask PTA_CLWB (HOST_WIDE_INT_1U << 55);
- const wide_int_bitmask PTA_MWAITX (HOST_WIDE_INT_1U << 56);
- const wide_int_bitmask PTA_CLZERO (HOST_WIDE_INT_1U << 57);
- const wide_int_bitmask PTA_NO_80387 (HOST_WIDE_INT_1U << 58);
- const wide_int_bitmask PTA_PKU (HOST_WIDE_INT_1U << 59);
- const wide_int_bitmask PTA_AVX5124VNNIW (HOST_WIDE_INT_1U << 60);
- const wide_int_bitmask PTA_AVX5124FMAPS (HOST_WIDE_INT_1U << 61);
- const wide_int_bitmask PTA_AVX512VPOPCNTDQ (HOST_WIDE_INT_1U << 62);
- const wide_int_bitmask PTA_SGX (HOST_WIDE_INT_1U << 63);
- const wide_int_bitmask PTA_AVX512VNNI (0, HOST_WIDE_INT_1U);
- const wide_int_bitmask PTA_GFNI (0, HOST_WIDE_INT_1U << 1);
- const wide_int_bitmask PTA_VAES (0, HOST_WIDE_INT_1U << 2);
- const wide_int_bitmask PTA_AVX512VBMI2 (0, HOST_WIDE_INT_1U << 3);
- const wide_int_bitmask PTA_VPCLMULQDQ (0, HOST_WIDE_INT_1U << 4);
- const wide_int_bitmask PTA_AVX512BITALG (0, HOST_WIDE_INT_1U << 5);
- const wide_int_bitmask PTA_RDPID (0, HOST_WIDE_INT_1U << 6);
- const wide_int_bitmask PTA_PCONFIG (0, HOST_WIDE_INT_1U << 7);
- const wide_int_bitmask PTA_WBNOINVD (0, HOST_WIDE_INT_1U << 8);
- const wide_int_bitmask PTA_WAITPKG (0, HOST_WIDE_INT_1U << 9);
-
- const wide_int_bitmask PTA_CORE2 = PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2
- | PTA_SSE3 | PTA_SSSE3 | PTA_CX16 | PTA_FXSR;
- const wide_int_bitmask PTA_NEHALEM = PTA_CORE2 | PTA_SSE4_1 | PTA_SSE4_2
- | PTA_POPCNT;
- const wide_int_bitmask PTA_WESTMERE = PTA_NEHALEM | PTA_AES | PTA_PCLMUL;
- const wide_int_bitmask PTA_SANDYBRIDGE = PTA_WESTMERE | PTA_AVX | PTA_XSAVE
- | PTA_XSAVEOPT;
- const wide_int_bitmask PTA_IVYBRIDGE = PTA_SANDYBRIDGE | PTA_FSGSBASE
- | PTA_RDRND | PTA_F16C;
- const wide_int_bitmask PTA_HASWELL = PTA_IVYBRIDGE | PTA_AVX2 | PTA_BMI
- | PTA_BMI2 | PTA_LZCNT | PTA_FMA | PTA_MOVBE | PTA_HLE;
- const wide_int_bitmask PTA_BROADWELL = PTA_HASWELL | PTA_ADX | PTA_PRFCHW
- | PTA_RDSEED;
- const wide_int_bitmask PTA_SKYLAKE = PTA_BROADWELL | PTA_CLFLUSHOPT
- | PTA_XSAVEC | PTA_XSAVES | PTA_SGX;
- const wide_int_bitmask PTA_SKYLAKE_AVX512 = PTA_SKYLAKE | PTA_AVX512F
- | PTA_AVX512CD | PTA_AVX512VL | PTA_AVX512BW | PTA_AVX512DQ | PTA_PKU
- | PTA_CLWB;
- const wide_int_bitmask PTA_CANNONLAKE = PTA_SKYLAKE | PTA_AVX512F
- | PTA_AVX512CD | PTA_AVX512VL | PTA_AVX512BW | PTA_AVX512DQ | PTA_PKU
- | PTA_AVX512VBMI | PTA_AVX512IFMA | PTA_SHA;
- const wide_int_bitmask PTA_ICELAKE_CLIENT = PTA_CANNONLAKE | PTA_AVX512VNNI
- | PTA_GFNI | PTA_VAES | PTA_AVX512VBMI2 | PTA_VPCLMULQDQ | PTA_AVX512BITALG
- | PTA_RDPID | PTA_CLWB;
- const wide_int_bitmask PTA_ICELAKE_SERVER = PTA_ICELAKE_CLIENT | PTA_PCONFIG
- | PTA_WBNOINVD;
- const wide_int_bitmask PTA_KNL = PTA_BROADWELL | PTA_AVX512PF | PTA_AVX512ER
- | PTA_AVX512F | PTA_AVX512CD;
- const wide_int_bitmask PTA_BONNELL = PTA_CORE2 | PTA_MOVBE;
- const wide_int_bitmask PTA_SILVERMONT = PTA_WESTMERE | PTA_MOVBE | PTA_RDRND;
- const wide_int_bitmask PTA_GOLDMONT = PTA_SILVERMONT | PTA_SHA | PTA_XSAVE
- | PTA_RDSEED | PTA_XSAVEC | PTA_XSAVES | PTA_CLFLUSHOPT | PTA_XSAVEOPT
- | PTA_FSGSBASE;
- const wide_int_bitmask PTA_GOLDMONT_PLUS = PTA_GOLDMONT | PTA_RDPID
- | PTA_SGX;
- const wide_int_bitmask PTA_TREMONT = PTA_GOLDMONT_PLUS | PTA_CLWB
- | PTA_GFNI;
- const wide_int_bitmask PTA_KNM = PTA_KNL | PTA_AVX5124VNNIW
- | PTA_AVX5124FMAPS | PTA_AVX512VPOPCNTDQ;
-
- static struct pta
- {
- const char *const name; /* processor name or nickname. */
- const enum processor_type processor;
- const enum attr_cpu schedule;
- const wide_int_bitmask flags;
- }
- const processor_alias_table[] =
- {
- {"i386", PROCESSOR_I386, CPU_NONE, 0},
- {"i486", PROCESSOR_I486, CPU_NONE, 0},
- {"i586", PROCESSOR_PENTIUM, CPU_PENTIUM, 0},
- {"pentium", PROCESSOR_PENTIUM, CPU_PENTIUM, 0},
- {"lakemont", PROCESSOR_LAKEMONT, CPU_PENTIUM, PTA_NO_80387},
- {"pentium-mmx", PROCESSOR_PENTIUM, CPU_PENTIUM, PTA_MMX},
- {"winchip-c6", PROCESSOR_I486, CPU_NONE, PTA_MMX},
- {"winchip2", PROCESSOR_I486, CPU_NONE, PTA_MMX | PTA_3DNOW},
- {"c3", PROCESSOR_I486, CPU_NONE, PTA_MMX | PTA_3DNOW},
- {"samuel-2", PROCESSOR_I486, CPU_NONE, PTA_MMX | PTA_3DNOW},
- {"c3-2", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO,
- PTA_MMX | PTA_SSE | PTA_FXSR},
- {"nehemiah", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO,
- PTA_MMX | PTA_SSE | PTA_FXSR},
- {"c7", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO,
- PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_FXSR},
- {"esther", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO,
- PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_FXSR},
- {"i686", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, 0},
- {"pentiumpro", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, 0},
- {"pentium2", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, PTA_MMX | PTA_FXSR},
- {"pentium3", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO,
- PTA_MMX | PTA_SSE | PTA_FXSR},
- {"pentium3m", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO,
- PTA_MMX | PTA_SSE | PTA_FXSR},
- {"pentium-m", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO,
- PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_FXSR},
- {"pentium4", PROCESSOR_PENTIUM4, CPU_NONE,
- PTA_MMX |PTA_SSE | PTA_SSE2 | PTA_FXSR},
- {"pentium4m", PROCESSOR_PENTIUM4, CPU_NONE,
- PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_FXSR},
- {"prescott", PROCESSOR_NOCONA, CPU_NONE,
- PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_FXSR},
- {"nocona", PROCESSOR_NOCONA, CPU_NONE,
- PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
- | PTA_CX16 | PTA_NO_SAHF | PTA_FXSR},
- {"core2", PROCESSOR_CORE2, CPU_CORE2, PTA_CORE2},
- {"nehalem", PROCESSOR_NEHALEM, CPU_NEHALEM, PTA_NEHALEM},
- {"corei7", PROCESSOR_NEHALEM, CPU_NEHALEM, PTA_NEHALEM},
- {"westmere", PROCESSOR_NEHALEM, CPU_NEHALEM, PTA_WESTMERE},
- {"sandybridge", PROCESSOR_SANDYBRIDGE, CPU_NEHALEM,
- PTA_SANDYBRIDGE},
- {"corei7-avx", PROCESSOR_SANDYBRIDGE, CPU_NEHALEM,
- PTA_SANDYBRIDGE},
- {"ivybridge", PROCESSOR_SANDYBRIDGE, CPU_NEHALEM,
- PTA_IVYBRIDGE},
- {"core-avx-i", PROCESSOR_SANDYBRIDGE, CPU_NEHALEM,
- PTA_IVYBRIDGE},
- {"haswell", PROCESSOR_HASWELL, CPU_HASWELL, PTA_HASWELL},
- {"core-avx2", PROCESSOR_HASWELL, CPU_HASWELL, PTA_HASWELL},
- {"broadwell", PROCESSOR_HASWELL, CPU_HASWELL, PTA_BROADWELL},
- {"skylake", PROCESSOR_SKYLAKE, CPU_HASWELL, PTA_SKYLAKE},
- {"skylake-avx512", PROCESSOR_SKYLAKE_AVX512, CPU_HASWELL,
- PTA_SKYLAKE_AVX512},
- {"cannonlake", PROCESSOR_CANNONLAKE, CPU_HASWELL, PTA_CANNONLAKE},
- {"icelake-client", PROCESSOR_ICELAKE_CLIENT, CPU_HASWELL,
- PTA_ICELAKE_CLIENT},
- {"icelake-server", PROCESSOR_ICELAKE_SERVER, CPU_HASWELL,
- PTA_ICELAKE_SERVER},
- {"bonnell", PROCESSOR_BONNELL, CPU_ATOM, PTA_BONNELL},
- {"atom", PROCESSOR_BONNELL, CPU_ATOM, PTA_BONNELL},
- {"silvermont", PROCESSOR_SILVERMONT, CPU_SLM, PTA_SILVERMONT},
- {"slm", PROCESSOR_SILVERMONT, CPU_SLM, PTA_SILVERMONT},
- {"goldmont", PROCESSOR_GOLDMONT, CPU_GLM, PTA_GOLDMONT},
- {"goldmont-plus", PROCESSOR_GOLDMONT_PLUS, CPU_GLM, PTA_GOLDMONT_PLUS},
- {"tremont", PROCESSOR_TREMONT, CPU_GLM, PTA_TREMONT},
- {"knl", PROCESSOR_KNL, CPU_SLM, PTA_KNL},
- {"knm", PROCESSOR_KNM, CPU_SLM, PTA_KNM},
- {"intel", PROCESSOR_INTEL, CPU_SLM, PTA_NEHALEM},
- {"geode", PROCESSOR_GEODE, CPU_GEODE,
- PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_PREFETCH_SSE},
- {"k6", PROCESSOR_K6, CPU_K6, PTA_MMX},
- {"k6-2", PROCESSOR_K6, CPU_K6, PTA_MMX | PTA_3DNOW},
- {"k6-3", PROCESSOR_K6, CPU_K6, PTA_MMX | PTA_3DNOW},
- {"athlon", PROCESSOR_ATHLON, CPU_ATHLON,
- PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_PREFETCH_SSE},
- {"athlon-tbird", PROCESSOR_ATHLON, CPU_ATHLON,
- PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_PREFETCH_SSE},
- {"athlon-4", PROCESSOR_ATHLON, CPU_ATHLON,
- PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE | PTA_FXSR},
- {"athlon-xp", PROCESSOR_ATHLON, CPU_ATHLON,
- PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE | PTA_FXSR},
- {"athlon-mp", PROCESSOR_ATHLON, CPU_ATHLON,
- PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE | PTA_FXSR},
- {"x86-64", PROCESSOR_K8, CPU_K8,
- PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_NO_SAHF | PTA_FXSR},
- {"eden-x2", PROCESSOR_K8, CPU_K8,
- PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_FXSR},
- {"nano", PROCESSOR_K8, CPU_K8,
- PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
- | PTA_SSSE3 | PTA_FXSR},
- {"nano-1000", PROCESSOR_K8, CPU_K8,
- PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
- | PTA_SSSE3 | PTA_FXSR},
- {"nano-2000", PROCESSOR_K8, CPU_K8,
- PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
- | PTA_SSSE3 | PTA_FXSR},
- {"nano-3000", PROCESSOR_K8, CPU_K8,
- PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
- | PTA_SSSE3 | PTA_SSE4_1 | PTA_FXSR},
- {"nano-x2", PROCESSOR_K8, CPU_K8,
- PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
- | PTA_SSSE3 | PTA_SSE4_1 | PTA_FXSR},
- {"eden-x4", PROCESSOR_K8, CPU_K8,
- PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
- | PTA_SSSE3 | PTA_SSE4_1 | PTA_FXSR},
- {"nano-x4", PROCESSOR_K8, CPU_K8,
- PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
- | PTA_SSSE3 | PTA_SSE4_1 | PTA_FXSR},
- {"k8", PROCESSOR_K8, CPU_K8,
- PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE
- | PTA_SSE2 | PTA_NO_SAHF | PTA_FXSR},
- {"k8-sse3", PROCESSOR_K8, CPU_K8,
- PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE
- | PTA_SSE2 | PTA_SSE3 | PTA_NO_SAHF | PTA_FXSR},
- {"opteron", PROCESSOR_K8, CPU_K8,
- PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE
- | PTA_SSE2 | PTA_NO_SAHF | PTA_FXSR},
- {"opteron-sse3", PROCESSOR_K8, CPU_K8,
- PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE
- | PTA_SSE2 | PTA_SSE3 | PTA_NO_SAHF | PTA_FXSR},
- {"athlon64", PROCESSOR_K8, CPU_K8,
- PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE
- | PTA_SSE2 | PTA_NO_SAHF | PTA_FXSR},
- {"athlon64-sse3", PROCESSOR_K8, CPU_K8,
- PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE
- | PTA_SSE2 | PTA_SSE3 | PTA_NO_SAHF | PTA_FXSR},
- {"athlon-fx", PROCESSOR_K8, CPU_K8,
- PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE
- | PTA_SSE2 | PTA_NO_SAHF | PTA_FXSR},
- {"amdfam10", PROCESSOR_AMDFAM10, CPU_AMDFAM10,
- PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE | PTA_SSE2
- | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_PRFCHW | PTA_FXSR},
- {"barcelona", PROCESSOR_AMDFAM10, CPU_AMDFAM10,
- PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE | PTA_SSE2
- | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_PRFCHW | PTA_FXSR},
- {"bdver1", PROCESSOR_BDVER1, CPU_BDVER1,
- PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
- | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1
- | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_FMA4
- | PTA_XOP | PTA_LWP | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE},
- {"bdver2", PROCESSOR_BDVER2, CPU_BDVER2,
- PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
- | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1
- | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_FMA4
- | PTA_XOP | PTA_LWP | PTA_BMI | PTA_TBM | PTA_F16C
- | PTA_FMA | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE},
- {"bdver3", PROCESSOR_BDVER3, CPU_BDVER3,
- PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
- | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1
- | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_FMA4
- | PTA_XOP | PTA_LWP | PTA_BMI | PTA_TBM | PTA_F16C
- | PTA_FMA | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE
- | PTA_XSAVEOPT | PTA_FSGSBASE},
- {"bdver4", PROCESSOR_BDVER4, CPU_BDVER4,
- PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
- | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1
- | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_AVX2
- | PTA_FMA4 | PTA_XOP | PTA_LWP | PTA_BMI | PTA_BMI2
- | PTA_TBM | PTA_F16C | PTA_FMA | PTA_PRFCHW | PTA_FXSR
- | PTA_XSAVE | PTA_XSAVEOPT | PTA_FSGSBASE | PTA_RDRND
- | PTA_MOVBE | PTA_MWAITX},
- {"znver1", PROCESSOR_ZNVER1, CPU_ZNVER1,
- PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
- | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1
- | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_AVX2
- | PTA_BMI | PTA_BMI2 | PTA_F16C | PTA_FMA | PTA_PRFCHW
- | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT | PTA_FSGSBASE
- | PTA_RDRND | PTA_MOVBE | PTA_MWAITX | PTA_ADX | PTA_RDSEED
- | PTA_CLZERO | PTA_CLFLUSHOPT | PTA_XSAVEC | PTA_XSAVES
- | PTA_SHA | PTA_LZCNT | PTA_POPCNT},
- {"btver1", PROCESSOR_BTVER1, CPU_GENERIC,
- PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
- | PTA_SSSE3 | PTA_SSE4A |PTA_ABM | PTA_CX16 | PTA_PRFCHW
- | PTA_FXSR | PTA_XSAVE},
- {"btver2", PROCESSOR_BTVER2, CPU_BTVER2,
- PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
- | PTA_SSSE3 | PTA_SSE4A |PTA_ABM | PTA_CX16 | PTA_SSE4_1
- | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX
- | PTA_BMI | PTA_F16C | PTA_MOVBE | PTA_PRFCHW
- | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT},
-
- {"generic", PROCESSOR_GENERIC, CPU_GENERIC,
- PTA_64BIT
- | PTA_HLE /* flags are only used for -march switch. */ },
- };
-
/* -mrecip options. */
static struct
{
@@ -3740,7 +3407,6 @@ ix86_option_override_internal (bool main_args_p,
{ "vec-sqrt", RECIP_MASK_VEC_SQRT },
};
- int const pta_size = ARRAY_SIZE (processor_alias_table);
/* Turn off both OPTION_MASK_ABI_64 and OPTION_MASK_ABI_X32 if
TARGET_64BIT_DEFAULT is true and TARGET_64BIT is false. */
@@ -3828,8 +3494,7 @@ ix86_option_override_internal (bool main_args_p,
opts->x_ix86_tune_string = opts->x_ix86_arch_string;
if (!opts->x_ix86_tune_string)
{
- opts->x_ix86_tune_string
- = processor_target_table[TARGET_CPU_DEFAULT].name;
+ opts->x_ix86_tune_string = processor_names[TARGET_CPU_DEFAULT];
ix86_tune_defaulted = 1;
}
@@ -4396,7 +4061,7 @@ ix86_option_override_internal (bool main_args_p,
}
}
- ix86_tune_cost = processor_target_table[ix86_tune].cost;
+ ix86_tune_cost = processor_cost_table[ix86_tune];
/* TODO: ix86_cost should be chosen at instruction or function granuality
so for cold code we use size_cost even in !optimize_size compilation. */
if (opts->x_optimize_size)
@@ -5193,7 +4858,7 @@ ix86_function_specific_restore (struct gcc_options *opts,
opts->x_ix86_tune_memset_strategy = ptr->x_ix86_tune_memset_strategy;
opts->x_ix86_tune_no_default = ptr->x_ix86_tune_no_default;
opts->x_ix86_veclibabi_type = ptr->x_ix86_veclibabi_type;
- ix86_tune_cost = processor_target_table[ix86_tune].cost;
+ ix86_tune_cost = processor_cost_table[ix86_tune];
/* TODO: ix86_cost should be chosen at instruction or function granuality
so for cold code we use size_cost even in !optimize_size compilation. */
if (opts->x_optimize_size)
@@ -5280,12 +4945,12 @@ ix86_function_specific_print (FILE *file, int indent,
gcc_assert (ptr->arch < PROCESSOR_max);
fprintf (file, "%*sarch = %d (%s)\n",
indent, "",
- ptr->arch, processor_target_table[ptr->arch].name);
+ ptr->arch, processor_names[ptr->arch]);
gcc_assert (ptr->tune < PROCESSOR_max);
fprintf (file, "%*stune = %d (%s)\n",
indent, "",
- ptr->tune, processor_target_table[ptr->tune].name);
+ ptr->tune, processor_names[ptr->tune]);
fprintf (file, "%*sbranch_cost = %d\n", indent, "", ptr->branch_cost);
@@ -10656,26 +10321,16 @@ static int indirectlabelno;
/* True if call thunk function is needed. */
static bool indirect_thunk_needed = false;
-/* True if call thunk function with the BND prefix is needed. */
-static bool indirect_thunk_bnd_needed = false;
/* Bit masks of integer registers, which contain branch target, used
by call thunk functions. */
static int indirect_thunks_used;
-/* Bit masks of integer registers, which contain branch target, used
- by call thunk functions with the BND prefix. */
-static int indirect_thunks_bnd_used;
/* True if return thunk function is needed. */
static bool indirect_return_needed = false;
-/* True if return thunk function with the BND prefix is needed. */
-static bool indirect_return_bnd_needed = false;
/* True if return thunk function via CX is needed. */
static bool indirect_return_via_cx;
-/* True if return thunk function via CX with the BND prefix is
- needed. */
-static bool indirect_return_via_cx_bnd;
#ifndef INDIRECT_LABEL
# define INDIRECT_LABEL "LIND"
@@ -10685,7 +10340,6 @@ static bool indirect_return_via_cx_bnd;
enum indirect_thunk_prefix
{
indirect_thunk_prefix_none,
- indirect_thunk_prefix_bnd,
indirect_thunk_prefix_nt
};
@@ -10722,10 +10376,8 @@ indirect_thunk_name (char name[32], unsigned int regno,
{
const char *prefix;
- if (need_prefix == indirect_thunk_prefix_bnd)
- prefix = "_bnd";
- else if (need_prefix == indirect_thunk_prefix_nt
- && regno != INVALID_REGNUM)
+ if (need_prefix == indirect_thunk_prefix_nt
+ && regno != INVALID_REGNUM)
{
/* NOTRACK prefix is only used with external thunk via
register so that NOTRACK prefix can be added to indirect
@@ -10753,35 +10405,19 @@ indirect_thunk_name (char name[32], unsigned int regno,
else
{
if (regno != INVALID_REGNUM)
- {
- if (need_prefix == indirect_thunk_prefix_bnd)
- ASM_GENERATE_INTERNAL_LABEL (name, "LITBR", regno);
- else
- ASM_GENERATE_INTERNAL_LABEL (name, "LITR", regno);
- }
+ ASM_GENERATE_INTERNAL_LABEL (name, "LITR", regno);
else
{
if (ret_p)
- {
- if (need_prefix == indirect_thunk_prefix_bnd)
- ASM_GENERATE_INTERNAL_LABEL (name, "LRTB", 0);
- else
- ASM_GENERATE_INTERNAL_LABEL (name, "LRT", 0);
- }
+ ASM_GENERATE_INTERNAL_LABEL (name, "LRT", 0);
else
- {
- if (need_prefix == indirect_thunk_prefix_bnd)
- ASM_GENERATE_INTERNAL_LABEL (name, "LITB", 0);
- else
- ASM_GENERATE_INTERNAL_LABEL (name, "LIT", 0);
- }
+ ASM_GENERATE_INTERNAL_LABEL (name, "LIT", 0);
}
}
}
-/* Output a call and return thunk for indirect branch. If BND_P is
- true, the BND prefix is needed. If REGNO != -1, the function
- address is in REGNO and the call and return thunk looks like:
+/* Output a call and return thunk for indirect branch. If REGNO != -1,
+ the function address is in REGNO and the call and return thunk looks like:
call L2
L1:
@@ -10806,8 +10442,7 @@ indirect_thunk_name (char name[32], unsigned int regno,
*/
static void
-output_indirect_thunk (enum indirect_thunk_prefix need_prefix,
- unsigned int regno)
+output_indirect_thunk (unsigned int regno)
{
char indirectlabel1[32];
char indirectlabel2[32];
@@ -10818,10 +10453,7 @@ output_indirect_thunk (enum indirect_thunk_prefix need_prefix,
indirectlabelno++);
/* Call */
- if (need_prefix == indirect_thunk_prefix_bnd)
- fputs ("\tbnd call\t", asm_out_file);
- else
- fputs ("\tcall\t", asm_out_file);
+ fputs ("\tcall\t", asm_out_file);
assemble_name_raw (asm_out_file, indirectlabel2);
fputc ('\n', asm_out_file);
@@ -10855,17 +10487,13 @@ output_indirect_thunk (enum indirect_thunk_prefix need_prefix,
output_asm_insn ("lea\t{%E1, %0|%0, %E1}", xops);
}
- if (need_prefix == indirect_thunk_prefix_bnd)
- fputs ("\tbnd ret\n", asm_out_file);
- else
- fputs ("\tret\n", asm_out_file);
+ fputs ("\tret\n", asm_out_file);
}
/* Output a funtion with a call and return thunk for indirect branch.
- If BND_P is true, the BND prefix is needed. If REGNO != UNVALID_REGNUM,
- the function address is in REGNO. Otherwise, the function address is
- on the top of stack. Thunk is used for function return if RET_P is
- true. */
+ If REGNO != INVALID_REGNUM, the function address is in REGNO.
+ Otherwise, the function address is on the top of stack. Thunk is
+ used for function return if RET_P is true. */
static void
output_indirect_thunk_function (enum indirect_thunk_prefix need_prefix,
@@ -10874,7 +10502,7 @@ output_indirect_thunk_function (enum indirect_thunk_prefix need_prefix,
char name[32];
tree decl;
- /* Create __x86_indirect_thunk/__x86_indirect_thunk_bnd. */
+ /* Create __x86_indirect_thunk. */
indirect_thunk_name (name, regno, need_prefix, ret_p);
decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
get_identifier (name),
@@ -10929,7 +10557,7 @@ output_indirect_thunk_function (enum indirect_thunk_prefix need_prefix,
/* Make sure unwind info is emitted for the thunk if needed. */
final_start_function (emit_barrier (), asm_out_file, 1);
- output_indirect_thunk (need_prefix, regno);
+ output_indirect_thunk (regno);
final_end_function ();
init_insn_lengths ();
@@ -10967,23 +10595,12 @@ ix86_code_end (void)
if (indirect_return_needed)
output_indirect_thunk_function (indirect_thunk_prefix_none,
INVALID_REGNUM, true);
- if (indirect_return_bnd_needed)
- output_indirect_thunk_function (indirect_thunk_prefix_bnd,
- INVALID_REGNUM, true);
-
if (indirect_return_via_cx)
output_indirect_thunk_function (indirect_thunk_prefix_none,
CX_REG, true);
- if (indirect_return_via_cx_bnd)
- output_indirect_thunk_function (indirect_thunk_prefix_bnd,
- CX_REG, true);
-
if (indirect_thunk_needed)
output_indirect_thunk_function (indirect_thunk_prefix_none,
INVALID_REGNUM, false);
- if (indirect_thunk_bnd_needed)
- output_indirect_thunk_function (indirect_thunk_prefix_bnd,
- INVALID_REGNUM, false);
for (regno = FIRST_REX_INT_REG; regno <= LAST_REX_INT_REG; regno++)
{
@@ -10991,10 +10608,6 @@ ix86_code_end (void)
if ((indirect_thunks_used & (1 << i)))
output_indirect_thunk_function (indirect_thunk_prefix_none,
regno, false);
-
- if ((indirect_thunks_bnd_used & (1 << i)))
- output_indirect_thunk_function (indirect_thunk_prefix_bnd,
- regno, false);
}
for (regno = FIRST_INT_REG; regno <= LAST_INT_REG; regno++)
@@ -11006,10 +10619,6 @@ ix86_code_end (void)
output_indirect_thunk_function (indirect_thunk_prefix_none,
regno, false);
- if ((indirect_thunks_bnd_used & (1 << regno)))
- output_indirect_thunk_function (indirect_thunk_prefix_bnd,
- regno, false);
-
if (!(pic_labels_used & (1 << regno)))
continue;
@@ -11255,15 +10864,6 @@ ix86_hard_regno_scratch_ok (unsigned int regno)
&& df_regs_ever_live_p (regno)));
}
-/* Return true if register class CL should be an additional allocno
- class. */
-
-static bool
-ix86_additional_allocno_class_p (reg_class_t cl)
-{
- return cl == MOD4_SSE_REGS;
-}
-
/* Return TRUE if we need to save REGNO. */
static bool
@@ -11284,16 +10884,6 @@ ix86_save_reg (unsigned int regno, bool maybe_eh_return, bool ignore_outlined)
while (nregs-- > 0)
if ((i + nregs) == regno)
return false;
-
- reg = crtl->return_bnd;
- if (reg)
- {
- i = REGNO (reg);
- nregs = REG_NREGS (reg);
- while (nregs-- > 0)
- if ((i + nregs) == regno)
- return false;
- }
}
return (df_regs_ever_live_p (regno)
@@ -13281,12 +12871,14 @@ ix86_finalize_stack_frame_flags (void)
recompute_frame_layout_p = true;
}
}
- else if (crtl->max_used_stack_slot_alignment
- > crtl->preferred_stack_boundary)
+ else if (crtl->max_used_stack_slot_alignment >= 128)
{
- /* We don't need to realign stack. But we still need to keep
- stack frame properly aligned to satisfy the largest alignment
- of stack slots. */
+ /* We don't need to realign stack. max_used_stack_alignment is
+ used to decide how stack frame should be aligned. This is
+ independent of any psABIs nor 32-bit vs 64-bit. It is always
+ safe to compute max_used_stack_alignment. We compute it only
+ if 128-bit aligned load/store may be generated on misaligned
+ stack slot which will lead to segfault. */
if (ix86_find_max_used_stack_alignment (stack_alignment, true))
cfun->machine->max_used_stack_alignment
= stack_alignment / BITS_PER_UNIT;
@@ -15502,10 +15094,6 @@ ix86_force_load_from_GOT_p (rtx x)
static bool
ix86_legitimate_constant_p (machine_mode mode, rtx x)
{
- /* Pointer bounds constants are not valid. */
- if (POINTER_BOUNDS_MODE_P (GET_MODE (x)))
- return false;
-
switch (GET_CODE (x))
{
case CONST:
@@ -18644,25 +18232,6 @@ ix86_print_operand_address_as (FILE *file, rtx addr,
ok = ix86_decompose_address (XVECEXP (addr, 0, 0), &parts);
code = 'q';
}
- else if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_BNDMK_ADDR)
- {
- ok = ix86_decompose_address (XVECEXP (addr, 0, 1), &parts);
- gcc_assert (parts.base == NULL_RTX || parts.index == NULL_RTX);
- if (parts.base != NULL_RTX)
- {
- parts.index = parts.base;
- parts.scale = 1;
- }
- parts.base = XVECEXP (addr, 0, 0);
- addr = XVECEXP (addr, 0, 0);
- }
- else if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_BNDLDX_ADDR)
- {
- ok = ix86_decompose_address (XVECEXP (addr, 0, 0), &parts);
- gcc_assert (parts.index == NULL_RTX);
- parts.index = XVECEXP (addr, 0, 1);
- addr = XVECEXP (addr, 0, 0);
- }
else
ok = ix86_decompose_address (addr, &parts);
@@ -19776,8 +19345,6 @@ ix86_output_addr_diff_elt (FILE *file, int value, int rel)
if (TARGET_64BIT || TARGET_VXWORKS_RTP)
fprintf (file, "%s%s%d-%s%d\n",
directive, LPREFIX, value, LPREFIX, rel);
- else if (HAVE_AS_GOTOFF_IN_DATA)
- fprintf (file, ASM_LONG "%s%d@GOTOFF\n", LPREFIX, value);
#if TARGET_MACHO
else if (TARGET_MACHO)
{
@@ -19786,6 +19353,8 @@ ix86_output_addr_diff_elt (FILE *file, int value, int rel)
putc ('\n', file);
}
#endif
+ else if (HAVE_AS_GOTOFF_IN_DATA)
+ fprintf (file, ASM_LONG "%s%d@GOTOFF\n", LPREFIX, value);
else
asm_fprintf (file, ASM_LONG "%U%s+[.-%s%d]\n",
GOT_SYMBOL_NAME, LPREFIX, value);
@@ -27630,6 +27199,11 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
issetmem,
issetmem && val_exp == const0_rtx, have_as,
&dynamic_check, &noalign, false);
+
+ if (dump_file)
+ fprintf (dump_file, "Selected stringop expansion strategy: %s\n",
+ stringop_alg_names[alg]);
+
if (alg == libcall)
return false;
gcc_assert (alg != no_stringop);
@@ -28548,10 +28122,7 @@ ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p)
int i = regno;
if (i >= FIRST_REX_INT_REG)
i -= (FIRST_REX_INT_REG - LAST_INT_REG - 1);
- if (need_prefix == indirect_thunk_prefix_bnd)
- indirect_thunks_bnd_used |= 1 << i;
- else
- indirect_thunks_used |= 1 << i;
+ indirect_thunks_used |= 1 << i;
}
indirect_thunk_name (thunk_name_buf, regno, need_prefix, false);
thunk_name = thunk_name_buf;
@@ -28562,23 +28133,15 @@ ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p)
if (sibcall_p)
{
if (thunk_name != NULL)
- {
- if (need_prefix == indirect_thunk_prefix_bnd)
- fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
- else
- fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
- }
+ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
else
- output_indirect_thunk (need_prefix, regno);
+ output_indirect_thunk (regno);
}
else
{
if (thunk_name != NULL)
{
- if (need_prefix == indirect_thunk_prefix_bnd)
- fprintf (asm_out_file, "\tbnd call\t%s\n", thunk_name);
- else
- fprintf (asm_out_file, "\tcall\t%s\n", thunk_name);
+ fprintf (asm_out_file, "\tcall\t%s\n", thunk_name);
return;
}
@@ -28593,32 +28156,21 @@ ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p)
indirectlabelno++);
/* Jump. */
- if (need_prefix == indirect_thunk_prefix_bnd)
- fputs ("\tbnd jmp\t", asm_out_file);
- else
- fputs ("\tjmp\t", asm_out_file);
+ fputs ("\tjmp\t", asm_out_file);
assemble_name_raw (asm_out_file, indirectlabel2);
fputc ('\n', asm_out_file);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel1);
if (thunk_name != NULL)
- {
- if (need_prefix == indirect_thunk_prefix_bnd)
- fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
- else
- fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
- }
+ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
else
- output_indirect_thunk (need_prefix, regno);
+ output_indirect_thunk (regno);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
/* Call. */
- if (need_prefix == indirect_thunk_prefix_bnd)
- fputs ("\tbnd call\t", asm_out_file);
- else
- fputs ("\tcall\t", asm_out_file);
+ fputs ("\tcall\t", asm_out_file);
assemble_name_raw (asm_out_file, indirectlabel1);
fputc ('\n', asm_out_file);
}
@@ -28657,12 +28209,7 @@ ix86_output_indirect_branch_via_push (rtx call_op, const char *xasm,
!= indirect_branch_thunk_inline)
{
if (cfun->machine->indirect_branch_type == indirect_branch_thunk)
- {
- if (need_prefix == indirect_thunk_prefix_bnd)
- indirect_thunk_bnd_needed = true;
- else
- indirect_thunk_needed = true;
- }
+ indirect_thunk_needed = true;
indirect_thunk_name (thunk_name_buf, regno, need_prefix, false);
thunk_name = thunk_name_buf;
}
@@ -28676,14 +28223,9 @@ ix86_output_indirect_branch_via_push (rtx call_op, const char *xasm,
{
output_asm_insn (push_buf, &call_op);
if (thunk_name != NULL)
- {
- if (need_prefix == indirect_thunk_prefix_bnd)
- fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
- else
- fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
- }
+ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
else
- output_indirect_thunk (need_prefix, regno);
+ output_indirect_thunk (regno);
}
else
{
@@ -28698,10 +28240,7 @@ ix86_output_indirect_branch_via_push (rtx call_op, const char *xasm,
indirectlabelno++);
/* Jump. */
- if (need_prefix == indirect_thunk_prefix_bnd)
- fputs ("\tbnd jmp\t", asm_out_file);
- else
- fputs ("\tjmp\t", asm_out_file);
+ fputs ("\tjmp\t", asm_out_file);
assemble_name_raw (asm_out_file, indirectlabel2);
fputc ('\n', asm_out_file);
@@ -28743,22 +28282,14 @@ ix86_output_indirect_branch_via_push (rtx call_op, const char *xasm,
output_asm_insn (push_buf, &call_op);
if (thunk_name != NULL)
- {
- if (need_prefix == indirect_thunk_prefix_bnd)
- fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
- else
- fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
- }
+ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
else
- output_indirect_thunk (need_prefix, regno);
+ output_indirect_thunk (regno);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
/* Call. */
- if (need_prefix == indirect_thunk_prefix_bnd)
- fputs ("\tbnd call\t", asm_out_file);
- else
- fputs ("\tcall\t", asm_out_file);
+ fputs ("\tcall\t", asm_out_file);
assemble_name_raw (asm_out_file, indirectlabel1);
fputc ('\n', asm_out_file);
}
@@ -28816,19 +28347,11 @@ ix86_output_function_return (bool long_p)
== indirect_branch_thunk);
indirect_thunk_name (thunk_name, INVALID_REGNUM, need_prefix,
true);
- if (need_prefix == indirect_thunk_prefix_bnd)
- {
- indirect_return_bnd_needed |= need_thunk;
- fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
- }
- else
- {
- indirect_return_needed |= need_thunk;
- fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
- }
+ indirect_return_needed |= need_thunk;
+ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
}
else
- output_indirect_thunk (need_prefix, INVALID_REGNUM);
+ output_indirect_thunk (INVALID_REGNUM);
return "";
}
@@ -28859,27 +28382,16 @@ ix86_output_indirect_function_return (rtx ret_op)
bool need_thunk = (cfun->machine->function_return_type
== indirect_branch_thunk);
indirect_thunk_name (thunk_name, regno, need_prefix, true);
- if (need_prefix == indirect_thunk_prefix_bnd)
- {
- if (need_thunk)
- {
- indirect_return_via_cx_bnd = true;
- indirect_thunks_bnd_used |= 1 << CX_REG;
- }
- fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
- }
- else
+
+ if (need_thunk)
{
- if (need_thunk)
- {
- indirect_return_via_cx = true;
- indirect_thunks_used |= 1 << CX_REG;
- }
- fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
+ indirect_return_via_cx = true;
+ indirect_thunks_used |= 1 << CX_REG;
}
+ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
}
else
- output_indirect_thunk (need_prefix, regno);
+ output_indirect_thunk (regno);
return "";
}
@@ -29108,98 +28620,6 @@ ix86_instantiate_decls (void)
instantiate_decl_rtl (s->rtl);
}
-/* Return the number used for encoding REG, in the range 0..7. */
-
-static int
-reg_encoded_number (rtx reg)
-{
- unsigned regno = REGNO (reg);
- switch (regno)
- {
- case AX_REG:
- return 0;
- case CX_REG:
- return 1;
- case DX_REG:
- return 2;
- case BX_REG:
- return 3;
- case SP_REG:
- return 4;
- case BP_REG:
- return 5;
- case SI_REG:
- return 6;
- case DI_REG:
- return 7;
- default:
- break;
- }
- if (IN_RANGE (regno, FIRST_STACK_REG, LAST_STACK_REG))
- return regno - FIRST_STACK_REG;
- if (IN_RANGE (regno, FIRST_SSE_REG, LAST_SSE_REG))
- return regno - FIRST_SSE_REG;
- if (IN_RANGE (regno, FIRST_MMX_REG, LAST_MMX_REG))
- return regno - FIRST_MMX_REG;
- if (IN_RANGE (regno, FIRST_REX_SSE_REG, LAST_REX_SSE_REG))
- return regno - FIRST_REX_SSE_REG;
- if (IN_RANGE (regno, FIRST_REX_INT_REG, LAST_REX_INT_REG))
- return regno - FIRST_REX_INT_REG;
- if (IN_RANGE (regno, FIRST_MASK_REG, LAST_MASK_REG))
- return regno - FIRST_MASK_REG;
- return -1;
-}
-
-/* Given an insn INSN with NOPERANDS OPERANDS, return the modr/m byte used
- in its encoding if it could be relevant for ROP mitigation, otherwise
- return -1. If POPNO0 and POPNO1 are nonnull, store the operand numbers
- used for calculating it into them. */
-
-static int
-ix86_get_modrm_for_rop (rtx_insn *insn, rtx *operands, int noperands,
- int *popno0 = 0, int *popno1 = 0)
-{
- if (asm_noperands (PATTERN (insn)) >= 0)
- return -1;
- int has_modrm = get_attr_modrm (insn);
- if (!has_modrm)
- return -1;
- enum attr_modrm_class cls = get_attr_modrm_class (insn);
- rtx op0, op1;
- switch (cls)
- {
- case MODRM_CLASS_OP02:
- gcc_assert (noperands >= 3);
- if (popno0)
- {
- *popno0 = 0;
- *popno1 = 2;
- }
- op0 = operands[0];
- op1 = operands[2];
- break;
- case MODRM_CLASS_OP01:
- gcc_assert (noperands >= 2);
- if (popno0)
- {
- *popno0 = 0;
- *popno1 = 1;
- }
- op0 = operands[0];
- op1 = operands[1];
- break;
- default:
- return -1;
- }
- if (REG_P (op0) && REG_P (op1))
- {
- int enc0 = reg_encoded_number (op0);
- int enc1 = reg_encoded_number (op1);
- return 0xc0 + (enc1 << 3) + enc0;
- }
- return -1;
-}
-
/* Check whether x86 address PARTS is a pc-relative address. */
bool
@@ -29586,16 +29006,6 @@ avoid_func_arg_motion (rtx_insn *first_arg, rtx_insn *insn)
rtx set;
rtx tmp;
- /* Add anti dependencies for bounds stores. */
- if (INSN_P (insn)
- && GET_CODE (PATTERN (insn)) == PARALLEL
- && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == UNSPEC
- && XINT (XVECEXP (PATTERN (insn), 0, 0), 1) == UNSPEC_BNDSTX)
- {
- add_dependence (first_arg, insn, REG_DEP_ANTI);
- return;
- }
-
set = single_set (insn);
if (!set)
return;
@@ -33593,7 +33003,7 @@ ix86_gimple_fold_builtin (gimple_stmt_iterator *gsi)
{
gimple *stmt = gsi_stmt (*gsi);
tree fndecl = gimple_call_fndecl (stmt);
- gcc_checking_assert (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD);
+ gcc_checking_assert (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_MD));
int n_args = gimple_call_num_args (stmt);
enum ix86_builtins fn_code = (enum ix86_builtins) DECL_FUNCTION_CODE (fndecl);
tree decl = NULL_TREE;
@@ -38183,7 +37593,7 @@ rdseed_step:
{
tree fndecl = gimple_call_fndecl (def_stmt);
if (fndecl
- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
+ && fndecl_built_in_p (fndecl, BUILT_IN_MD))
switch ((unsigned int) DECL_FUNCTION_CODE (fndecl))
{
case IX86_BUILTIN_CMPPD:
@@ -39604,12 +39014,14 @@ ix86_register_priority (int hard_regno)
return 1;
/* New x86-64 int registers result in bigger code size. Discourage
them. */
- if (FIRST_REX_INT_REG <= hard_regno && hard_regno <= LAST_REX_INT_REG)
+ if (IN_RANGE (hard_regno, FIRST_REX_INT_REG, LAST_REX_INT_REG))
return 2;
/* New x86-64 SSE registers result in bigger code size. Discourage
them. */
- if (FIRST_REX_SSE_REG <= hard_regno && hard_regno <= LAST_REX_SSE_REG)
+ if (IN_RANGE (hard_regno, FIRST_REX_SSE_REG, LAST_REX_SSE_REG))
return 2;
+ if (IN_RANGE (hard_regno, FIRST_EXT_REX_SSE_REG, LAST_EXT_REX_SSE_REG))
+ return 1;
/* Usage of AX register results in smaller code. Prefer it. */
if (hard_regno == AX_REG)
return 4;
@@ -40246,16 +39658,11 @@ ix86_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
|| VALID_AVX512F_SCALAR_MODE (mode)))
return true;
- /* For AVX-5124FMAPS allow V64SFmode for special regnos. */
- if ((TARGET_AVX5124FMAPS || TARGET_AVX5124VNNIW)
- && MOD4_SSE_REGNO_P (regno)
- && mode == V64SFmode)
- return true;
-
- /* For AVX-5124VNNIW allow V64SImode for special regnos. */
+ /* For AVX-5124FMAPS or AVX-5124VNNIW
+ allow V64SF and V64SI modes for special regnos. */
if ((TARGET_AVX5124FMAPS || TARGET_AVX5124VNNIW)
- && MOD4_SSE_REGNO_P (regno)
- && mode == V64SImode)
+ && (mode == V64SFmode || mode == V64SImode)
+ && MOD4_SSE_REGNO_P (regno))
return true;
/* TODO check for QI/HI scalars. */
@@ -40383,6 +39790,10 @@ ix86_modes_tieable_p (machine_mode mode1, machine_mode mode2)
/* If MODE2 is only appropriate for an SSE register, then tie with
any other mode acceptable to SSE registers. */
+ if (GET_MODE_SIZE (mode2) == 64
+ && ix86_hard_regno_mode_ok (FIRST_SSE_REG, mode2))
+ return (GET_MODE_SIZE (mode1) == 64
+ && ix86_hard_regno_mode_ok (FIRST_SSE_REG, mode1));
if (GET_MODE_SIZE (mode2) == 32
&& ix86_hard_regno_mode_ok (FIRST_SSE_REG, mode2))
return (GET_MODE_SIZE (mode1) == 32
@@ -40654,7 +40065,7 @@ ix86_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno,
{
case SET:
if (register_operand (SET_DEST (x), VOIDmode)
- && reg_or_0_operand (SET_SRC (x), VOIDmode))
+ && register_operand (SET_SRC (x), VOIDmode))
{
*total = ix86_set_reg_reg_cost (GET_MODE (SET_DEST (x)));
return true;
@@ -40681,20 +40092,10 @@ ix86_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno,
case CONST:
case LABEL_REF:
case SYMBOL_REF:
- if (TARGET_64BIT && !x86_64_immediate_operand (x, VOIDmode))
- *total = 3;
- else if (TARGET_64BIT && !x86_64_zext_immediate_operand (x, VOIDmode))
- *total = 2;
- else if (flag_pic && SYMBOLIC_CONST (x)
- && !(TARGET_64BIT
- && (GET_CODE (x) == LABEL_REF
- || (GET_CODE (x) == SYMBOL_REF
- && SYMBOL_REF_LOCAL_P (x))))
- /* Use 0 cost for CONST to improve its propagation. */
- && (TARGET_64BIT || GET_CODE (x) != CONST))
- *total = 1;
- else
+ if (x86_64_immediate_operand (x, VOIDmode))
*total = 0;
+ else
+ *total = 1;
return true;
case CONST_DOUBLE:
@@ -41808,6 +41209,10 @@ x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
{
const char *mcount_name = (flag_fentry ? MCOUNT_NAME_BEFORE_PROLOGUE
: MCOUNT_NAME);
+
+ if (cfun->machine->endbr_queued_at_entrance)
+ fprintf (file, "\t%s\n", TARGET_64BIT ? "endbr64" : "endbr32");
+
if (TARGET_64BIT)
{
#ifndef NO_PROFILE_COUNTERS
@@ -42213,215 +41618,6 @@ ix86_seh_fixup_eh_fallthru (void)
}
}
-/* Given a register number BASE, the lowest of a group of registers, update
- regsets IN and OUT with the registers that should be avoided in input
- and output operands respectively when trying to avoid generating a modr/m
- byte for -mmitigate-rop. */
-
-static void
-set_rop_modrm_reg_bits (int base, HARD_REG_SET &in, HARD_REG_SET &out)
-{
- SET_HARD_REG_BIT (out, base);
- SET_HARD_REG_BIT (out, base + 1);
- SET_HARD_REG_BIT (in, base + 2);
- SET_HARD_REG_BIT (in, base + 3);
-}
-
-/* Called if -mmitigate-rop is in effect. Try to rewrite instructions so
- that certain encodings of modr/m bytes do not occur. */
-static void
-ix86_mitigate_rop (void)
-{
- HARD_REG_SET input_risky;
- HARD_REG_SET output_risky;
- HARD_REG_SET inout_risky;
-
- CLEAR_HARD_REG_SET (output_risky);
- CLEAR_HARD_REG_SET (input_risky);
- SET_HARD_REG_BIT (output_risky, AX_REG);
- SET_HARD_REG_BIT (output_risky, CX_REG);
- SET_HARD_REG_BIT (input_risky, BX_REG);
- SET_HARD_REG_BIT (input_risky, DX_REG);
- set_rop_modrm_reg_bits (FIRST_SSE_REG, input_risky, output_risky);
- set_rop_modrm_reg_bits (FIRST_REX_INT_REG, input_risky, output_risky);
- set_rop_modrm_reg_bits (FIRST_REX_SSE_REG, input_risky, output_risky);
- set_rop_modrm_reg_bits (FIRST_EXT_REX_SSE_REG, input_risky, output_risky);
- set_rop_modrm_reg_bits (FIRST_MASK_REG, input_risky, output_risky);
- COPY_HARD_REG_SET (inout_risky, input_risky);
- IOR_HARD_REG_SET (inout_risky, output_risky);
-
- df_note_add_problem ();
- /* Fix up what stack-regs did. */
- df_insn_rescan_all ();
- df_analyze ();
-
- regrename_init (true);
- regrename_analyze (NULL);
-
- auto_vec<du_head_p> cands;
-
- for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- if (!NONDEBUG_INSN_P (insn))
- continue;
-
- if (GET_CODE (PATTERN (insn)) == USE
- || GET_CODE (PATTERN (insn)) == CLOBBER)
- continue;
-
- extract_insn (insn);
-
- int opno0, opno1;
- int modrm = ix86_get_modrm_for_rop (insn, recog_data.operand,
- recog_data.n_operands, &opno0,
- &opno1);
-
- if (!ix86_rop_should_change_byte_p (modrm))
- continue;
-
- insn_rr_info *info = &insn_rr[INSN_UID (insn)];
-
- /* This happens when regrename has to fail a block. */
- if (!info->op_info)
- continue;
-
- if (info->op_info[opno0].n_chains != 0)
- {
- gcc_assert (info->op_info[opno0].n_chains == 1);
- du_head_p op0c;
- op0c = regrename_chain_from_id (info->op_info[opno0].heads[0]->id);
- if (op0c->target_data_1 + op0c->target_data_2 == 0
- && !op0c->cannot_rename)
- cands.safe_push (op0c);
-
- op0c->target_data_1++;
- }
- if (info->op_info[opno1].n_chains != 0)
- {
- gcc_assert (info->op_info[opno1].n_chains == 1);
- du_head_p op1c;
- op1c = regrename_chain_from_id (info->op_info[opno1].heads[0]->id);
- if (op1c->target_data_1 + op1c->target_data_2 == 0
- && !op1c->cannot_rename)
- cands.safe_push (op1c);
-
- op1c->target_data_2++;
- }
- }
-
- int i;
- du_head_p head;
- FOR_EACH_VEC_ELT (cands, i, head)
- {
- int old_reg, best_reg;
- HARD_REG_SET unavailable;
-
- CLEAR_HARD_REG_SET (unavailable);
- if (head->target_data_1)
- IOR_HARD_REG_SET (unavailable, output_risky);
- if (head->target_data_2)
- IOR_HARD_REG_SET (unavailable, input_risky);
-
- int n_uses;
- reg_class superclass = regrename_find_superclass (head, &n_uses,
- &unavailable);
- old_reg = head->regno;
- best_reg = find_rename_reg (head, superclass, &unavailable,
- old_reg, false);
- bool ok = regrename_do_replace (head, best_reg);
- gcc_assert (ok);
- if (dump_file)
- fprintf (dump_file, "Chain %d renamed as %s in %s\n", head->id,
- reg_names[best_reg], reg_class_names[superclass]);
-
- }
-
- regrename_finish ();
-
- df_analyze ();
-
- basic_block bb;
- regset_head live;
-
- INIT_REG_SET (&live);
-
- FOR_EACH_BB_FN (bb, cfun)
- {
- rtx_insn *insn;
-
- COPY_REG_SET (&live, DF_LR_OUT (bb));
- df_simulate_initialize_backwards (bb, &live);
-
- FOR_BB_INSNS_REVERSE (bb, insn)
- {
- if (!NONDEBUG_INSN_P (insn))
- continue;
-
- df_simulate_one_insn_backwards (bb, insn, &live);
-
- if (GET_CODE (PATTERN (insn)) == USE
- || GET_CODE (PATTERN (insn)) == CLOBBER)
- continue;
-
- extract_insn (insn);
- constrain_operands_cached (insn, reload_completed);
- int opno0, opno1;
- int modrm = ix86_get_modrm_for_rop (insn, recog_data.operand,
- recog_data.n_operands, &opno0,
- &opno1);
- if (modrm < 0
- || !ix86_rop_should_change_byte_p (modrm)
- || opno0 == opno1)
- continue;
-
- rtx oldreg = recog_data.operand[opno1];
- preprocess_constraints (insn);
- const operand_alternative *alt = which_op_alt ();
-
- int i;
- for (i = 0; i < recog_data.n_operands; i++)
- if (i != opno1
- && alt[i].earlyclobber
- && reg_overlap_mentioned_p (recog_data.operand[i],
- oldreg))
- break;
-
- if (i < recog_data.n_operands)
- continue;
-
- if (dump_file)
- fprintf (dump_file,
- "attempting to fix modrm byte in insn %d:"
- " reg %d class %s", INSN_UID (insn), REGNO (oldreg),
- reg_class_names[alt[opno1].cl]);
-
- HARD_REG_SET unavailable;
- REG_SET_TO_HARD_REG_SET (unavailable, &live);
- SET_HARD_REG_BIT (unavailable, REGNO (oldreg));
- IOR_COMPL_HARD_REG_SET (unavailable, call_used_reg_set);
- IOR_HARD_REG_SET (unavailable, fixed_reg_set);
- IOR_HARD_REG_SET (unavailable, output_risky);
- IOR_COMPL_HARD_REG_SET (unavailable,
- reg_class_contents[alt[opno1].cl]);
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (!TEST_HARD_REG_BIT (unavailable, i))
- break;
- if (i == FIRST_PSEUDO_REGISTER)
- {
- if (dump_file)
- fprintf (dump_file, ", none available\n");
- continue;
- }
- if (dump_file)
- fprintf (dump_file, " -> %d\n", i);
- rtx newreg = gen_rtx_REG (recog_data.operand_mode[opno1], i);
- validate_change (insn, recog_data.operand_loc[opno1], newreg, false);
- insn = emit_insn_before (gen_move_insn (newreg, oldreg), insn);
- }
- }
-}
-
/* Implement machine specific optimizations. We implement padding of returns
for K8 CPUs and pass to avoid 4 jumps in the single 16 byte window. */
static void
@@ -42431,9 +41627,6 @@ ix86_reorg (void)
with old MDEP_REORGS that are not CFG based. Recompute it now. */
compute_bb_for_insn ();
- if (flag_mitigate_rop)
- ix86_mitigate_rop ();
-
if (TARGET_SEH && current_function_has_exception_handlers ())
ix86_seh_fixup_eh_fallthru ();
@@ -44750,20 +43943,20 @@ void ix86_emit_i387_log1p (rtx op0, rtx op1)
rtx test;
emit_insn (gen_absxf2 (tmp, op1));
+ emit_move_insn (tmp2, standard_80387_constant_rtx (4)); /* fldln2 */
test = gen_rtx_GE (VOIDmode, tmp,
const_double_from_real_value (
REAL_VALUE_ATOF ("0.29289321881345247561810596348408353", XFmode),
XFmode));
- emit_jump_insn (gen_cbranchxf4 (test, XEXP (test, 0), XEXP (test, 1), label1));
+ emit_jump_insn
+ (gen_cbranchxf4 (test, XEXP (test, 0), XEXP (test, 1), label1));
- emit_move_insn (tmp2, standard_80387_constant_rtx (4)); /* fldln2 */
emit_insn (gen_fyl2xp1xf3_i387 (op0, op1, tmp2));
emit_jump (label2);
emit_label (label1);
emit_move_insn (tmp, CONST1_RTX (XFmode));
emit_insn (gen_addxf3 (tmp, op1, tmp));
- emit_move_insn (tmp2, standard_80387_constant_rtx (4)); /* fldln2 */
emit_insn (gen_fyl2xxf3_i387 (op0, tmp, tmp2));
emit_label (label2);
@@ -46144,6 +45337,42 @@ expand_vselect_vconcat (rtx target, rtx op0, rtx op1,
}
/* A subroutine of ix86_expand_vec_perm_builtin_1. Try to implement D
+ using movss or movsd. */
+static bool
+expand_vec_perm_movs (struct expand_vec_perm_d *d)
+{
+ machine_mode vmode = d->vmode;
+ unsigned i, nelt = d->nelt;
+ rtx x;
+
+ if (d->one_operand_p)
+ return false;
+
+ if (!(TARGET_SSE && vmode == V4SFmode)
+ && !(TARGET_SSE2 && vmode == V2DFmode))
+ return false;
+
+ /* Only the first element is changed. */
+ if (d->perm[0] != nelt && d->perm[0] != 0)
+ return false;
+ for (i = 1; i < nelt; ++i)
+ if (d->perm[i] != i + nelt - d->perm[0])
+ return false;
+
+ if (d->testing_p)
+ return true;
+
+ if (d->perm[0] == nelt)
+ x = gen_rtx_VEC_MERGE (vmode, d->op1, d->op0, GEN_INT (1));
+ else
+ x = gen_rtx_VEC_MERGE (vmode, d->op0, d->op1, GEN_INT (1));
+
+ emit_insn (gen_rtx_SET (d->target, x));
+
+ return true;
+}
+
+/* A subroutine of ix86_expand_vec_perm_builtin_1. Try to implement D
in terms of blendp[sd] / pblendw / pblendvb / vpblendd. */
static bool
@@ -46885,6 +46114,10 @@ expand_vec_perm_1 (struct expand_vec_perm_d *d)
}
}
+ /* Try movss/movsd instructions. */
+ if (expand_vec_perm_movs (d))
+ return true;
+
/* Finally, try the fully general two operand permute. */
if (expand_vselect_vconcat (d->target, d->op0, d->op1, d->perm, nelt,
d->testing_p))
@@ -51882,9 +51115,6 @@ ix86_run_selftests (void)
#undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
#define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 1
-#undef TARGET_ADDITIONAL_ALLOCNO_CLASS_P
-#define TARGET_ADDITIONAL_ALLOCNO_CLASS_P ix86_additional_allocno_class_p
-
#undef TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID
#define TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID ix86_addr_space_zero_address_valid
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index fbba598..e77dac7 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -311,6 +311,14 @@ struct processor_costs {
cost model. */
const int cond_not_taken_branch_cost;/* Cost of not taken branch for
vectorizer cost model. */
+
+ /* The "0:0:8" label alignment specified for some processors generates
+ secondary 8-byte alignment only for those label/jump/loop targets
+ which have primary alignment. */
+ const char *const align_loop; /* Loop alignment. */
+ const char *const align_jump; /* Jump alignment. */
+ const char *const align_label; /* Label alignment. */
+ const char *const align_func; /* Function alignment. */
};
extern const struct processor_costs *ix86_cost;
@@ -1033,9 +1041,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
/*xmm24,xmm25,xmm26,xmm27,xmm28,xmm29,xmm30,xmm31*/ \
0, 0, 0, 0, 0, 0, 0, 0, \
/* k0, k1, k2, k3, k4, k5, k6, k7*/ \
- 0, 0, 0, 0, 0, 0, 0, 0, \
-/* b0, b1, b2, b3*/ \
- 0, 0, 0, 0 }
+ 0, 0, 0, 0, 0, 0, 0, 0 }
/* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any
@@ -1072,9 +1078,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
/*xmm24,xmm25,xmm26,xmm27,xmm28,xmm29,xmm30,xmm31*/ \
6, 6, 6, 6, 6, 6, 6, 6, \
/* k0, k1, k2, k3, k4, k5, k6, k7*/ \
- 1, 1, 1, 1, 1, 1, 1, 1, \
-/* b0, b1, b2, b3*/ \
- 1, 1, 1, 1 }
+ 1, 1, 1, 1, 1, 1, 1, 1 }
/* Order in which to allocate registers. Each register must be
listed once, even those in FIXED_REGISTERS. List frame pointer
@@ -1090,8 +1094,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, \
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, \
- 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, \
- 78, 79, 80 }
+ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76 }
/* ADJUST_REG_ALLOC_ORDER is a macro which permits reg_alloc_order
to be rearranged based on a particular function. When using sse math,
@@ -1312,10 +1315,6 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
For any two classes, it is very desirable that there be another
class that represents their union.
- It might seem that class BREG is unnecessary, since no useful 386
- opcode needs reg %ebx. But some systems pass args to the OS in ebx,
- and the "b" register constraint is useful in asms for syscalls.
-
The flags, fpsr and fpcr registers are in no class. */
enum reg_class
@@ -1336,7 +1335,6 @@ enum reg_class
SSE_FIRST_REG,
NO_REX_SSE_REGS,
SSE_REGS,
- EVEX_SSE_REGS,
ALL_SSE_REGS,
MMX_REGS,
FP_TOP_SSE_REGS,
@@ -1345,10 +1343,10 @@ enum reg_class
FLOAT_INT_REGS,
INT_SSE_REGS,
FLOAT_INT_SSE_REGS,
- MASK_EVEX_REGS,
MASK_REGS,
- MOD4_SSE_REGS,
- ALL_REGS, LIM_REG_CLASSES
+ ALL_MASK_REGS,
+ ALL_REGS,
+ LIM_REG_CLASSES
};
#define N_REG_CLASSES ((int) LIM_REG_CLASSES)
@@ -1362,7 +1360,7 @@ enum reg_class
#define MMX_CLASS_P(CLASS) \
((CLASS) == MMX_REGS)
#define MASK_CLASS_P(CLASS) \
- reg_class_subset_p ((CLASS), MASK_REGS)
+ reg_class_subset_p ((CLASS), ALL_MASK_REGS)
#define MAYBE_INTEGER_CLASS_P(CLASS) \
reg_classes_intersect_p ((CLASS), GENERAL_REGS)
#define MAYBE_FLOAT_CLASS_P(CLASS) \
@@ -1372,7 +1370,7 @@ enum reg_class
#define MAYBE_MMX_CLASS_P(CLASS) \
reg_classes_intersect_p ((CLASS), MMX_REGS)
#define MAYBE_MASK_CLASS_P(CLASS) \
- reg_classes_intersect_p ((CLASS), MASK_REGS)
+ reg_classes_intersect_p ((CLASS), ALL_MASK_REGS)
#define Q_CLASS_P(CLASS) \
reg_class_subset_p ((CLASS), Q_REGS)
@@ -1398,7 +1396,6 @@ enum reg_class
"SSE_FIRST_REG", \
"NO_REX_SSE_REGS", \
"SSE_REGS", \
- "EVEX_SSE_REGS", \
"ALL_SSE_REGS", \
"MMX_REGS", \
"FP_TOP_SSE_REGS", \
@@ -1407,9 +1404,8 @@ enum reg_class
"FLOAT_INT_REGS", \
"INT_SSE_REGS", \
"FLOAT_INT_SSE_REGS", \
- "MASK_EVEX_REGS", \
"MASK_REGS", \
- "MOD4_SSE_REGS", \
+ "ALL_MASK_REGS", \
"ALL_REGS" }
/* Define which registers fit in which classes. This is an initializer
@@ -1418,41 +1414,39 @@ enum reg_class
Note that CLOBBERED_REGS are calculated by
TARGET_CONDITIONAL_REGISTER_USAGE. */
-#define REG_CLASS_CONTENTS \
-{ { 0x00, 0x0, 0x0 }, \
- { 0x01, 0x0, 0x0 }, /* AREG */ \
- { 0x02, 0x0, 0x0 }, /* DREG */ \
- { 0x04, 0x0, 0x0 }, /* CREG */ \
- { 0x08, 0x0, 0x0 }, /* BREG */ \
- { 0x10, 0x0, 0x0 }, /* SIREG */ \
- { 0x20, 0x0, 0x0 }, /* DIREG */ \
- { 0x03, 0x0, 0x0 }, /* AD_REGS */ \
- { 0x07, 0x0, 0x0 }, /* CLOBBERED_REGS */ \
- { 0x0f, 0x0, 0x0 }, /* Q_REGS */ \
- { 0x1100f0, 0x1fe0, 0x0 }, /* NON_Q_REGS */ \
- { 0x7e, 0x1fe0, 0x0 }, /* TLS_GOTBASE_REGS */ \
- { 0x7f, 0x1fe0, 0x0 }, /* INDEX_REGS */ \
- { 0x1100ff, 0x0, 0x0 }, /* LEGACY_REGS */ \
- { 0x1100ff, 0x1fe0, 0x0 }, /* GENERAL_REGS */ \
- { 0x100, 0x0, 0x0 }, /* FP_TOP_REG */ \
- { 0x0200, 0x0, 0x0 }, /* FP_SECOND_REG */ \
- { 0xff00, 0x0, 0x0 }, /* FLOAT_REGS */ \
- { 0x200000, 0x0, 0x0 }, /* SSE_FIRST_REG */ \
-{ 0x1fe00000, 0x000000, 0x0 }, /* NO_REX_SSE_REGS */ \
-{ 0x1fe00000, 0x1fe000, 0x0 }, /* SSE_REGS */ \
- { 0x0,0xffe00000, 0x1f }, /* EVEX_SSE_REGS */ \
-{ 0x1fe00000,0xffffe000, 0x1f }, /* ALL_SSE_REGS */ \
-{ 0xe0000000, 0x1f, 0x0 }, /* MMX_REGS */ \
-{ 0x1fe00100,0xffffe000, 0x1f }, /* FP_TOP_SSE_REG */ \
-{ 0x1fe00200,0xffffe000, 0x1f }, /* FP_SECOND_SSE_REG */ \
-{ 0x1fe0ff00,0xffffe000, 0x1f }, /* FLOAT_SSE_REGS */ \
-{ 0x11ffff, 0x1fe0, 0x0 }, /* FLOAT_INT_REGS */ \
-{ 0x1ff100ff,0xffffffe0, 0x1f }, /* INT_SSE_REGS */ \
-{ 0x1ff1ffff,0xffffffe0, 0x1f }, /* FLOAT_INT_SSE_REGS */ \
- { 0x0, 0x0, 0x1fc0 }, /* MASK_EVEX_REGS */ \
- { 0x0, 0x0, 0x1fe0 }, /* MASK_REGS */ \
-{ 0x1fe00000,0xffffe000, 0x1f }, /* MOD4_SSE_REGS */ \
-{ 0xffffffff,0xffffffff,0x1ffff } \
+#define REG_CLASS_CONTENTS \
+{ { 0x0, 0x0, 0x0 }, /* NO_REGS */ \
+ { 0x01, 0x0, 0x0 }, /* AREG */ \
+ { 0x02, 0x0, 0x0 }, /* DREG */ \
+ { 0x04, 0x0, 0x0 }, /* CREG */ \
+ { 0x08, 0x0, 0x0 }, /* BREG */ \
+ { 0x10, 0x0, 0x0 }, /* SIREG */ \
+ { 0x20, 0x0, 0x0 }, /* DIREG */ \
+ { 0x03, 0x0, 0x0 }, /* AD_REGS */ \
+ { 0x07, 0x0, 0x0 }, /* CLOBBERED_REGS */ \
+ { 0x0f, 0x0, 0x0 }, /* Q_REGS */ \
+ { 0x1100f0, 0x0, 0x0 }, /* NON_Q_REGS */ \
+ { 0x7e, 0x1fe0, 0x0 }, /* TLS_GOTBASE_REGS */ \
+ { 0x7f, 0x1fe0, 0x0 }, /* INDEX_REGS */ \
+ { 0x1100ff, 0x0, 0x0 }, /* LEGACY_REGS */ \
+ { 0x1100ff, 0x1fe0, 0x0 }, /* GENERAL_REGS */ \
+ { 0x100, 0x0, 0x0 }, /* FP_TOP_REG */ \
+ { 0x0200, 0x0, 0x0 }, /* FP_SECOND_REG */ \
+ { 0xff00, 0x0, 0x0 }, /* FLOAT_REGS */ \
+ { 0x200000, 0x0, 0x0 }, /* SSE_FIRST_REG */ \
+{ 0x1fe00000, 0x0, 0x0 }, /* NO_REX_SSE_REGS */ \
+{ 0x1fe00000, 0x1fe000, 0x0 }, /* SSE_REGS */ \
+{ 0x1fe00000, 0xffffe000, 0x1f }, /* ALL_SSE_REGS */ \
+{ 0xe0000000, 0x1f, 0x0 }, /* MMX_REGS */ \
+{ 0x1fe00100, 0xffffe000, 0x1f }, /* FP_TOP_SSE_REG */ \
+{ 0x1fe00200, 0xffffe000, 0x1f }, /* FP_SECOND_SSE_REG */ \
+{ 0x1fe0ff00, 0xffffe000, 0x1f }, /* FLOAT_SSE_REGS */ \
+{ 0x11ffff, 0x1fe0, 0x0 }, /* FLOAT_INT_REGS */ \
+{ 0x1ff100ff, 0xffffffe0, 0x1f }, /* INT_SSE_REGS */ \
+{ 0x1ff1ffff, 0xffffffe0, 0x1f }, /* FLOAT_INT_SSE_REGS */ \
+ { 0x0, 0x0, 0x1fc0 }, /* MASK_REGS */ \
+ { 0x0, 0x0, 0x1fe0 }, /* ALL_MASK_REGS */ \
+{ 0xffffffff, 0xffffffff, 0x1fff } /* ALL_REGS */ \
}
/* The same information, inverted:
@@ -2043,8 +2037,7 @@ do { \
"xmm20", "xmm21", "xmm22", "xmm23", \
"xmm24", "xmm25", "xmm26", "xmm27", \
"xmm28", "xmm29", "xmm30", "xmm31", \
- "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7", \
- "bnd0", "bnd1", "bnd2", "bnd3" }
+ "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7" }
#define REGISTER_NAMES HI_REGISTER_NAMES
@@ -2283,6 +2276,144 @@ enum processor_type
PROCESSOR_max
};
+#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS)
+extern const char *const processor_names[PROCESSOR_max];
+
+#include "wide-int-bitmask.h"
+
+const wide_int_bitmask PTA_3DNOW (HOST_WIDE_INT_1U << 0);
+const wide_int_bitmask PTA_3DNOW_A (HOST_WIDE_INT_1U << 1);
+const wide_int_bitmask PTA_64BIT (HOST_WIDE_INT_1U << 2);
+const wide_int_bitmask PTA_ABM (HOST_WIDE_INT_1U << 3);
+const wide_int_bitmask PTA_AES (HOST_WIDE_INT_1U << 4);
+const wide_int_bitmask PTA_AVX (HOST_WIDE_INT_1U << 5);
+const wide_int_bitmask PTA_BMI (HOST_WIDE_INT_1U << 6);
+const wide_int_bitmask PTA_CX16 (HOST_WIDE_INT_1U << 7);
+const wide_int_bitmask PTA_F16C (HOST_WIDE_INT_1U << 8);
+const wide_int_bitmask PTA_FMA (HOST_WIDE_INT_1U << 9);
+const wide_int_bitmask PTA_FMA4 (HOST_WIDE_INT_1U << 10);
+const wide_int_bitmask PTA_FSGSBASE (HOST_WIDE_INT_1U << 11);
+const wide_int_bitmask PTA_LWP (HOST_WIDE_INT_1U << 12);
+const wide_int_bitmask PTA_LZCNT (HOST_WIDE_INT_1U << 13);
+const wide_int_bitmask PTA_MMX (HOST_WIDE_INT_1U << 14);
+const wide_int_bitmask PTA_MOVBE (HOST_WIDE_INT_1U << 15);
+const wide_int_bitmask PTA_NO_SAHF (HOST_WIDE_INT_1U << 16);
+const wide_int_bitmask PTA_PCLMUL (HOST_WIDE_INT_1U << 17);
+const wide_int_bitmask PTA_POPCNT (HOST_WIDE_INT_1U << 18);
+const wide_int_bitmask PTA_PREFETCH_SSE (HOST_WIDE_INT_1U << 19);
+const wide_int_bitmask PTA_RDRND (HOST_WIDE_INT_1U << 20);
+const wide_int_bitmask PTA_SSE (HOST_WIDE_INT_1U << 21);
+const wide_int_bitmask PTA_SSE2 (HOST_WIDE_INT_1U << 22);
+const wide_int_bitmask PTA_SSE3 (HOST_WIDE_INT_1U << 23);
+const wide_int_bitmask PTA_SSE4_1 (HOST_WIDE_INT_1U << 24);
+const wide_int_bitmask PTA_SSE4_2 (HOST_WIDE_INT_1U << 25);
+const wide_int_bitmask PTA_SSE4A (HOST_WIDE_INT_1U << 26);
+const wide_int_bitmask PTA_SSSE3 (HOST_WIDE_INT_1U << 27);
+const wide_int_bitmask PTA_TBM (HOST_WIDE_INT_1U << 28);
+const wide_int_bitmask PTA_XOP (HOST_WIDE_INT_1U << 29);
+const wide_int_bitmask PTA_AVX2 (HOST_WIDE_INT_1U << 30);
+const wide_int_bitmask PTA_BMI2 (HOST_WIDE_INT_1U << 31);
+const wide_int_bitmask PTA_RTM (HOST_WIDE_INT_1U << 32);
+const wide_int_bitmask PTA_HLE (HOST_WIDE_INT_1U << 33);
+const wide_int_bitmask PTA_PRFCHW (HOST_WIDE_INT_1U << 34);
+const wide_int_bitmask PTA_RDSEED (HOST_WIDE_INT_1U << 35);
+const wide_int_bitmask PTA_ADX (HOST_WIDE_INT_1U << 36);
+const wide_int_bitmask PTA_FXSR (HOST_WIDE_INT_1U << 37);
+const wide_int_bitmask PTA_XSAVE (HOST_WIDE_INT_1U << 38);
+const wide_int_bitmask PTA_XSAVEOPT (HOST_WIDE_INT_1U << 39);
+const wide_int_bitmask PTA_AVX512F (HOST_WIDE_INT_1U << 40);
+const wide_int_bitmask PTA_AVX512ER (HOST_WIDE_INT_1U << 41);
+const wide_int_bitmask PTA_AVX512PF (HOST_WIDE_INT_1U << 42);
+const wide_int_bitmask PTA_AVX512CD (HOST_WIDE_INT_1U << 43);
+/* Hole after PTA_MPX was removed. */
+const wide_int_bitmask PTA_SHA (HOST_WIDE_INT_1U << 45);
+const wide_int_bitmask PTA_PREFETCHWT1 (HOST_WIDE_INT_1U << 46);
+const wide_int_bitmask PTA_CLFLUSHOPT (HOST_WIDE_INT_1U << 47);
+const wide_int_bitmask PTA_XSAVEC (HOST_WIDE_INT_1U << 48);
+const wide_int_bitmask PTA_XSAVES (HOST_WIDE_INT_1U << 49);
+const wide_int_bitmask PTA_AVX512DQ (HOST_WIDE_INT_1U << 50);
+const wide_int_bitmask PTA_AVX512BW (HOST_WIDE_INT_1U << 51);
+const wide_int_bitmask PTA_AVX512VL (HOST_WIDE_INT_1U << 52);
+const wide_int_bitmask PTA_AVX512IFMA (HOST_WIDE_INT_1U << 53);
+const wide_int_bitmask PTA_AVX512VBMI (HOST_WIDE_INT_1U << 54);
+const wide_int_bitmask PTA_CLWB (HOST_WIDE_INT_1U << 55);
+const wide_int_bitmask PTA_MWAITX (HOST_WIDE_INT_1U << 56);
+const wide_int_bitmask PTA_CLZERO (HOST_WIDE_INT_1U << 57);
+const wide_int_bitmask PTA_NO_80387 (HOST_WIDE_INT_1U << 58);
+const wide_int_bitmask PTA_PKU (HOST_WIDE_INT_1U << 59);
+const wide_int_bitmask PTA_AVX5124VNNIW (HOST_WIDE_INT_1U << 60);
+const wide_int_bitmask PTA_AVX5124FMAPS (HOST_WIDE_INT_1U << 61);
+const wide_int_bitmask PTA_AVX512VPOPCNTDQ (HOST_WIDE_INT_1U << 62);
+const wide_int_bitmask PTA_SGX (HOST_WIDE_INT_1U << 63);
+const wide_int_bitmask PTA_AVX512VNNI (0, HOST_WIDE_INT_1U);
+const wide_int_bitmask PTA_GFNI (0, HOST_WIDE_INT_1U << 1);
+const wide_int_bitmask PTA_VAES (0, HOST_WIDE_INT_1U << 2);
+const wide_int_bitmask PTA_AVX512VBMI2 (0, HOST_WIDE_INT_1U << 3);
+const wide_int_bitmask PTA_VPCLMULQDQ (0, HOST_WIDE_INT_1U << 4);
+const wide_int_bitmask PTA_AVX512BITALG (0, HOST_WIDE_INT_1U << 5);
+const wide_int_bitmask PTA_RDPID (0, HOST_WIDE_INT_1U << 6);
+const wide_int_bitmask PTA_PCONFIG (0, HOST_WIDE_INT_1U << 7);
+const wide_int_bitmask PTA_WBNOINVD (0, HOST_WIDE_INT_1U << 8);
+const wide_int_bitmask PTA_WAITPKG (0, HOST_WIDE_INT_1U << 9);
+
+const wide_int_bitmask PTA_CORE2 = PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2
+ | PTA_SSE3 | PTA_SSSE3 | PTA_CX16 | PTA_FXSR;
+const wide_int_bitmask PTA_NEHALEM = PTA_CORE2 | PTA_SSE4_1 | PTA_SSE4_2
+ | PTA_POPCNT;
+const wide_int_bitmask PTA_WESTMERE = PTA_NEHALEM | PTA_AES | PTA_PCLMUL;
+const wide_int_bitmask PTA_SANDYBRIDGE = PTA_WESTMERE | PTA_AVX | PTA_XSAVE
+ | PTA_XSAVEOPT;
+const wide_int_bitmask PTA_IVYBRIDGE = PTA_SANDYBRIDGE | PTA_FSGSBASE
+ | PTA_RDRND | PTA_F16C;
+const wide_int_bitmask PTA_HASWELL = PTA_IVYBRIDGE | PTA_AVX2 | PTA_BMI
+ | PTA_BMI2 | PTA_LZCNT | PTA_FMA | PTA_MOVBE | PTA_HLE;
+const wide_int_bitmask PTA_BROADWELL = PTA_HASWELL | PTA_ADX | PTA_PRFCHW
+ | PTA_RDSEED;
+const wide_int_bitmask PTA_SKYLAKE = PTA_BROADWELL | PTA_CLFLUSHOPT
+ | PTA_XSAVEC | PTA_XSAVES | PTA_SGX;
+const wide_int_bitmask PTA_SKYLAKE_AVX512 = PTA_SKYLAKE | PTA_AVX512F
+ | PTA_AVX512CD | PTA_AVX512VL | PTA_AVX512BW | PTA_AVX512DQ | PTA_PKU
+ | PTA_CLWB;
+const wide_int_bitmask PTA_CANNONLAKE = PTA_SKYLAKE | PTA_AVX512F
+ | PTA_AVX512CD | PTA_AVX512VL | PTA_AVX512BW | PTA_AVX512DQ | PTA_PKU
+ | PTA_AVX512VBMI | PTA_AVX512IFMA | PTA_SHA;
+const wide_int_bitmask PTA_ICELAKE_CLIENT = PTA_CANNONLAKE | PTA_AVX512VNNI
+ | PTA_GFNI | PTA_VAES | PTA_AVX512VBMI2 | PTA_VPCLMULQDQ | PTA_AVX512BITALG
+ | PTA_RDPID | PTA_CLWB;
+const wide_int_bitmask PTA_ICELAKE_SERVER = PTA_ICELAKE_CLIENT | PTA_PCONFIG
+ | PTA_WBNOINVD;
+const wide_int_bitmask PTA_KNL = PTA_BROADWELL | PTA_AVX512PF | PTA_AVX512ER
+ | PTA_AVX512F | PTA_AVX512CD;
+const wide_int_bitmask PTA_BONNELL = PTA_CORE2 | PTA_MOVBE;
+const wide_int_bitmask PTA_SILVERMONT = PTA_WESTMERE | PTA_MOVBE | PTA_RDRND;
+const wide_int_bitmask PTA_GOLDMONT = PTA_SILVERMONT | PTA_SHA | PTA_XSAVE
+ | PTA_RDSEED | PTA_XSAVEC | PTA_XSAVES | PTA_CLFLUSHOPT | PTA_XSAVEOPT
+ | PTA_FSGSBASE;
+const wide_int_bitmask PTA_GOLDMONT_PLUS = PTA_GOLDMONT | PTA_RDPID
+ | PTA_SGX;
+const wide_int_bitmask PTA_TREMONT = PTA_GOLDMONT_PLUS | PTA_CLWB
+ | PTA_GFNI;
+const wide_int_bitmask PTA_KNM = PTA_KNL | PTA_AVX5124VNNIW
+ | PTA_AVX5124FMAPS | PTA_AVX512VPOPCNTDQ;
+
+#ifndef GENERATOR_FILE
+
+#include "insn-attr-common.h"
+
+struct pta
+{
+ const char *const name; /* processor name or nickname. */
+ const enum processor_type processor;
+ const enum attr_cpu schedule;
+ const wide_int_bitmask flags;
+};
+
+extern const pta processor_alias_table[];
+extern int const pta_size;
+#endif
+
+#endif
+
extern enum processor_type ix86_tune;
extern enum processor_type ix86_arch;
@@ -2616,6 +2747,9 @@ struct GTY(()) machine_function {
/* Nonzero if the function places outgoing arguments on stack. */
BOOL_BITFIELD outgoing_args_on_stack : 1;
+ /* If true, ENDBR is queued at function entrance. */
+ BOOL_BITFIELD endbr_queued_at_entrance : 1;
+
/* The largest alignment, in bytes, of stack slot actually used. */
unsigned int max_used_stack_alignment;
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 559ad93..e08b2b7 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -184,16 +184,6 @@
UNSPEC_PDEP
UNSPEC_PEXT
- UNSPEC_BNDMK
- UNSPEC_BNDMK_ADDR
- UNSPEC_BNDSTX
- UNSPEC_BNDLDX
- UNSPEC_BNDLDX_ADDR
- UNSPEC_BNDCL
- UNSPEC_BNDCU
- UNSPEC_BNDCN
- UNSPEC_MPX_FENCE
-
;; IRET support
UNSPEC_INTERRUPT_RETURN
])
@@ -301,6 +291,9 @@
;; For CLDEMOTE support
UNSPECV_CLDEMOTE
+
+ ;; For Speculation Barrier support
+ UNSPECV_SPECULATION_BARRIER
])
;; Constants to represent rounding modes in the ROUND instruction
@@ -425,11 +418,7 @@
(MASK5_REG 74)
(MASK6_REG 75)
(MASK7_REG 76)
- (BND0_REG 77)
- (BND1_REG 78)
- (BND2_REG 79)
- (BND3_REG 80)
- (FIRST_PSEUDO_REG 81)
+ (FIRST_PSEUDO_REG 77)
])
;; Insns whose names begin with "x86_" are emitted by gen_FOO calls
@@ -464,8 +453,7 @@
ssecvt,ssecvt1,sseicvt,sseins,
sseshuf,sseshuf1,ssemuladd,sse4arg,
lwp,mskmov,msklog,
- mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft,
- mpxmov,mpxmk,mpxchk,mpxld,mpxst"
+ mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft"
(const_string "other"))
;; Main data type used by the insn
@@ -494,8 +482,7 @@
;; The (bounding maximum) length of an instruction immediate.
(define_attr "length_immediate" ""
(cond [(eq_attr "type" "incdec,setcc,icmov,str,lea,other,multi,idiv,leave,
- bitmanip,imulx,msklog,mskmov,mpxmk,mpxmov,mpxchk,
- mpxld,mpxst")
+ bitmanip,imulx,msklog,mskmov")
(const_int 0)
(eq_attr "unit" "i387,sse,mmx")
(const_int 0)
@@ -556,8 +543,7 @@
;; Set when 0f opcode prefix is used.
(define_attr "prefix_0f" ""
(if_then_else
- (ior (eq_attr "type" "imovx,setcc,icmov,bitmanip,msklog,mskmov,
- mpxmk,mpxmov,mpxchk,mpxld,mpxst")
+ (ior (eq_attr "type" "imovx,setcc,icmov,bitmanip,msklog,mskmov")
(eq_attr "unit" "sse,mmx"))
(const_int 1)
(const_int 0)))
@@ -660,19 +646,6 @@
]
(const_int 1)))
-(define_attr "modrm_class" "none,incdec,op0,op01,op02,pushpop,unknown"
- (cond [(eq_attr "modrm" "0")
- (const_string "none")
- (eq_attr "type" "alu,imul,ishift")
- (const_string "op02")
- (eq_attr "type" "imov,imovx,lea,alu1,icmp")
- (const_string "op01")
- (eq_attr "type" "incdec")
- (const_string "incdec")
- (eq_attr "type" "push,pop")
- (const_string "pushpop")]
- (const_string "unknown")))
-
;; The (bounding maximum) length of an instruction in bytes.
;; ??? fistp and frndint are in fact fldcw/{fistp,frndint}/fldcw sequences.
;; Later we may want to split them and compute proper length as for
@@ -719,16 +692,12 @@
(define_attr "memory" "none,load,store,both,unknown"
(cond [(eq_attr "type" "other,multi,str,lwp")
(const_string "unknown")
- (eq_attr "type" "lea,fcmov,fpspc,mpxmk,mpxchk")
+ (eq_attr "type" "lea,fcmov,fpspc")
(const_string "none")
(eq_attr "type" "fistp,leave")
(const_string "both")
(eq_attr "type" "frndint")
(const_string "load")
- (eq_attr "type" "mpxld")
- (const_string "load")
- (eq_attr "type" "mpxst")
- (const_string "store")
(eq_attr "type" "push")
(if_then_else (match_operand 1 "memory_operand")
(const_string "both")
@@ -774,7 +743,7 @@
fmov,fcmp,fsgn,
sse,ssemov,ssecmp,ssecomi,ssecvt,ssecvt1,sseicvt,
sselog1,sseshuf1,sseadd1,sseiadd1,sseishft1,
- mmx,mmxmov,mmxcmp,mmxcvt,mskmov,msklog,mpxmov")
+ mmx,mmxmov,mmxcmp,mmxcvt,mskmov,msklog")
(match_operand 2 "memory_operand"))
(const_string "load")
(and (eq_attr "type" "icmov,ssemuladd,sse4arg")
@@ -1064,10 +1033,6 @@
(define_mode_iterator DWIH [(SI "!TARGET_64BIT")
(DI "TARGET_64BIT")])
-;; Bound modes.
-(define_mode_iterator BND [(BND32 "!TARGET_LP64")
- (BND64 "TARGET_LP64")])
-
;; Instruction suffix for integer modes.
(define_mode_attr imodesuffix [(QI "b") (HI "w") (SI "l") (DI "q")])
@@ -1296,7 +1261,6 @@
ktest<mskmodesuffix>\t%0, %0"
[(set_attr "type" "test,icmp,msklog")
(set_attr "length_immediate" "0,1,*")
- (set_attr "modrm_class" "op0,unknown,*")
(set_attr "prefix" "*,*,vex")
(set_attr "mode" "<MODE>")])
@@ -1310,7 +1274,6 @@
cmp{<imodesuffix>}\t{%1, %0|%0, %1}"
[(set_attr "type" "test,icmp")
(set_attr "length_immediate" "0,1")
- (set_attr "modrm_class" "op0,unknown")
(set_attr "mode" "<MODE>")])
(define_insn "*cmp<mode>_1"
@@ -2025,7 +1988,6 @@
"reload_completed"
"xor{l}\t%k0, %k0"
[(set_attr "type" "alu1")
- (set_attr "modrm_class" "op0")
(set_attr "mode" "SI")
(set_attr "length_immediate" "0")])
@@ -2910,7 +2872,6 @@
"reload_completed"
"xor{<imodesuffix>}\t%0, %0"
[(set_attr "type" "alu1")
- (set_attr "modrm_class" "op0")
(set_attr "mode" "<MODE>")
(set_attr "length_immediate" "0")])
@@ -3865,7 +3826,7 @@
(define_split
[(set (match_operand 0 "any_fp_register_operand")
- (match_operand 1 "nonimmediate_operand"))]
+ (match_operand 1 "memory_operand"))]
"reload_completed
&& (GET_MODE (operands[0]) == TFmode
|| GET_MODE (operands[0]) == XFmode
@@ -3877,7 +3838,7 @@
(define_split
[(set (match_operand 0 "any_fp_register_operand")
- (float_extend (match_operand 1 "nonimmediate_operand")))]
+ (float_extend (match_operand 1 "memory_operand")))]
"reload_completed
&& (GET_MODE (operands[0]) == TFmode
|| GET_MODE (operands[0]) == XFmode
@@ -3903,7 +3864,7 @@
operands[1] = CONST1_RTX (<MODE>mode);
})
-(define_insn "swapxf"
+(define_insn "*swapxf"
[(set (match_operand:XF 0 "register_operand" "+f")
(match_operand:XF 1 "register_operand" "+f"))
(set (match_dup 1)
@@ -3917,22 +3878,8 @@
}
[(set_attr "type" "fxch")
(set_attr "mode" "XF")])
-
-(define_insn "*swap<mode>"
- [(set (match_operand:MODEF 0 "fp_register_operand" "+f")
- (match_operand:MODEF 1 "fp_register_operand" "+f"))
- (set (match_dup 1)
- (match_dup 0))]
- "TARGET_80387 || reload_completed"
-{
- if (STACK_TOP_P (operands[0]))
- return "fxch\t%1";
- else
- return "fxch\t%0";
-}
- [(set_attr "type" "fxch")
- (set_attr "mode" "<MODE>")])
+
;; Zero extension instructions
(define_expand "zero_extendsidi2"
@@ -4509,6 +4456,40 @@
}
})
+(define_insn "*extendsfdf2"
+ [(set (match_operand:DF 0 "nonimm_ssenomem_operand" "=f,m,v")
+ (float_extend:DF
+ (match_operand:SF 1 "nonimmediate_operand" "fm,f,vm")))]
+ "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ case 1:
+ return output_387_reg_move (insn, operands);
+
+ case 2:
+ return "%vcvtss2sd\t{%1, %d0|%d0, %1}";
+
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "fmov,fmov,ssecvt")
+ (set_attr "prefix" "orig,orig,maybe_vex")
+ (set_attr "mode" "SF,XF,DF")
+ (set (attr "enabled")
+ (if_then_else
+ (match_test ("TARGET_SSE2 && TARGET_SSE_MATH"))
+ (if_then_else
+ (eq_attr "alternative" "0,1")
+ (symbol_ref "TARGET_MIX_SSE_I387")
+ (symbol_ref "true"))
+ (if_then_else
+ (eq_attr "alternative" "0,1")
+ (symbol_ref "true")
+ (symbol_ref "false"))))])
+
/* For converting SF(xmm2) to DF(xmm1), use the following code instead of
cvtss2sd:
unpcklps xmm2,xmm2 ; packed conversion might crash on signaling NaNs
@@ -4576,39 +4557,31 @@
(set (match_dup 0) (float_extend:DF (match_dup 2)))]
"operands[2] = lowpart_subreg (SFmode, operands[0], DFmode);")
-(define_insn "*extendsfdf2"
- [(set (match_operand:DF 0 "nonimm_ssenomem_operand" "=f,m,v")
+;; Break partial reg stall for cvtss2sd. This splitter should split
+;; late in the pass sequence (after register rename pass),
+;; so allocated registers won't change anymore.
+
+(define_split
+ [(set (match_operand:DF 0 "sse_reg_operand")
(float_extend:DF
- (match_operand:SF 1 "nonimmediate_operand" "fm,f,vm")))]
- "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
+ (match_operand:SF 1 "nonimmediate_operand")))]
+ "TARGET_SSE_PARTIAL_REG_DEPENDENCY && epilogue_completed
+ && optimize_function_for_speed_p (cfun)
+ && (!REG_P (operands[1])
+ || REGNO (operands[0]) != REGNO (operands[1]))
+ && (!EXT_REX_SSE_REG_P (operands[0])
+ || TARGET_AVX512VL)"
+ [(set (match_dup 0)
+ (vec_merge:V2DF
+ (vec_duplicate:V2DF
+ (float_extend:DF
+ (match_dup 1)))
+ (match_dup 0)
+ (const_int 1)))]
{
- switch (which_alternative)
- {
- case 0:
- case 1:
- return output_387_reg_move (insn, operands);
-
- case 2:
- return "%vcvtss2sd\t{%1, %d0|%d0, %1}";
-
- default:
- gcc_unreachable ();
- }
-}
- [(set_attr "type" "fmov,fmov,ssecvt")
- (set_attr "prefix" "orig,orig,maybe_vex")
- (set_attr "mode" "SF,XF,DF")
- (set (attr "enabled")
- (if_then_else
- (match_test ("TARGET_SSE2 && TARGET_SSE_MATH"))
- (if_then_else
- (eq_attr "alternative" "0,1")
- (symbol_ref "TARGET_MIX_SSE_I387")
- (symbol_ref "true"))
- (if_then_else
- (eq_attr "alternative" "0,1")
- (symbol_ref "true")
- (symbol_ref "false"))))])
+ operands[0] = lowpart_subreg (V2DFmode, operands[0], DFmode);
+ emit_move_insn (operands[0], CONST0_RTX (V2DFmode));
+})
(define_expand "extend<mode>xf2"
[(set (match_operand:XF 0 "nonimmediate_operand")
@@ -4647,23 +4620,43 @@
;; Conversion from DFmode to SFmode.
-(define_expand "truncdfsf2"
- [(set (match_operand:SF 0 "nonimmediate_operand")
+(define_insn "truncdfsf2"
+ [(set (match_operand:SF 0 "nonimm_ssenomem_operand" "=m,f,v")
(float_truncate:SF
- (match_operand:DF 1 "nonimmediate_operand")))]
+ (match_operand:DF 1 "register_ssemem_operand" "f,f,vm")))]
"TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
{
- if (TARGET_SSE2 && TARGET_SSE_MATH && !TARGET_MIX_SSE_I387)
- ;
- else if (flag_unsafe_math_optimizations)
- ;
- else
+ switch (which_alternative)
{
- rtx temp = assign_386_stack_local (SFmode, SLOT_TEMP);
- emit_insn (gen_truncdfsf2_with_temp (operands[0], operands[1], temp));
- DONE;
+ case 0:
+ case 1:
+ return output_387_reg_move (insn, operands);
+
+ case 2:
+ return "%vcvtsd2ss\t{%1, %d0|%d0, %1}";
+
+ default:
+ gcc_unreachable ();
}
-})
+}
+ [(set_attr "type" "fmov,fmov,ssecvt")
+ (set_attr "mode" "SF")
+ (set (attr "enabled")
+ (if_then_else
+ (match_test ("TARGET_SSE2 && TARGET_SSE_MATH"))
+ (cond [(eq_attr "alternative" "0")
+ (symbol_ref "TARGET_MIX_SSE_I387")
+ (eq_attr "alternative" "1")
+ (symbol_ref "TARGET_MIX_SSE_I387
+ && flag_unsafe_math_optimizations")
+ ]
+ (symbol_ref "true"))
+ (cond [(eq_attr "alternative" "0")
+ (symbol_ref "true")
+ (eq_attr "alternative" "1")
+ (symbol_ref "flag_unsafe_math_optimizations")
+ ]
+ (symbol_ref "false"))))])
/* For converting DF(xmm2) to SF(xmm1), use the following code instead of
cvtsd2ss:
@@ -4674,7 +4667,7 @@
anyway. */
(define_split
[(set (match_operand:SF 0 "sse_reg_operand")
- (float_truncate:SF
+ (float_truncate:SF
(match_operand:DF 1 "nonimmediate_operand")))]
"TARGET_USE_VECTOR_FP_CONVERTS
&& optimize_insn_for_speed_p ()
@@ -4711,7 +4704,7 @@
CONST0_RTX (DFmode)));
})
-;; It's more profitable to split and then extend in the same register.
+;; It's more profitable to split and then truncate in the same register.
(define_peephole2
[(set (match_operand:SF 0 "sse_reg_operand")
(float_truncate:SF
@@ -4722,197 +4715,47 @@
(set (match_dup 0) (float_truncate:SF (match_dup 2)))]
"operands[2] = lowpart_subreg (DFmode, operands[0], SFmode);")
-(define_expand "truncdfsf2_with_temp"
- [(parallel [(set (match_operand:SF 0)
- (float_truncate:SF (match_operand:DF 1)))
- (clobber (match_operand:SF 2))])])
-
-;; SSE alternative doesn't depend on flag_unsafe_math_optimizations,
-;; because nothing we do there is unsafe.
-(define_insn "*truncdfsf_fast_mixed"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=fm,v")
- (float_truncate:SF
- (match_operand:DF 1 "nonimmediate_operand" "f ,vm")))]
- "TARGET_SSE2 && TARGET_SSE_MATH"
-{
- switch (which_alternative)
- {
- case 0:
- return output_387_reg_move (insn, operands);
- case 1:
- return "%vcvtsd2ss\t{%1, %d0|%d0, %1}";
- default:
- gcc_unreachable ();
- }
-}
- [(set_attr "type" "fmov,ssecvt")
- (set_attr "prefix" "orig,maybe_vex")
- (set_attr "mode" "SF")
- (set (attr "enabled")
- (cond [(eq_attr "alternative" "0")
- (symbol_ref "TARGET_MIX_SSE_I387
- && flag_unsafe_math_optimizations")
- ]
- (symbol_ref "true")))])
-
-(define_insn "*truncdfsf_fast_i387"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=fm")
- (float_truncate:SF
- (match_operand:DF 1 "nonimmediate_operand" "f")))]
- "TARGET_80387 && flag_unsafe_math_optimizations"
- "* return output_387_reg_move (insn, operands);"
- [(set_attr "type" "fmov")
- (set_attr "mode" "SF")])
-
-(define_insn "*truncdfsf_mixed"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=m,v ,?f,?v,?*r")
- (float_truncate:SF
- (match_operand:DF 1 "nonimmediate_operand" "f ,vm,f ,f ,f")))
- (clobber (match_operand:SF 2 "memory_operand" "=X,X ,m ,m ,m"))]
- "TARGET_MIX_SSE_I387"
-{
- switch (which_alternative)
- {
- case 0:
- return output_387_reg_move (insn, operands);
- case 1:
- return "%vcvtsd2ss\t{%1, %d0|%d0, %1}";
-
- default:
- return "#";
- }
-}
- [(set_attr "isa" "*,sse2,*,*,*")
- (set_attr "type" "fmov,ssecvt,multi,multi,multi")
- (set_attr "unit" "*,*,i387,i387,i387")
- (set_attr "prefix" "orig,maybe_vex,orig,orig,orig")
- (set_attr "mode" "SF")])
-
-(define_insn "*truncdfsf_i387"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?v,?*r")
- (float_truncate:SF
- (match_operand:DF 1 "nonimmediate_operand" "f ,f ,f ,f")))
- (clobber (match_operand:SF 2 "memory_operand" "=X,m ,m ,m"))]
- "TARGET_80387"
-{
- switch (which_alternative)
- {
- case 0:
- return output_387_reg_move (insn, operands);
-
- default:
- return "#";
- }
-}
- [(set_attr "type" "fmov,multi,multi,multi")
- (set_attr "unit" "*,i387,i387,i387")
- (set_attr "mode" "SF")])
-
-(define_insn "*truncdfsf2_i387_1"
- [(set (match_operand:SF 0 "memory_operand" "=m")
- (float_truncate:SF
- (match_operand:DF 1 "register_operand" "f")))]
- "TARGET_80387
- && !(TARGET_SSE2 && TARGET_SSE_MATH)
- && !TARGET_MIX_SSE_I387"
- "* return output_387_reg_move (insn, operands);"
- [(set_attr "type" "fmov")
- (set_attr "mode" "SF")])
+;; Break partial reg stall for cvtsd2ss. This splitter should split
+;; late in the pass sequence (after register rename pass),
+;; so allocated registers won't change anymore.
(define_split
- [(set (match_operand:SF 0 "register_operand")
- (float_truncate:SF
- (match_operand:DF 1 "fp_register_operand")))
- (clobber (match_operand 2))]
- "reload_completed"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 0) (match_dup 2))]
- "operands[1] = gen_rtx_REG (SFmode, REGNO (operands[1]));")
-
-;; Conversion from XFmode to {SF,DF}mode
-
-(define_expand "truncxf<mode>2"
- [(parallel [(set (match_operand:MODEF 0 "nonimmediate_operand")
- (float_truncate:MODEF
- (match_operand:XF 1 "register_operand")))
- (clobber (match_dup 2))])]
- "TARGET_80387"
+ [(set (match_operand:SF 0 "sse_reg_operand")
+ (float_truncate:SF
+ (match_operand:DF 1 "nonimmediate_operand")))]
+ "TARGET_SSE_PARTIAL_REG_DEPENDENCY && epilogue_completed
+ && optimize_function_for_speed_p (cfun)
+ && (!REG_P (operands[1])
+ || REGNO (operands[0]) != REGNO (operands[1]))
+ && (!EXT_REX_SSE_REG_P (operands[0])
+ || TARGET_AVX512VL)"
+ [(set (match_dup 0)
+ (vec_merge:V4SF
+ (vec_duplicate:V4SF
+ (float_truncate:SF
+ (match_dup 1)))
+ (match_dup 0)
+ (const_int 1)))]
{
- if (flag_unsafe_math_optimizations)
- {
- rtx reg = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (<MODE>mode);
- emit_insn (gen_truncxf<mode>2_i387_noop (reg, operands[1]));
- if (reg != operands[0])
- emit_move_insn (operands[0], reg);
- DONE;
- }
- else
- operands[2] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
+ operands[0] = lowpart_subreg (V4SFmode, operands[0], SFmode);
+ emit_move_insn (operands[0], CONST0_RTX (V4SFmode));
})
-(define_insn "*truncxfsf2_mixed"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?v,?*r")
- (float_truncate:SF
- (match_operand:XF 1 "register_operand" "f ,f ,f ,f")))
- (clobber (match_operand:SF 2 "memory_operand" "=X,m ,m ,m"))]
- "TARGET_80387"
-{
- gcc_assert (!which_alternative);
- return output_387_reg_move (insn, operands);
-}
- [(set_attr "type" "fmov,multi,multi,multi")
- (set_attr "unit" "*,i387,i387,i387")
- (set_attr "mode" "SF")])
-
-(define_insn "*truncxfdf2_mixed"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?v,?*r")
- (float_truncate:DF
- (match_operand:XF 1 "register_operand" "f ,f ,f ,f")))
- (clobber (match_operand:DF 2 "memory_operand" "=X,m ,m ,m"))]
- "TARGET_80387"
-{
- gcc_assert (!which_alternative);
- return output_387_reg_move (insn, operands);
-}
- [(set_attr "isa" "*,*,sse2,*")
- (set_attr "type" "fmov,multi,multi,multi")
- (set_attr "unit" "*,i387,i387,i387")
- (set_attr "mode" "DF")])
-
-(define_insn "truncxf<mode>2_i387_noop"
- [(set (match_operand:MODEF 0 "register_operand" "=f")
- (float_truncate:MODEF
- (match_operand:XF 1 "register_operand" "f")))]
- "TARGET_80387 && flag_unsafe_math_optimizations"
- "* return output_387_reg_move (insn, operands);"
- [(set_attr "type" "fmov")
- (set_attr "mode" "<MODE>")])
+;; Conversion from XFmode to {SF,DF}mode
-(define_insn "*truncxf<mode>2_i387"
- [(set (match_operand:MODEF 0 "memory_operand" "=m")
+(define_insn "truncxf<mode>2"
+ [(set (match_operand:MODEF 0 "nonimmediate_operand" "=m,f")
(float_truncate:MODEF
- (match_operand:XF 1 "register_operand" "f")))]
+ (match_operand:XF 1 "register_operand" "f,f")))]
"TARGET_80387"
"* return output_387_reg_move (insn, operands);"
[(set_attr "type" "fmov")
- (set_attr "mode" "<MODE>")])
-
-(define_split
- [(set (match_operand:MODEF 0 "register_operand")
- (float_truncate:MODEF
- (match_operand:XF 1 "register_operand")))
- (clobber (match_operand:MODEF 2 "memory_operand"))]
- "TARGET_80387 && reload_completed"
- [(set (match_dup 2) (float_truncate:MODEF (match_dup 1)))
- (set (match_dup 0) (match_dup 2))])
-
-(define_split
- [(set (match_operand:MODEF 0 "memory_operand")
- (float_truncate:MODEF
- (match_operand:XF 1 "register_operand")))
- (clobber (match_operand:MODEF 2 "memory_operand"))]
- "TARGET_80387"
- [(set (match_dup 0) (float_truncate:MODEF (match_dup 1)))])
+ (set_attr "mode" "<MODE>")
+ (set (attr "enabled")
+ (cond [(eq_attr "alternative" "1")
+ (symbol_ref "flag_unsafe_math_optimizations")
+ ]
+ (symbol_ref "true")))])
;; Signed conversion to DImode.
@@ -4924,7 +4767,7 @@
{
if (TARGET_FISTTP)
{
- emit_insn (gen_fix_truncdi_fisttp_i387_1 (operands[0], operands[1]));
+ emit_insn (gen_fix_truncdi_i387_fisttp (operands[0], operands[1]));
DONE;
}
})
@@ -4938,7 +4781,7 @@
if (TARGET_FISTTP
&& !(TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))
{
- emit_insn (gen_fix_truncdi_fisttp_i387_1 (operands[0], operands[1]));
+ emit_insn (gen_fix_truncdi_i387_fisttp (operands[0], operands[1]));
DONE;
}
if (TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode))
@@ -4961,7 +4804,7 @@
{
if (TARGET_FISTTP)
{
- emit_insn (gen_fix_truncsi_fisttp_i387_1 (operands[0], operands[1]));
+ emit_insn (gen_fix_truncsi_i387_fisttp (operands[0], operands[1]));
DONE;
}
})
@@ -4975,7 +4818,7 @@
if (TARGET_FISTTP
&& !(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))
{
- emit_insn (gen_fix_truncsi_fisttp_i387_1 (operands[0], operands[1]));
+ emit_insn (gen_fix_truncsi_i387_fisttp (operands[0], operands[1]));
DONE;
}
if (SSE_FLOAT_MODE_P (<MODE>mode))
@@ -4999,7 +4842,7 @@
{
if (TARGET_FISTTP)
{
- emit_insn (gen_fix_trunchi_fisttp_i387_1 (operands[0], operands[1]));
+ emit_insn (gen_fix_trunchi_i387_fisttp (operands[0], operands[1]));
DONE;
}
})
@@ -5063,7 +4906,7 @@
(zero_extend:DI
(unsigned_fix:SI
(match_operand:MODEF 1 "nonimmediate_operand" "vm"))))]
- "TARGET_64BIT && TARGET_AVX512F"
+ "TARGET_64BIT && TARGET_AVX512F && TARGET_SSE_MATH"
"vcvtt<ssemodesuffix>2usi\t{%1, %k0|%k0, %1}"
[(set_attr "type" "sseicvt")
(set_attr "prefix" "evex")
@@ -5128,35 +4971,8 @@
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (fix:SWI48 (match_dup 2)))])
-(define_insn_and_split "fix_trunc<mode>_fisttp_i387_1"
- [(set (match_operand:SWI248x 0 "nonimmediate_operand")
- (fix:SWI248x (match_operand 1 "register_operand")))]
- "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
- && TARGET_FISTTP
- && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
- && (TARGET_64BIT || <MODE>mode != DImode))
- && TARGET_SSE_MATH)
- && can_create_pseudo_p ()"
- "#"
- "&& 1"
- [(const_int 0)]
-{
- if (memory_operand (operands[0], VOIDmode))
- emit_insn (gen_fix_trunc<mode>_i387_fisttp (operands[0], operands[1]));
- else
- {
- operands[2] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
- emit_insn (gen_fix_trunc<mode>_i387_fisttp_with_temp (operands[0],
- operands[1],
- operands[2]));
- }
- DONE;
-}
- [(set_attr "type" "fisttp")
- (set_attr "mode" "<MODE>")])
-
(define_insn "fix_trunc<mode>_i387_fisttp"
- [(set (match_operand:SWI248x 0 "memory_operand" "=m")
+ [(set (match_operand:SWI248x 0 "nonimmediate_operand" "=m")
(fix:SWI248x (match_operand 1 "register_operand" "f")))
(clobber (match_scratch:XF 2 "=&1f"))]
"X87_FLOAT_MODE_P (GET_MODE (operands[1]))
@@ -5168,39 +4984,6 @@
[(set_attr "type" "fisttp")
(set_attr "mode" "<MODE>")])
-(define_insn "fix_trunc<mode>_i387_fisttp_with_temp"
- [(set (match_operand:SWI248x 0 "nonimmediate_operand" "=m,?r")
- (fix:SWI248x (match_operand 1 "register_operand" "f,f")))
- (clobber (match_operand:SWI248x 2 "memory_operand" "=X,m"))
- (clobber (match_scratch:XF 3 "=&1f,&1f"))]
- "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
- && TARGET_FISTTP
- && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
- && (TARGET_64BIT || <MODE>mode != DImode))
- && TARGET_SSE_MATH)"
- "#"
- [(set_attr "type" "fisttp")
- (set_attr "mode" "<MODE>")])
-
-(define_split
- [(set (match_operand:SWI248x 0 "register_operand")
- (fix:SWI248x (match_operand 1 "register_operand")))
- (clobber (match_operand:SWI248x 2 "memory_operand"))
- (clobber (match_scratch 3))]
- "reload_completed"
- [(parallel [(set (match_dup 2) (fix:SWI248x (match_dup 1)))
- (clobber (match_dup 3))])
- (set (match_dup 0) (match_dup 2))])
-
-(define_split
- [(set (match_operand:SWI248x 0 "memory_operand")
- (fix:SWI248x (match_operand 1 "register_operand")))
- (clobber (match_operand:SWI248x 2 "memory_operand"))
- (clobber (match_scratch 3))]
- "reload_completed"
- [(parallel [(set (match_dup 0) (fix:SWI248x (match_dup 1)))
- (clobber (match_dup 3))])])
-
;; See the comments in i386.h near OPTIMIZE_MODE_SWITCHING for the description
;; of the machinery. Please note the clobber of FLAGS_REG. In i387 control
;; word calculation (inserted by LCM in mode switching pass) a FLAGS_REG
@@ -5223,16 +5006,9 @@
operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
operands[3] = assign_386_stack_local (HImode, SLOT_CW_TRUNC);
- if (memory_operand (operands[0], VOIDmode))
- emit_insn (gen_fix_trunc<mode>_i387 (operands[0], operands[1],
- operands[2], operands[3]));
- else
- {
- operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
- emit_insn (gen_fix_trunc<mode>_i387_with_temp (operands[0], operands[1],
- operands[2], operands[3],
- operands[4]));
- }
+
+ emit_insn (gen_fix_trunc<mode>_i387 (operands[0], operands[1],
+ operands[2], operands[3]));
DONE;
}
[(set_attr "type" "fistp")
@@ -5240,7 +5016,7 @@
(set_attr "mode" "<MODE>")])
(define_insn "fix_truncdi_i387"
- [(set (match_operand:DI 0 "memory_operand" "=m")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=m")
(fix:DI (match_operand 1 "register_operand" "f")))
(use (match_operand:HI 2 "memory_operand" "m"))
(use (match_operand:HI 3 "memory_operand" "m"))
@@ -5253,50 +5029,8 @@
(set_attr "i387_cw" "trunc")
(set_attr "mode" "DI")])
-(define_insn "fix_truncdi_i387_with_temp"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
- (fix:DI (match_operand 1 "register_operand" "f,f")))
- (use (match_operand:HI 2 "memory_operand" "m,m"))
- (use (match_operand:HI 3 "memory_operand" "m,m"))
- (clobber (match_operand:DI 4 "memory_operand" "=X,m"))
- (clobber (match_scratch:XF 5 "=&1f,&1f"))]
- "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
- && !TARGET_FISTTP
- && !(TARGET_64BIT && SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
- "#"
- [(set_attr "type" "fistp")
- (set_attr "i387_cw" "trunc")
- (set_attr "mode" "DI")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand")
- (fix:DI (match_operand 1 "register_operand")))
- (use (match_operand:HI 2 "memory_operand"))
- (use (match_operand:HI 3 "memory_operand"))
- (clobber (match_operand:DI 4 "memory_operand"))
- (clobber (match_scratch 5))]
- "reload_completed"
- [(parallel [(set (match_dup 4) (fix:DI (match_dup 1)))
- (use (match_dup 2))
- (use (match_dup 3))
- (clobber (match_dup 5))])
- (set (match_dup 0) (match_dup 4))])
-
-(define_split
- [(set (match_operand:DI 0 "memory_operand")
- (fix:DI (match_operand 1 "register_operand")))
- (use (match_operand:HI 2 "memory_operand"))
- (use (match_operand:HI 3 "memory_operand"))
- (clobber (match_operand:DI 4 "memory_operand"))
- (clobber (match_scratch 5))]
- "reload_completed"
- [(parallel [(set (match_dup 0) (fix:DI (match_dup 1)))
- (use (match_dup 2))
- (use (match_dup 3))
- (clobber (match_dup 5))])])
-
(define_insn "fix_trunc<mode>_i387"
- [(set (match_operand:SWI24 0 "memory_operand" "=m")
+ [(set (match_operand:SWI24 0 "nonimmediate_operand" "=m")
(fix:SWI24 (match_operand 1 "register_operand" "f")))
(use (match_operand:HI 2 "memory_operand" "m"))
(use (match_operand:HI 3 "memory_operand" "m"))]
@@ -5308,43 +5042,6 @@
(set_attr "i387_cw" "trunc")
(set_attr "mode" "<MODE>")])
-(define_insn "fix_trunc<mode>_i387_with_temp"
- [(set (match_operand:SWI24 0 "nonimmediate_operand" "=m,?r")
- (fix:SWI24 (match_operand 1 "register_operand" "f,f")))
- (use (match_operand:HI 2 "memory_operand" "m,m"))
- (use (match_operand:HI 3 "memory_operand" "m,m"))
- (clobber (match_operand:SWI24 4 "memory_operand" "=X,m"))]
- "X87_FLOAT_MODE_P (GET_MODE (operands[1]))
- && !TARGET_FISTTP
- && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
- "#"
- [(set_attr "type" "fistp")
- (set_attr "i387_cw" "trunc")
- (set_attr "mode" "<MODE>")])
-
-(define_split
- [(set (match_operand:SWI24 0 "register_operand")
- (fix:SWI24 (match_operand 1 "register_operand")))
- (use (match_operand:HI 2 "memory_operand"))
- (use (match_operand:HI 3 "memory_operand"))
- (clobber (match_operand:SWI24 4 "memory_operand"))]
- "reload_completed"
- [(parallel [(set (match_dup 4) (fix:SWI24 (match_dup 1)))
- (use (match_dup 2))
- (use (match_dup 3))])
- (set (match_dup 0) (match_dup 4))])
-
-(define_split
- [(set (match_operand:SWI24 0 "memory_operand")
- (fix:SWI24 (match_operand 1 "register_operand")))
- (use (match_operand:HI 2 "memory_operand"))
- (use (match_operand:HI 3 "memory_operand"))
- (clobber (match_operand:SWI24 4 "memory_operand"))]
- "reload_completed"
- [(parallel [(set (match_dup 0) (fix:SWI24 (match_dup 1)))
- (use (match_dup 2))
- (use (match_dup 3))])])
-
(define_insn "x86_fnstcw_1"
[(set (match_operand:HI 0 "memory_operand" "=m")
(unspec:HI [(reg:HI FPCR_REG)] UNSPEC_FSTCW))]
@@ -5397,36 +5094,19 @@
(set_attr "znver1_decode" "double")
(set_attr "fp_int_src" "true")])
-(define_expand "float<SWI48:mode><MODEF:mode>2"
+(define_expand "float<SWI48x:mode><MODEF:mode>2"
[(set (match_operand:MODEF 0 "register_operand")
- (float:MODEF (match_operand:SWI48 1 "nonimmediate_operand")))]
- "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH)"
-{
- if (!(SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH)
- && !X87_ENABLE_FLOAT (<MODEF:MODE>mode, <SWI48:MODE>mode))
- {
- rtx reg = gen_reg_rtx (XFmode);
- rtx (*insn)(rtx, rtx);
-
- emit_insn (gen_float<SWI48:mode>xf2 (reg, operands[1]));
-
- if (<MODEF:MODE>mode == SFmode)
- insn = gen_truncxfsf2;
- else if (<MODEF:MODE>mode == DFmode)
- insn = gen_truncxfdf2;
- else
- gcc_unreachable ();
+ (float:MODEF (match_operand:SWI48x 1 "nonimmediate_operand")))]
+ "(TARGET_80387 && X87_ENABLE_FLOAT (<MODEF:MODE>mode, <SWI48x:MODE>mode))
+ || (SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH
+ && ((<SWI48x:MODE>mode != DImode) || TARGET_64BIT))")
- emit_insn (insn (operands[0], reg));
- DONE;
- }
-})
-
-(define_insn "*float<SWI48:mode><MODEF:mode>2_mixed"
+(define_insn "*float<SWI48:mode><MODEF:mode>2"
[(set (match_operand:MODEF 0 "register_operand" "=f,v,v")
(float:MODEF
(match_operand:SWI48 1 "nonimmediate_operand" "m,r,m")))]
- "SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH"
+ "(TARGET_80387 && X87_ENABLE_FLOAT (<MODEF:MODE>mode, <SWI48:MODE>mode))
+ || (SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH)"
"@
fild%Z1\t%1
%vcvtsi2<MODEF:ssemodesuffix><SWI48:rex64suffix>\t{%1, %d0|%d0, %1}
@@ -5447,21 +5127,28 @@
(set_attr "znver1_decode" "double,*,*")
(set_attr "fp_int_src" "true")
(set (attr "enabled")
- (cond [(eq_attr "alternative" "0")
- (symbol_ref "TARGET_MIX_SSE_I387
- && X87_ENABLE_FLOAT (<MODEF:MODE>mode,
- <SWI48:MODE>mode)")
- ]
- (symbol_ref "true")))
+ (if_then_else
+ (match_test ("SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH"))
+ (if_then_else
+ (eq_attr "alternative" "0")
+ (symbol_ref "TARGET_MIX_SSE_I387
+ && X87_ENABLE_FLOAT (<MODEF:MODE>mode,
+ <SWI48:MODE>mode)")
+ (symbol_ref "true"))
+ (if_then_else
+ (eq_attr "alternative" "0")
+ (symbol_ref "true")
+ (symbol_ref "false"))))
(set (attr "preferred_for_speed")
(cond [(eq_attr "alternative" "1")
- (symbol_ref "TARGET_INTER_UNIT_CONVERSIONS")]
- (symbol_ref "true")))])
+ (symbol_ref "TARGET_INTER_UNIT_CONVERSIONS")]
+ (symbol_ref "true")))])
-(define_insn "*float<SWI48x:mode><MODEF:mode>2_i387"
+(define_insn "*floatdi<MODEF:mode>2_i387"
[(set (match_operand:MODEF 0 "register_operand" "=f")
- (float:MODEF (match_operand:SWI48x 1 "nonimmediate_operand" "m")))]
- "TARGET_80387 && X87_ENABLE_FLOAT (<MODEF:MODE>mode, <SWI48x:MODE>mode)"
+ (float:MODEF (match_operand:DI 1 "nonimmediate_operand" "m")))]
+ "!TARGET_64BIT
+ && TARGET_80387 && X87_ENABLE_FLOAT (<MODEF:MODE>mode, DImode)"
"fild%Z1\t%1"
[(set_attr "type" "fmov")
(set_attr "mode" "<MODEF:MODE>")
@@ -5496,6 +5183,56 @@
DONE;
})
+;; Avoid store forwarding (partial memory) stall penalty
+;; by passing DImode value through XMM registers. */
+
+(define_split
+ [(set (match_operand:X87MODEF 0 "register_operand")
+ (float:X87MODEF
+ (match_operand:DI 1 "register_operand")))]
+ "!TARGET_64BIT && TARGET_INTER_UNIT_MOVES_TO_VEC
+ && TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode)
+ && TARGET_SSE2 && optimize_function_for_speed_p (cfun)
+ && can_create_pseudo_p ()"
+ [(const_int 0)]
+{
+ emit_insn (gen_floatdi<mode>2_i387_with_xmm
+ (operands[0], operands[1],
+ assign_386_stack_local (DImode, SLOT_TEMP)));
+ DONE;
+})
+
+(define_insn_and_split "floatdi<X87MODEF:mode>2_i387_with_xmm"
+ [(set (match_operand:X87MODEF 0 "register_operand" "=f")
+ (float:X87MODEF
+ (match_operand:DI 1 "register_operand" "r")))
+ (clobber (match_scratch:V4SI 3 "=x"))
+ (clobber (match_scratch:V4SI 4 "=x"))
+ (clobber (match_operand:DI 2 "memory_operand" "=m"))]
+ "!TARGET_64BIT && TARGET_INTER_UNIT_MOVES_TO_VEC
+ && TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode)
+ && TARGET_SSE2 && optimize_function_for_speed_p (cfun)"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 2) (match_dup 3))
+ (set (match_dup 0) (float:X87MODEF (match_dup 2)))]
+{
+ /* The DImode arrived in a pair of integral registers (e.g. %edx:%eax).
+ Assemble the 64-bit DImode value in an xmm register. */
+ emit_insn (gen_sse2_loadld (operands[3], CONST0_RTX (V4SImode),
+ gen_lowpart (SImode, operands[1])));
+ emit_insn (gen_sse2_loadld (operands[4], CONST0_RTX (V4SImode),
+ gen_highpart (SImode, operands[1])));
+ emit_insn (gen_vec_interleave_lowv4si (operands[3], operands[3],
+ operands[4]));
+
+ operands[3] = gen_lowpart (DImode, operands[3]);
+}
+ [(set_attr "type" "multi")
+ (set_attr "mode" "<X87MODEF:MODE>")
+ (set_attr "unit" "i387")
+ (set_attr "fp_int_src" "true")])
+
;; Avoid partial SSE register dependency stalls. This splitter should split
;; late in the pass sequence (after register rename pass), so allocated
;; registers won't change anymore
@@ -5521,114 +5258,6 @@
emit_move_insn (operands[0], CONST0_RTX (vmode));
})
-;; Break partial reg stall for cvtsd2ss. This splitter should split
-;; late in the pass sequence (after register rename pass),
-;; so allocated registers won't change anymore.
-
-(define_split
- [(set (match_operand:SF 0 "sse_reg_operand")
- (float_truncate:SF
- (match_operand:DF 1 "nonimmediate_operand")))]
- "TARGET_SSE_PARTIAL_REG_DEPENDENCY && epilogue_completed
- && optimize_function_for_speed_p (cfun)
- && (!REG_P (operands[1])
- || REGNO (operands[0]) != REGNO (operands[1]))
- && (!EXT_REX_SSE_REG_P (operands[0])
- || TARGET_AVX512VL)"
- [(set (match_dup 0)
- (vec_merge:V4SF
- (vec_duplicate:V4SF
- (float_truncate:SF
- (match_dup 1)))
- (match_dup 0)
- (const_int 1)))]
-{
- operands[0] = lowpart_subreg (V4SFmode, operands[0], SFmode);
- emit_move_insn (operands[0], CONST0_RTX (V4SFmode));
-})
-
-;; Break partial reg stall for cvtss2sd. This splitter should split
-;; late in the pass sequence (after register rename pass),
-;; so allocated registers won't change anymore.
-
-(define_split
- [(set (match_operand:DF 0 "sse_reg_operand")
- (float_extend:DF
- (match_operand:SF 1 "nonimmediate_operand")))]
- "TARGET_SSE_PARTIAL_REG_DEPENDENCY && epilogue_completed
- && optimize_function_for_speed_p (cfun)
- && (!REG_P (operands[1])
- || REGNO (operands[0]) != REGNO (operands[1]))
- && (!EXT_REX_SSE_REG_P (operands[0])
- || TARGET_AVX512VL)"
- [(set (match_dup 0)
- (vec_merge:V2DF
- (vec_duplicate:V2DF
- (float_extend:DF
- (match_dup 1)))
- (match_dup 0)
- (const_int 1)))]
-{
- operands[0] = lowpart_subreg (V2DFmode, operands[0], DFmode);
- emit_move_insn (operands[0], CONST0_RTX (V2DFmode));
-})
-
-;; Avoid store forwarding (partial memory) stall penalty
-;; by passing DImode value through XMM registers. */
-
-(define_insn "floatdi<X87MODEF:mode>2_i387_with_xmm"
- [(set (match_operand:X87MODEF 0 "register_operand" "=f,f")
- (float:X87MODEF
- (match_operand:DI 1 "nonimmediate_operand" "m,?r")))
- (clobber (match_scratch:V4SI 3 "=X,x"))
- (clobber (match_scratch:V4SI 4 "=X,x"))
- (clobber (match_operand:DI 2 "memory_operand" "=X,m"))]
- "TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode)
- && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES_TO_VEC
- && !TARGET_64BIT && optimize_function_for_speed_p (cfun)"
- "#"
- [(set_attr "type" "multi")
- (set_attr "mode" "<X87MODEF:MODE>")
- (set_attr "unit" "i387")
- (set_attr "fp_int_src" "true")])
-
-(define_split
- [(set (match_operand:X87MODEF 0 "fp_register_operand")
- (float:X87MODEF (match_operand:DI 1 "register_operand")))
- (clobber (match_scratch:V4SI 3))
- (clobber (match_scratch:V4SI 4))
- (clobber (match_operand:DI 2 "memory_operand"))]
- "TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode)
- && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES_TO_VEC
- && !TARGET_64BIT && optimize_function_for_speed_p (cfun)
- && reload_completed"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 0) (float:X87MODEF (match_dup 2)))]
-{
- /* The DImode arrived in a pair of integral registers (e.g. %edx:%eax).
- Assemble the 64-bit DImode value in an xmm register. */
- emit_insn (gen_sse2_loadld (operands[3], CONST0_RTX (V4SImode),
- gen_lowpart (SImode, operands[1])));
- emit_insn (gen_sse2_loadld (operands[4], CONST0_RTX (V4SImode),
- gen_highpart (SImode, operands[1])));
- emit_insn (gen_vec_interleave_lowv4si (operands[3], operands[3],
- operands[4]));
-
- operands[3] = gen_lowpart (DImode, operands[3]);
-})
-
-(define_split
- [(set (match_operand:X87MODEF 0 "fp_register_operand")
- (float:X87MODEF (match_operand:DI 1 "memory_operand")))
- (clobber (match_scratch:V4SI 3))
- (clobber (match_scratch:V4SI 4))
- (clobber (match_operand:DI 2 "memory_operand"))]
- "TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode)
- && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES_TO_VEC
- && !TARGET_64BIT && optimize_function_for_speed_p (cfun)
- && reload_completed"
- [(set (match_dup 0) (float:X87MODEF (match_dup 1)))])
-
(define_expand "floatuns<SWI12:mode><MODEF:mode>2"
[(set (match_operand:MODEF 0 "register_operand")
(unsigned_float:MODEF
@@ -7789,16 +7418,16 @@
(set_attr "mode" "QI")])
(define_expand "<s>mul<mode>3_highpart"
- [(parallel [(set (match_operand:SWI48 0 "register_operand")
- (truncate:SWI48
+ [(parallel [(set (match_operand:DWIH 0 "register_operand")
+ (truncate:DWIH
(lshiftrt:<DWI>
(mult:<DWI>
(any_extend:<DWI>
- (match_operand:SWI48 1 "nonimmediate_operand"))
+ (match_operand:DWIH 1 "nonimmediate_operand"))
(any_extend:<DWI>
- (match_operand:SWI48 2 "register_operand")))
+ (match_operand:DWIH 2 "register_operand")))
(match_dup 3))))
- (clobber (match_scratch:SWI48 4))
+ (clobber (match_scratch:DWIH 4))
(clobber (reg:CC FLAGS_REG))])]
""
"operands[3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode));")
@@ -10208,19 +9837,10 @@
[(set_attr "type" "fsgn")
(set_attr "mode" "DF")])
-(define_insn "*<code>extendsfxf2"
+(define_insn "*<code>extend<mode>xf2"
[(set (match_operand:XF 0 "register_operand" "=f")
(absneg:XF (float_extend:XF
- (match_operand:SF 1 "register_operand" "0"))))]
- "TARGET_80387"
- "f<absneg_mnemonic>"
- [(set_attr "type" "fsgn")
- (set_attr "mode" "XF")])
-
-(define_insn "*<code>extenddfxf2"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (absneg:XF (float_extend:XF
- (match_operand:DF 1 "register_operand" "0"))))]
+ (match_operand:MODEF 1 "register_operand" "0"))))]
"TARGET_80387"
"f<absneg_mnemonic>"
[(set_attr "type" "fsgn")
@@ -13582,7 +13202,6 @@
"lea{q}\t{_GLOBAL_OFFSET_TABLE_(%%rip), %0|%0, _GLOBAL_OFFSET_TABLE_[rip]}"
[(set_attr "type" "lea")
(set_attr "length_address" "4")
- (set_attr "modrm_class" "unknown")
(set_attr "mode" "DI")])
(define_insn "set_rip_rex64"
@@ -13627,7 +13246,10 @@
stack address we wish to restore. */
tmp = gen_rtx_PLUS (Pmode, arg_pointer_rtx, sa);
tmp = plus_constant (Pmode, tmp, -UNITS_PER_WORD);
- tmp = gen_rtx_MEM (Pmode, tmp);
+ /* Return address is always in word_mode. */
+ tmp = gen_rtx_MEM (word_mode, tmp);
+ if (GET_MODE (ra) != word_mode)
+ ra = convert_to_mode (word_mode, ra, 1);
emit_move_insn (tmp, ra);
emit_jump_insn (gen_eh_return_internal ());
@@ -15462,7 +15084,7 @@
;; all fancy i386 XFmode math functions.
(define_insn "truncxf<mode>2_i387_noop_unspec"
- [(set (match_operand:MODEF 0 "register_operand" "=f")
+ [(set (match_operand:MODEF 0 "nonimmediate_operand" "=mf")
(unspec:MODEF [(match_operand:XF 1 "register_operand" "f")]
UNSPEC_TRUNC_NOOP))]
"TARGET_USE_FANCY_MATH_387"
@@ -15481,19 +15103,6 @@
(set_attr "amdfam10_decode" "direct")
(set_attr "bdver1_decode" "direct")])
-(define_insn "sqrt_extend<mode>xf2_i387"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (sqrt:XF
- (float_extend:XF
- (match_operand:MODEF 1 "register_operand" "0"))))]
- "TARGET_USE_FANCY_MATH_387"
- "fsqrt"
- [(set_attr "type" "fpspc")
- (set_attr "mode" "XF")
- (set_attr "athlon_decode" "direct")
- (set_attr "amdfam10_decode" "direct")
- (set_attr "bdver1_decode" "direct")])
-
(define_insn "*rsqrtsf2_sse"
[(set (match_operand:SF 0 "register_operand" "=x,x")
(unspec:SF [(match_operand:SF 1 "nonimmediate_operand" "x,m")]
@@ -15556,9 +15165,10 @@
if (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))
{
rtx op0 = gen_reg_rtx (XFmode);
- rtx op1 = force_reg (<MODE>mode, operands[1]);
+ rtx op1 = gen_reg_rtx (XFmode);
- emit_insn (gen_sqrt_extend<mode>xf2_i387 (op0, op1));
+ emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
+ emit_insn (gen_sqrtxf2 (op0, op1));
emit_insn (gen_truncxf<mode>2_i387_noop_unspec (operands[0], op0));
DONE;
}
@@ -15723,7 +15333,7 @@
[(UNSPEC_SIN "sin")
(UNSPEC_COS "cos")])
-(define_insn "*<sincos>xf2_i387"
+(define_insn "<sincos>xf2"
[(set (match_operand:XF 0 "register_operand" "=f")
(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
SINCOS))]
@@ -15734,25 +15344,23 @@
(set_attr "znver1_decode" "vector")
(set_attr "mode" "XF")])
-(define_insn "*<sincos>_extend<mode>xf2_i387"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (unspec:XF [(float_extend:XF
- (match_operand:MODEF 1 "register_operand" "0"))]
- SINCOS))]
+(define_expand "<sincos><mode>2"
+ [(set (match_operand:MODEF 0 "register_operand")
+ (unspec:MODEF [(match_operand:MODEF 1 "general_operand")]
+ SINCOS))]
"TARGET_USE_FANCY_MATH_387
&& (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
|| TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
- "f<sincos>"
- [(set_attr "type" "fpspc")
- (set_attr "znver1_decode" "vector")
- (set_attr "mode" "XF")])
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
-;; When sincos pattern is defined, sin and cos builtin functions will be
-;; expanded to sincos pattern with one of its outputs left unused.
-;; CSE pass will figure out if two sincos patterns can be combined,
-;; otherwise sincos pattern will be split back to sin or cos pattern,
-;; depending on the unused output.
+ emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
+ emit_insn (gen_<sincos>xf2 (op0, op1));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op0));
+ DONE;
+})
(define_insn "sincosxf3"
[(set (match_operand:XF 0 "register_operand" "=f")
@@ -15767,70 +15375,10 @@
(set_attr "znver1_decode" "vector")
(set_attr "mode" "XF")])
-(define_split
- [(set (match_operand:XF 0 "register_operand")
- (unspec:XF [(match_operand:XF 2 "register_operand")]
- UNSPEC_SINCOS_COS))
- (set (match_operand:XF 1 "register_operand")
- (unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
- "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
- && can_create_pseudo_p ()"
- [(set (match_dup 1) (unspec:XF [(match_dup 2)] UNSPEC_SIN))])
-
-(define_split
- [(set (match_operand:XF 0 "register_operand")
- (unspec:XF [(match_operand:XF 2 "register_operand")]
- UNSPEC_SINCOS_COS))
- (set (match_operand:XF 1 "register_operand")
- (unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
- "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
- && can_create_pseudo_p ()"
- [(set (match_dup 0) (unspec:XF [(match_dup 2)] UNSPEC_COS))])
-
-(define_insn "sincos_extend<mode>xf3_i387"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (unspec:XF [(float_extend:XF
- (match_operand:MODEF 2 "register_operand" "0"))]
- UNSPEC_SINCOS_COS))
- (set (match_operand:XF 1 "register_operand" "=u")
- (unspec:XF [(float_extend:XF (match_dup 2))] UNSPEC_SINCOS_SIN))]
- "TARGET_USE_FANCY_MATH_387
- && (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
- || TARGET_MIX_SSE_I387)
- && flag_unsafe_math_optimizations"
- "fsincos"
- [(set_attr "type" "fpspc")
- (set_attr "znver1_decode" "vector")
- (set_attr "mode" "XF")])
-
-(define_split
- [(set (match_operand:XF 0 "register_operand")
- (unspec:XF [(float_extend:XF
- (match_operand:MODEF 2 "register_operand"))]
- UNSPEC_SINCOS_COS))
- (set (match_operand:XF 1 "register_operand")
- (unspec:XF [(float_extend:XF (match_dup 2))] UNSPEC_SINCOS_SIN))]
- "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
- && can_create_pseudo_p ()"
- [(set (match_dup 1)
- (unspec:XF [(float_extend:XF (match_dup 2))] UNSPEC_SIN))])
-
-(define_split
- [(set (match_operand:XF 0 "register_operand")
- (unspec:XF [(float_extend:XF
- (match_operand:MODEF 2 "register_operand"))]
- UNSPEC_SINCOS_COS))
- (set (match_operand:XF 1 "register_operand")
- (unspec:XF [(float_extend:XF (match_dup 2))] UNSPEC_SINCOS_SIN))]
- "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
- && can_create_pseudo_p ()"
- [(set (match_dup 0)
- (unspec:XF [(float_extend:XF (match_dup 2))] UNSPEC_COS))])
-
(define_expand "sincos<mode>3"
[(use (match_operand:MODEF 0 "register_operand"))
(use (match_operand:MODEF 1 "register_operand"))
- (use (match_operand:MODEF 2 "register_operand"))]
+ (use (match_operand:MODEF 2 "general_operand"))]
"TARGET_USE_FANCY_MATH_387
&& (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
|| TARGET_MIX_SSE_I387)
@@ -15838,39 +15386,23 @@
{
rtx op0 = gen_reg_rtx (XFmode);
rtx op1 = gen_reg_rtx (XFmode);
+ rtx op2 = gen_reg_rtx (XFmode);
- emit_insn (gen_sincos_extend<mode>xf3_i387 (op0, op1, operands[2]));
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[1], op1));
+ emit_insn (gen_extend<mode>xf2 (op2, operands[2]));
+ emit_insn (gen_sincosxf3 (op0, op1, op2));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op0));
+ emit_insn (gen_truncxf<mode>2 (operands[1], op1));
DONE;
})
(define_insn "fptanxf4_i387"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (match_operand:XF 3 "const_double_operand" "F"))
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (match_operand:SF 3 "const1_operand"))
(set (match_operand:XF 1 "register_operand" "=u")
(unspec:XF [(match_operand:XF 2 "register_operand" "0")]
UNSPEC_TAN))]
"TARGET_USE_FANCY_MATH_387
- && flag_unsafe_math_optimizations
- && standard_80387_constant_p (operands[3]) == 2"
- "fptan"
- [(set_attr "type" "fpspc")
- (set_attr "znver1_decode" "vector")
- (set_attr "mode" "XF")])
-
-(define_insn "fptan_extend<mode>xf4_i387"
- [(set (match_operand:MODEF 0 "register_operand" "=f")
- (match_operand:MODEF 3 "const_double_operand" "F"))
- (set (match_operand:XF 1 "register_operand" "=u")
- (unspec:XF [(float_extend:XF
- (match_operand:MODEF 2 "register_operand" "0"))]
- UNSPEC_TAN))]
- "TARGET_USE_FANCY_MATH_387
- && (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
- || TARGET_MIX_SSE_I387)
- && flag_unsafe_math_optimizations
- && standard_80387_constant_p (operands[3]) == 2"
+ && flag_unsafe_math_optimizations"
"fptan"
[(set_attr "type" "fpspc")
(set_attr "znver1_decode" "vector")
@@ -15882,33 +15414,30 @@
"TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
{
- rtx one = gen_reg_rtx (XFmode);
- rtx op2 = CONST1_RTX (XFmode); /* fld1 */
-
- emit_insn (gen_fptanxf4_i387 (one, operands[0], operands[1], op2));
+ rtx one = gen_reg_rtx (SFmode);
+ emit_insn (gen_fptanxf4_i387 (one, operands[0], operands[1],
+ CONST1_RTX (SFmode)));
DONE;
})
(define_expand "tan<mode>2"
[(use (match_operand:MODEF 0 "register_operand"))
- (use (match_operand:MODEF 1 "register_operand"))]
+ (use (match_operand:MODEF 1 "general_operand"))]
"TARGET_USE_FANCY_MATH_387
&& (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
|| TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
- rtx one = gen_reg_rtx (<MODE>mode);
- rtx op2 = CONST1_RTX (<MODE>mode); /* fld1 */
-
- emit_insn (gen_fptan_extend<mode>xf4_i387 (one, op0,
- operands[1], op2));
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+ emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
+ emit_insn (gen_tanxf2 (op0, op1));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op0));
DONE;
})
-(define_insn "*fpatanxf3_i387"
+(define_insn "atan2xf3"
[(set (match_operand:XF 0 "register_operand" "=f")
(unspec:XF [(match_operand:XF 1 "register_operand" "0")
(match_operand:XF 2 "register_operand" "u")]
@@ -15921,45 +15450,24 @@
(set_attr "znver1_decode" "vector")
(set_attr "mode" "XF")])
-(define_insn "fpatan_extend<mode>xf3_i387"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (unspec:XF [(float_extend:XF
- (match_operand:MODEF 1 "register_operand" "0"))
- (float_extend:XF
- (match_operand:MODEF 2 "register_operand" "u"))]
- UNSPEC_FPATAN))
- (clobber (match_scratch:XF 3 "=2"))]
- "TARGET_USE_FANCY_MATH_387
- && (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
- || TARGET_MIX_SSE_I387)
- && flag_unsafe_math_optimizations"
- "fpatan"
- [(set_attr "type" "fpspc")
- (set_attr "znver1_decode" "vector")
- (set_attr "mode" "XF")])
-
-(define_expand "atan2xf3"
- [(parallel [(set (match_operand:XF 0 "register_operand")
- (unspec:XF [(match_operand:XF 2 "register_operand")
- (match_operand:XF 1 "register_operand")]
- UNSPEC_FPATAN))
- (clobber (match_scratch:XF 3))])]
- "TARGET_USE_FANCY_MATH_387
- && flag_unsafe_math_optimizations")
-
(define_expand "atan2<mode>3"
[(use (match_operand:MODEF 0 "register_operand"))
- (use (match_operand:MODEF 1 "register_operand"))
- (use (match_operand:MODEF 2 "register_operand"))]
+ (use (match_operand:MODEF 1 "general_operand"))
+ (use (match_operand:MODEF 2 "general_operand"))]
"TARGET_USE_FANCY_MATH_387
&& (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
|| TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+ rtx op2 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extend<mode>xf2 (op2, operands[2]));
+ emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
- emit_insn (gen_fpatan_extend<mode>xf3_i387 (op0, operands[2], operands[1]));
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+ emit_insn (gen_atan2xf3 (op0, op2, op1));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op0));
DONE;
})
@@ -15971,26 +15479,22 @@
(clobber (match_scratch:XF 3))])]
"TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
-{
- operands[2] = gen_reg_rtx (XFmode);
- emit_move_insn (operands[2], CONST1_RTX (XFmode)); /* fld1 */
-})
+ "operands[2] = force_reg (XFmode, CONST1_RTX (XFmode));")
(define_expand "atan<mode>2"
[(use (match_operand:MODEF 0 "register_operand"))
- (use (match_operand:MODEF 1 "register_operand"))]
+ (use (match_operand:MODEF 1 "general_operand"))]
"TARGET_USE_FANCY_MATH_387
&& (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
|| TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
- rtx op2 = gen_reg_rtx (<MODE>mode);
- emit_move_insn (op2, CONST1_RTX (<MODE>mode)); /* fld1 */
-
- emit_insn (gen_fpatan_extend<mode>xf3_i387 (op0, op2, operands[1]));
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+ emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
+ emit_insn (gen_atanxf2 (op0, op1));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op0));
DONE;
})
@@ -16012,7 +15516,7 @@
for (i = 2; i < 6; i++)
operands[i] = gen_reg_rtx (XFmode);
- emit_move_insn (operands[3], CONST1_RTX (XFmode)); /* fld1 */
+ emit_move_insn (operands[3], CONST1_RTX (XFmode));
})
(define_expand "asin<mode>2"
@@ -16028,7 +15532,7 @@
emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
emit_insn (gen_asinxf2 (op0, op1));
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op0));
DONE;
})
@@ -16050,7 +15554,7 @@
for (i = 2; i < 6; i++)
operands[i] = gen_reg_rtx (XFmode);
- emit_move_insn (operands[3], CONST1_RTX (XFmode)); /* fld1 */
+ emit_move_insn (operands[3], CONST1_RTX (XFmode));
})
(define_expand "acos<mode>2"
@@ -16066,7 +15570,7 @@
emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
emit_insn (gen_acosxf2 (op0, op1));
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op0));
DONE;
})
@@ -16083,22 +15587,6 @@
(set_attr "znver1_decode" "vector")
(set_attr "mode" "XF")])
-(define_insn "fyl2x_extend<mode>xf3_i387"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (unspec:XF [(float_extend:XF
- (match_operand:MODEF 1 "register_operand" "0"))
- (match_operand:XF 2 "register_operand" "u")]
- UNSPEC_FYL2X))
- (clobber (match_scratch:XF 3 "=2"))]
- "TARGET_USE_FANCY_MATH_387
- && (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
- || TARGET_MIX_SSE_I387)
- && flag_unsafe_math_optimizations"
- "fyl2x"
- [(set_attr "type" "fpspc")
- (set_attr "znver1_decode" "vector")
- (set_attr "mode" "XF")])
-
(define_expand "logxf2"
[(parallel [(set (match_operand:XF 0 "register_operand")
(unspec:XF [(match_operand:XF 1 "register_operand")
@@ -16107,25 +15595,24 @@
"TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
{
- operands[2] = gen_reg_rtx (XFmode);
- emit_move_insn (operands[2], standard_80387_constant_rtx (4)); /* fldln2 */
+ operands[2]
+ = force_reg (XFmode, standard_80387_constant_rtx (4)); /* fldln2 */
})
(define_expand "log<mode>2"
[(use (match_operand:MODEF 0 "register_operand"))
- (use (match_operand:MODEF 1 "register_operand"))]
+ (use (match_operand:MODEF 1 "general_operand"))]
"TARGET_USE_FANCY_MATH_387
&& (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
|| TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
- rtx op2 = gen_reg_rtx (XFmode);
- emit_move_insn (op2, standard_80387_constant_rtx (4)); /* fldln2 */
-
- emit_insn (gen_fyl2x_extend<mode>xf3_i387 (op0, operands[1], op2));
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+ emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
+ emit_insn (gen_logxf2 (op0, op1));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op0));
DONE;
})
@@ -16137,25 +15624,24 @@
"TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
{
- operands[2] = gen_reg_rtx (XFmode);
- emit_move_insn (operands[2], standard_80387_constant_rtx (3)); /* fldlg2 */
+ operands[2]
+ = force_reg (XFmode, standard_80387_constant_rtx (3)); /* fldlg2 */
})
(define_expand "log10<mode>2"
[(use (match_operand:MODEF 0 "register_operand"))
- (use (match_operand:MODEF 1 "register_operand"))]
+ (use (match_operand:MODEF 1 "general_operand"))]
"TARGET_USE_FANCY_MATH_387
&& (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
|| TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
- rtx op2 = gen_reg_rtx (XFmode);
- emit_move_insn (op2, standard_80387_constant_rtx (3)); /* fldlg2 */
-
- emit_insn (gen_fyl2x_extend<mode>xf3_i387 (op0, operands[1], op2));
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+ emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
+ emit_insn (gen_log10xf2 (op0, op1));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op0));
DONE;
})
@@ -16166,26 +15652,22 @@
(clobber (match_scratch:XF 3))])]
"TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
-{
- operands[2] = gen_reg_rtx (XFmode);
- emit_move_insn (operands[2], CONST1_RTX (XFmode)); /* fld1 */
-})
+ "operands[2] = force_reg (XFmode, CONST1_RTX (XFmode));")
(define_expand "log2<mode>2"
[(use (match_operand:MODEF 0 "register_operand"))
- (use (match_operand:MODEF 1 "register_operand"))]
+ (use (match_operand:MODEF 1 "general_operand"))]
"TARGET_USE_FANCY_MATH_387
&& (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
|| TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
- rtx op2 = gen_reg_rtx (XFmode);
- emit_move_insn (op2, CONST1_RTX (XFmode)); /* fld1 */
-
- emit_insn (gen_fyl2x_extend<mode>xf3_i387 (op0, operands[1], op2));
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+ emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
+ emit_insn (gen_log2xf2 (op0, op1));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op0));
DONE;
})
@@ -16202,22 +15684,6 @@
(set_attr "znver1_decode" "vector")
(set_attr "mode" "XF")])
-(define_insn "fyl2xp1_extend<mode>xf3_i387"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (unspec:XF [(float_extend:XF
- (match_operand:MODEF 1 "register_operand" "0"))
- (match_operand:XF 2 "register_operand" "u")]
- UNSPEC_FYL2XP1))
- (clobber (match_scratch:XF 3 "=2"))]
- "TARGET_USE_FANCY_MATH_387
- && (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
- || TARGET_MIX_SSE_I387)
- && flag_unsafe_math_optimizations"
- "fyl2xp1"
- [(set_attr "type" "fpspc")
- (set_attr "znver1_decode" "vector")
- (set_attr "mode" "XF")])
-
(define_expand "log1pxf2"
[(use (match_operand:XF 0 "register_operand"))
(use (match_operand:XF 1 "register_operand"))]
@@ -16230,20 +15696,18 @@
(define_expand "log1p<mode>2"
[(use (match_operand:MODEF 0 "register_operand"))
- (use (match_operand:MODEF 1 "register_operand"))]
+ (use (match_operand:MODEF 1 "general_operand"))]
"TARGET_USE_FANCY_MATH_387
&& (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
|| TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
- rtx op0;
-
- op0 = gen_reg_rtx (XFmode);
-
- operands[1] = gen_rtx_FLOAT_EXTEND (XFmode, operands[1]);
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
- ix86_emit_i387_log1p (op0, operands[1]);
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+ emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
+ emit_insn (gen_log1pxf2 (op0, op1));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op0));
DONE;
})
@@ -16260,22 +15724,6 @@
(set_attr "znver1_decode" "vector")
(set_attr "mode" "XF")])
-(define_insn "fxtract_extend<mode>xf3_i387"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (unspec:XF [(float_extend:XF
- (match_operand:MODEF 2 "register_operand" "0"))]
- UNSPEC_XTRACT_FRACT))
- (set (match_operand:XF 1 "register_operand" "=u")
- (unspec:XF [(float_extend:XF (match_dup 2))] UNSPEC_XTRACT_EXP))]
- "TARGET_USE_FANCY_MATH_387
- && (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
- || TARGET_MIX_SSE_I387)
- && flag_unsafe_math_optimizations"
- "fxtract"
- [(set_attr "type" "fpspc")
- (set_attr "znver1_decode" "vector")
- (set_attr "mode" "XF")])
-
(define_expand "logbxf2"
[(parallel [(set (match_dup 2)
(unspec:XF [(match_operand:XF 1 "register_operand")]
@@ -16288,7 +15736,7 @@
(define_expand "logb<mode>2"
[(use (match_operand:MODEF 0 "register_operand"))
- (use (match_operand:MODEF 1 "register_operand"))]
+ (use (match_operand:MODEF 1 "general_operand"))]
"TARGET_USE_FANCY_MATH_387
&& (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
|| TARGET_MIX_SSE_I387)
@@ -16297,8 +15745,9 @@
rtx op0 = gen_reg_rtx (XFmode);
rtx op1 = gen_reg_rtx (XFmode);
- emit_insn (gen_fxtract_extend<mode>xf3_i387 (op0, op1, operands[1]));
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op1));
+ emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
+ emit_insn (gen_logbxf2 (op0, op1));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op1));
DONE;
})
@@ -16323,21 +15772,23 @@
(define_expand "ilogb<mode>2"
[(use (match_operand:SI 0 "register_operand"))
- (use (match_operand:MODEF 1 "register_operand"))]
+ (use (match_operand:MODEF 1 "general_operand"))]
"TARGET_USE_FANCY_MATH_387
&& (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
|| TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
- rtx op0, op1;
+ rtx op0, op1, op2;
if (optimize_insn_for_size_p ())
FAIL;
op0 = gen_reg_rtx (XFmode);
op1 = gen_reg_rtx (XFmode);
+ op2 = gen_reg_rtx (XFmode);
- emit_insn (gen_fxtract_extend<mode>xf3_i387 (op0, op1, operands[1]));
+ emit_insn (gen_extend<mode>xf2 (op2, operands[1]));
+ emit_insn (gen_fxtractxf3_i387 (op0, op1, op2));
emit_insn (gen_fix_truncxfsi2 (operands[0], op1));
DONE;
})
@@ -16389,7 +15840,7 @@
for (i = 3; i < 10; i++)
operands[i] = gen_reg_rtx (XFmode);
- emit_move_insn (operands[7], CONST1_RTX (XFmode)); /* fld1 */
+ emit_move_insn (operands[7], CONST1_RTX (XFmode));
})
(define_expand "expxf2"
@@ -16398,10 +15849,7 @@
"TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
{
- rtx op2;
-
- op2 = gen_reg_rtx (XFmode);
- emit_move_insn (op2, standard_80387_constant_rtx (5)); /* fldl2e */
+ rtx op2 = force_reg (XFmode, standard_80387_constant_rtx (5)); /* fldl2e */
emit_insn (gen_expNcorexf3 (operands[0], operands[1], op2));
DONE;
@@ -16415,14 +15863,12 @@
|| TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
- rtx op0, op1;
-
- op0 = gen_reg_rtx (XFmode);
- op1 = gen_reg_rtx (XFmode);
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
emit_insn (gen_expxf2 (op0, op1));
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op0));
DONE;
})
@@ -16432,10 +15878,7 @@
"TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
{
- rtx op2;
-
- op2 = gen_reg_rtx (XFmode);
- emit_move_insn (op2, standard_80387_constant_rtx (6)); /* fldl2t */
+ rtx op2 = force_reg (XFmode, standard_80387_constant_rtx (6)); /* fldl2t */
emit_insn (gen_expNcorexf3 (operands[0], operands[1], op2));
DONE;
@@ -16449,14 +15892,12 @@
|| TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
- rtx op0, op1;
-
- op0 = gen_reg_rtx (XFmode);
- op1 = gen_reg_rtx (XFmode);
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
emit_insn (gen_exp10xf2 (op0, op1));
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op0));
DONE;
})
@@ -16466,10 +15907,7 @@
"TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
{
- rtx op2;
-
- op2 = gen_reg_rtx (XFmode);
- emit_move_insn (op2, CONST1_RTX (XFmode)); /* fld1 */
+ rtx op2 = force_reg (XFmode, CONST1_RTX (XFmode));
emit_insn (gen_expNcorexf3 (operands[0], operands[1], op2));
DONE;
@@ -16483,14 +15921,12 @@
|| TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
- rtx op0, op1;
-
- op0 = gen_reg_rtx (XFmode);
- op1 = gen_reg_rtx (XFmode);
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
emit_insn (gen_exp2xf2 (op0, op1));
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op0));
DONE;
})
@@ -16499,7 +15935,6 @@
(match_dup 2)))
(set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT))
(set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4)))
- (set (match_dup 9) (float_extend:XF (match_dup 13)))
(set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
(parallel [(set (match_dup 7)
(unspec:XF [(match_dup 6) (match_dup 4)]
@@ -16513,8 +15948,7 @@
(set (match_dup 11)
(unspec:XF [(match_dup 9) (match_dup 8)]
UNSPEC_FSCALE_EXP))])
- (set (match_dup 12) (minus:XF (match_dup 10)
- (float_extend:XF (match_dup 13))))
+ (set (match_dup 12) (minus:XF (match_dup 10) (match_dup 9)))
(set (match_operand:XF 0 "register_operand")
(plus:XF (match_dup 12) (match_dup 7)))]
"TARGET_USE_FANCY_MATH_387
@@ -16525,10 +15959,8 @@
for (i = 2; i < 13; i++)
operands[i] = gen_reg_rtx (XFmode);
- operands[13]
- = validize_mem (force_const_mem (SFmode, CONST1_RTX (SFmode))); /* fld1 */
-
emit_move_insn (operands[2], standard_80387_constant_rtx (5)); /* fldl2e */
+ emit_move_insn (operands[9], CONST1_RTX (XFmode));
})
(define_expand "expm1<mode>2"
@@ -16539,14 +15971,12 @@
|| TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
- rtx op0, op1;
-
- op0 = gen_reg_rtx (XFmode);
- op1 = gen_reg_rtx (XFmode);
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
emit_insn (gen_expm1xf2 (op0, op1));
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op0));
DONE;
})
@@ -16557,10 +15987,8 @@
"TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
{
- rtx tmp1, tmp2;
-
- tmp1 = gen_reg_rtx (XFmode);
- tmp2 = gen_reg_rtx (XFmode);
+ rtx tmp1 = gen_reg_rtx (XFmode);
+ rtx tmp2 = gen_reg_rtx (XFmode);
emit_insn (gen_floatsixf2 (tmp1, operands[2]));
emit_insn (gen_fscalexf4_i387 (operands[0], tmp2,
@@ -16577,14 +16005,12 @@
|| TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
- rtx op0, op1;
-
- op0 = gen_reg_rtx (XFmode);
- op1 = gen_reg_rtx (XFmode);
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
emit_insn (gen_ldexpxf3 (op0, op1, operands[2]));
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op0));
DONE;
})
@@ -16598,9 +16024,7 @@
UNSPEC_FSCALE_EXP))])]
"TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
-{
- operands[3] = gen_reg_rtx (XFmode);
-})
+ "operands[3] = gen_reg_rtx (XFmode);")
(define_expand "scalb<mode>3"
[(use (match_operand:MODEF 0 "register_operand"))
@@ -16611,16 +16035,14 @@
|| TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
- rtx op0, op1, op2;
-
- op0 = gen_reg_rtx (XFmode);
- op1 = gen_reg_rtx (XFmode);
- op2 = gen_reg_rtx (XFmode);
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+ rtx op2 = gen_reg_rtx (XFmode);
emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
emit_insn (gen_extend<mode>xf2 (op2, operands[2]));
emit_insn (gen_scalbxf3 (op0, op1, op2));
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op0));
DONE;
})
@@ -16636,7 +16058,7 @@
(define_expand "significand<mode>2"
[(use (match_operand:MODEF 0 "register_operand"))
- (use (match_operand:MODEF 1 "register_operand"))]
+ (use (match_operand:MODEF 1 "general_operand"))]
"TARGET_USE_FANCY_MATH_387
&& (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
|| TARGET_MIX_SSE_I387)
@@ -16645,8 +16067,9 @@
rtx op0 = gen_reg_rtx (XFmode);
rtx op1 = gen_reg_rtx (XFmode);
- emit_insn (gen_fxtract_extend<mode>xf3_i387 (op0, op1, operands[1]));
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+ emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
+ emit_insn (gen_significandxf2 (op0, op1));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op0));
DONE;
})
@@ -16677,22 +16100,10 @@
(set_attr "znver1_decode" "vector")
(set_attr "mode" "XF")])
-(define_insn "rint<mode>2_frndint"
- [(set (match_operand:MODEF 0 "register_operand" "=f")
- (unspec:MODEF [(match_operand:MODEF 1 "register_operand" "0")]
- UNSPEC_FRNDINT))]
- "TARGET_USE_FANCY_MATH_387"
- "frndint"
- [(set_attr "type" "fpspc")
- (set_attr "znver1_decode" "vector")
- (set_attr "mode" "<MODE>")])
-
(define_expand "rint<mode>2"
[(use (match_operand:MODEF 0 "register_operand"))
- (use (match_operand:MODEF 1 "register_operand"))]
- "(TARGET_USE_FANCY_MATH_387
- && (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
- || TARGET_MIX_SSE_I387))
+ (use (match_operand:MODEF 1 "nonimmediate_operand"))]
+ "TARGET_USE_FANCY_MATH_387
|| (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)"
{
if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
@@ -16704,7 +16115,14 @@
ix86_expand_rint (operands[0], operands[1]);
}
else
- emit_insn (gen_rint<mode>2_frndint (operands[0], operands[1]));
+ {
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
+ emit_insn (gen_rintxf2 (op0, op1));
+ emit_insn (gen_truncxf<mode>2_i387_noop_unspec (operands[0], op0));
+ }
DONE;
})
@@ -16740,31 +16158,8 @@
DONE;
})
-(define_insn_and_split "*fistdi2_1"
- [(set (match_operand:DI 0 "nonimmediate_operand")
- (unspec:DI [(match_operand:XF 1 "register_operand")]
- UNSPEC_FIST))]
- "TARGET_USE_FANCY_MATH_387
- && can_create_pseudo_p ()"
- "#"
- "&& 1"
- [(const_int 0)]
-{
- if (memory_operand (operands[0], VOIDmode))
- emit_insn (gen_fistdi2 (operands[0], operands[1]));
- else
- {
- operands[2] = assign_386_stack_local (DImode, SLOT_TEMP);
- emit_insn (gen_fistdi2_with_temp (operands[0], operands[1],
- operands[2]));
- }
- DONE;
-}
- [(set_attr "type" "fpspc")
- (set_attr "mode" "DI")])
-
-(define_insn "fistdi2"
- [(set (match_operand:DI 0 "memory_operand" "=m")
+(define_insn "lrintxfdi2"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=m")
(unspec:DI [(match_operand:XF 1 "register_operand" "f")]
UNSPEC_FIST))
(clobber (match_scratch:XF 2 "=&1f"))]
@@ -16773,58 +16168,8 @@
[(set_attr "type" "fpspc")
(set_attr "mode" "DI")])
-(define_insn "fistdi2_with_temp"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
- (unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
- UNSPEC_FIST))
- (clobber (match_operand:DI 2 "memory_operand" "=X,m"))
- (clobber (match_scratch:XF 3 "=&1f,&1f"))]
- "TARGET_USE_FANCY_MATH_387"
- "#"
- [(set_attr "type" "fpspc")
- (set_attr "mode" "DI")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand")
- (unspec:DI [(match_operand:XF 1 "register_operand")]
- UNSPEC_FIST))
- (clobber (match_operand:DI 2 "memory_operand"))
- (clobber (match_scratch 3))]
- "reload_completed"
- [(parallel [(set (match_dup 2) (unspec:DI [(match_dup 1)] UNSPEC_FIST))
- (clobber (match_dup 3))])
- (set (match_dup 0) (match_dup 2))])
-
-(define_split
- [(set (match_operand:DI 0 "memory_operand")
- (unspec:DI [(match_operand:XF 1 "register_operand")]
- UNSPEC_FIST))
- (clobber (match_operand:DI 2 "memory_operand"))
- (clobber (match_scratch 3))]
- "reload_completed"
- [(parallel [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_FIST))
- (clobber (match_dup 3))])])
-
-(define_insn_and_split "*fist<mode>2_1"
- [(set (match_operand:SWI24 0 "register_operand")
- (unspec:SWI24 [(match_operand:XF 1 "register_operand")]
- UNSPEC_FIST))]
- "TARGET_USE_FANCY_MATH_387
- && can_create_pseudo_p ()"
- "#"
- "&& 1"
- [(const_int 0)]
-{
- operands[2] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
- emit_insn (gen_fist<mode>2_with_temp (operands[0], operands[1],
- operands[2]));
- DONE;
-}
- [(set_attr "type" "fpspc")
- (set_attr "mode" "<MODE>")])
-
-(define_insn "fist<mode>2"
- [(set (match_operand:SWI24 0 "memory_operand" "=m")
+(define_insn "lrintxf<mode>2"
+ [(set (match_operand:SWI24 0 "nonimmediate_operand" "=m")
(unspec:SWI24 [(match_operand:XF 1 "register_operand" "f")]
UNSPEC_FIST))]
"TARGET_USE_FANCY_MATH_387"
@@ -16832,39 +16177,6 @@
[(set_attr "type" "fpspc")
(set_attr "mode" "<MODE>")])
-(define_insn "fist<mode>2_with_temp"
- [(set (match_operand:SWI24 0 "register_operand" "=r")
- (unspec:SWI24 [(match_operand:XF 1 "register_operand" "f")]
- UNSPEC_FIST))
- (clobber (match_operand:SWI24 2 "memory_operand" "=m"))]
- "TARGET_USE_FANCY_MATH_387"
- "#"
- [(set_attr "type" "fpspc")
- (set_attr "mode" "<MODE>")])
-
-(define_split
- [(set (match_operand:SWI24 0 "register_operand")
- (unspec:SWI24 [(match_operand:XF 1 "register_operand")]
- UNSPEC_FIST))
- (clobber (match_operand:SWI24 2 "memory_operand"))]
- "reload_completed"
- [(set (match_dup 2) (unspec:SWI24 [(match_dup 1)] UNSPEC_FIST))
- (set (match_dup 0) (match_dup 2))])
-
-(define_split
- [(set (match_operand:SWI24 0 "memory_operand")
- (unspec:SWI24 [(match_operand:XF 1 "register_operand")]
- UNSPEC_FIST))
- (clobber (match_operand:SWI24 2 "memory_operand"))]
- "reload_completed"
- [(set (match_dup 0) (unspec:SWI24 [(match_dup 1)] UNSPEC_FIST))])
-
-(define_expand "lrintxf<mode>2"
- [(set (match_operand:SWI248x 0 "nonimmediate_operand")
- (unspec:SWI248x [(match_operand:XF 1 "register_operand")]
- UNSPEC_FIST))]
- "TARGET_USE_FANCY_MATH_387")
-
(define_expand "lrint<MODEF:mode><SWI48:mode>2"
[(set (match_operand:SWI48 0 "nonimmediate_operand")
(unspec:SWI48 [(match_operand:MODEF 1 "register_operand")]
@@ -16928,9 +16240,9 @@
(UNSPEC_FIST_CEIL "CEIL")])
;; Rounding mode control word calculation could clobber FLAGS_REG.
-(define_insn_and_split "frndint<mode>2_<rounding>"
- [(set (match_operand:X87MODEF 0 "register_operand")
- (unspec:X87MODEF [(match_operand:X87MODEF 1 "register_operand")]
+(define_insn_and_split "frndintxf2_<rounding>"
+ [(set (match_operand:XF 0 "register_operand")
+ (unspec:XF [(match_operand:XF 1 "register_operand")]
FRNDINT_ROUNDING))
(clobber (reg:CC FLAGS_REG))]
"TARGET_USE_FANCY_MATH_387
@@ -16945,18 +16257,18 @@
operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
operands[3] = assign_386_stack_local (HImode, SLOT_CW_<ROUNDING>);
- emit_insn (gen_frndint<mode>2_<rounding>_i387 (operands[0], operands[1],
- operands[2], operands[3]));
+ emit_insn (gen_frndintxf2_<rounding>_i387 (operands[0], operands[1],
+ operands[2], operands[3]));
DONE;
}
[(set_attr "type" "frndint")
(set_attr "i387_cw" "<rounding>")
- (set_attr "mode" "<MODE>")])
+ (set_attr "mode" "XF")])
-(define_insn "frndint<mode>2_<rounding>_i387"
- [(set (match_operand:X87MODEF 0 "register_operand" "=f")
- (unspec:X87MODEF [(match_operand:X87MODEF 1 "register_operand" "0")]
- FRNDINT_ROUNDING))
+(define_insn "frndintxf2_<rounding>_i387"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ FRNDINT_ROUNDING))
(use (match_operand:HI 2 "memory_operand" "m"))
(use (match_operand:HI 3 "memory_operand" "m"))]
"TARGET_USE_FANCY_MATH_387
@@ -16964,7 +16276,7 @@
"fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
[(set_attr "type" "frndint")
(set_attr "i387_cw" "<rounding>")
- (set_attr "mode" "<MODE>")])
+ (set_attr "mode" "XF")])
(define_expand "<rounding_insn>xf2"
[(parallel [(set (match_operand:XF 0 "register_operand")
@@ -16984,11 +16296,11 @@
|| TARGET_MIX_SSE_I387)
&& (flag_fp_int_builtin_inexact || !flag_trapping_math))
|| (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
- && (TARGET_SSE4_1 || !flag_trapping_math
- || flag_fp_int_builtin_inexact))"
+ && (TARGET_SSE4_1 || flag_fp_int_builtin_inexact
+ || !flag_trapping_math))"
{
if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
- && (TARGET_SSE4_1 || !flag_trapping_math || flag_fp_int_builtin_inexact))
+ && (TARGET_SSE4_1 || flag_fp_int_builtin_inexact || !flag_trapping_math))
{
if (TARGET_SSE4_1)
emit_insn (gen_sse4_1_round<mode>2
@@ -17018,7 +16330,14 @@
}
}
else
- emit_insn (gen_frndint<mode>2_<rounding> (operands[0], operands[1]));
+ {
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2_<rounding> (op0, op1));
+ emit_insn (gen_truncxf<mode>2_i387_noop_unspec (operands[0], op0));
+ }
DONE;
})
@@ -17082,8 +16401,7 @@
emit_insn (gen_extend<mode>xf2 (op1, operands[1]));
emit_insn (gen_frndintxf2_mask_pm (op0, op1));
-
- emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0));
+ emit_insn (gen_truncxf<mode>2 (operands[0], op0));
DONE;
})
@@ -17104,16 +16422,9 @@
operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
operands[3] = assign_386_stack_local (HImode, SLOT_CW_<ROUNDING>);
- if (memory_operand (operands[0], VOIDmode))
- emit_insn (gen_fist<mode>2_<rounding> (operands[0], operands[1],
- operands[2], operands[3]));
- else
- {
- operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
- emit_insn (gen_fist<mode>2_<rounding>_with_temp
- (operands[0], operands[1], operands[2],
- operands[3], operands[4]));
- }
+
+ emit_insn (gen_fist<mode>2_<rounding> (operands[0], operands[1],
+ operands[2], operands[3]));
DONE;
}
[(set_attr "type" "fistp")
@@ -17121,7 +16432,7 @@
(set_attr "mode" "<MODE>")])
(define_insn "fistdi2_<rounding>"
- [(set (match_operand:DI 0 "memory_operand" "=m")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=m")
(unspec:DI [(match_operand:XF 1 "register_operand" "f")]
FIST_ROUNDING))
(use (match_operand:HI 2 "memory_operand" "m"))
@@ -17134,54 +16445,8 @@
(set_attr "i387_cw" "<rounding>")
(set_attr "mode" "DI")])
-(define_insn "fistdi2_<rounding>_with_temp"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
- (unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
- FIST_ROUNDING))
- (use (match_operand:HI 2 "memory_operand" "m,m"))
- (use (match_operand:HI 3 "memory_operand" "m,m"))
- (clobber (match_operand:DI 4 "memory_operand" "=X,m"))
- (clobber (match_scratch:XF 5 "=&1f,&1f"))]
- "TARGET_USE_FANCY_MATH_387
- && flag_unsafe_math_optimizations"
- "#"
- [(set_attr "type" "fistp")
- (set_attr "i387_cw" "<rounding>")
- (set_attr "mode" "DI")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand")
- (unspec:DI [(match_operand:XF 1 "register_operand")]
- FIST_ROUNDING))
- (use (match_operand:HI 2 "memory_operand"))
- (use (match_operand:HI 3 "memory_operand"))
- (clobber (match_operand:DI 4 "memory_operand"))
- (clobber (match_scratch 5))]
- "reload_completed"
- [(parallel [(set (match_dup 4)
- (unspec:DI [(match_dup 1)] FIST_ROUNDING))
- (use (match_dup 2))
- (use (match_dup 3))
- (clobber (match_dup 5))])
- (set (match_dup 0) (match_dup 4))])
-
-(define_split
- [(set (match_operand:DI 0 "memory_operand")
- (unspec:DI [(match_operand:XF 1 "register_operand")]
- FIST_ROUNDING))
- (use (match_operand:HI 2 "memory_operand"))
- (use (match_operand:HI 3 "memory_operand"))
- (clobber (match_operand:DI 4 "memory_operand"))
- (clobber (match_scratch 5))]
- "reload_completed"
- [(parallel [(set (match_dup 0)
- (unspec:DI [(match_dup 1)] FIST_ROUNDING))
- (use (match_dup 2))
- (use (match_dup 3))
- (clobber (match_dup 5))])])
-
(define_insn "fist<mode>2_<rounding>"
- [(set (match_operand:SWI24 0 "memory_operand" "=m")
+ [(set (match_operand:SWI24 0 "nonimmediate_operand" "=m")
(unspec:SWI24 [(match_operand:XF 1 "register_operand" "f")]
FIST_ROUNDING))
(use (match_operand:HI 2 "memory_operand" "m"))
@@ -17193,47 +16458,6 @@
(set_attr "i387_cw" "<rounding>")
(set_attr "mode" "<MODE>")])
-(define_insn "fist<mode>2_<rounding>_with_temp"
- [(set (match_operand:SWI24 0 "nonimmediate_operand" "=m,?r")
- (unspec:SWI24 [(match_operand:XF 1 "register_operand" "f,f")]
- FIST_ROUNDING))
- (use (match_operand:HI 2 "memory_operand" "m,m"))
- (use (match_operand:HI 3 "memory_operand" "m,m"))
- (clobber (match_operand:SWI24 4 "memory_operand" "=X,m"))]
- "TARGET_USE_FANCY_MATH_387
- && flag_unsafe_math_optimizations"
- "#"
- [(set_attr "type" "fistp")
- (set_attr "i387_cw" "<rounding>")
- (set_attr "mode" "<MODE>")])
-
-(define_split
- [(set (match_operand:SWI24 0 "register_operand")
- (unspec:SWI24 [(match_operand:XF 1 "register_operand")]
- FIST_ROUNDING))
- (use (match_operand:HI 2 "memory_operand"))
- (use (match_operand:HI 3 "memory_operand"))
- (clobber (match_operand:SWI24 4 "memory_operand"))]
- "reload_completed"
- [(parallel [(set (match_dup 4)
- (unspec:SWI24 [(match_dup 1)] FIST_ROUNDING))
- (use (match_dup 2))
- (use (match_dup 3))])
- (set (match_dup 0) (match_dup 4))])
-
-(define_split
- [(set (match_operand:SWI24 0 "memory_operand")
- (unspec:SWI24 [(match_operand:XF 1 "register_operand")]
- FIST_ROUNDING))
- (use (match_operand:HI 2 "memory_operand"))
- (use (match_operand:HI 3 "memory_operand"))
- (clobber (match_operand:SWI24 4 "memory_operand"))]
- "reload_completed"
- [(parallel [(set (match_dup 0)
- (unspec:SWI24 [(match_dup 1)] FIST_ROUNDING))
- (use (match_dup 2))
- (use (match_dup 3))])])
-
(define_expand "l<rounding_insn>xf<mode>2"
[(parallel [(set (match_operand:SWI248x 0 "nonimmediate_operand")
(unspec:SWI248x [(match_operand:XF 1 "register_operand")]
@@ -18211,7 +17435,6 @@
""
"sbb{<imodesuffix>}\t%0, %0"
[(set_attr "type" "alu1")
- (set_attr "modrm_class" "op0")
(set_attr "use_carry" "1")
(set_attr "pent_pair" "pu")
(set_attr "mode" "<MODE>")
@@ -18227,7 +17450,6 @@
""
"sbb{<imodesuffix>}\t%0, %0"
[(set_attr "type" "alu1")
- (set_attr "modrm_class" "op0")
(set_attr "use_carry" "1")
(set_attr "pent_pair" "pu")
(set_attr "mode" "<MODE>")
@@ -18241,7 +17463,6 @@
""
"sbb{<imodesuffix>}\t%0, %0"
[(set_attr "type" "alu1")
- (set_attr "modrm_class" "op0")
(set_attr "use_carry" "1")
(set_attr "pent_pair" "pu")
(set_attr "mode" "<MODE>")
@@ -20979,6 +20200,13 @@
[(set_attr "type" "other")
(set_attr "memory" "unknown")])
+(define_insn "speculation_barrier"
+ [(unspec_volatile [(const_int 0)] UNSPECV_SPECULATION_BARRIER)]
+ ""
+ "lfence"
+ [(set_attr "type" "other")
+ (set_attr "length" "3")])
+
(include "mmx.md")
(include "sse.md")
(include "sync.md")
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index a34d4ac..e7fbf9b 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -842,7 +842,7 @@ Target Report Mask(ISA_CLWB) Var(ix86_isa_flags) Save
Support CLWB instruction.
mpcommit
-Target Undocumented Warn(%<-mpcommit%> was deprecated)
+Target Deprecated
;; Deprecated
mfxsr
@@ -951,7 +951,7 @@ Target Report Mask(ISA_RTM) Var(ix86_isa_flags) Save
Support RTM built-in functions and code generation.
mmpx
-Target Report Deprecated
+Target Deprecated
Deprecated in GCC 9. This switch has no effect.
mmwaitx
@@ -999,8 +999,8 @@ Target RejectNegative Joined Integer Var(ix86_stack_protector_guard_symbol_str)
Use the given symbol for addressing the stack-protector guard.
mmitigate-rop
-Target Var(flag_mitigate_rop)
-Attempt to avoid generating instruction sequences containing ret bytes.
+Target Deprecated
+;; Deprecated
mgeneral-regs-only
Target Report RejectNegative Mask(GENERAL_REGS_ONLY) Var(ix86_target_flags) Save
diff --git a/gcc/config/i386/movdirintrin.h b/gcc/config/i386/movdirintrin.h
index 8b4d0b3..75a5552 100644
--- a/gcc/config/i386/movdirintrin.h
+++ b/gcc/config/i386/movdirintrin.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2017 Free Software Foundation, Inc.
+/* Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of GCC.
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index babaf1d..ed3bc7c 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -1135,9 +1135,6 @@
(define_predicate "vsib_mem_operator"
(match_code "mem"))
-(define_predicate "bnd_mem_operator"
- (match_code "mem"))
-
;; Return true if the rtx is known to be at least 32 bits aligned.
(define_predicate "aligned_operand"
(match_operand 0 "general_operand")
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index d2722fdf..1e260c0 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -19951,7 +19951,7 @@
[(set (match_operand:V16SF 0 "register_operand" "=v")
(unspec:V16SF
[(match_operand:V16SF 1 "register_operand" "0")
- (match_operand:V64SF 2 "register_operand" "Yh")
+ (match_operand:V64SF 2 "register_operand" "v")
(match_operand:V4SF 3 "memory_operand" "m")] UNSPEC_VP4FMADD))]
"TARGET_AVX5124FMAPS"
"v4fmaddps\t{%3, %g2, %0|%0, %g2, %3}"
@@ -19963,7 +19963,7 @@
[(set (match_operand:V16SF 0 "register_operand" "=v")
(vec_merge:V16SF
(unspec:V16SF
- [(match_operand:V64SF 1 "register_operand" "Yh")
+ [(match_operand:V64SF 1 "register_operand" "v")
(match_operand:V4SF 2 "memory_operand" "m")] UNSPEC_VP4FMADD)
(match_operand:V16SF 3 "register_operand" "0")
(match_operand:HI 4 "register_operand" "Yk")))]
@@ -19978,7 +19978,7 @@
(vec_merge:V16SF
(unspec:V16SF
[(match_operand:V16SF 1 "register_operand" "0")
- (match_operand:V64SF 2 "register_operand" "Yh")
+ (match_operand:V64SF 2 "register_operand" "v")
(match_operand:V4SF 3 "memory_operand" "m")] UNSPEC_VP4FMADD)
(match_operand:V16SF 4 "const0_operand" "C")
(match_operand:HI 5 "register_operand" "Yk")))]
@@ -19992,7 +19992,7 @@
[(set (match_operand:V4SF 0 "register_operand" "=v")
(unspec:V4SF
[(match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V64SF 2 "register_operand" "Yh")
+ (match_operand:V64SF 2 "register_operand" "v")
(match_operand:V4SF 3 "memory_operand" "m")] UNSPEC_VP4FMADD))]
"TARGET_AVX5124FMAPS"
"v4fmaddss\t{%3, %x2, %0|%0, %x2, %3}"
@@ -20004,7 +20004,7 @@
[(set (match_operand:V4SF 0 "register_operand" "=v")
(vec_merge:V4SF
(unspec:V4SF
- [(match_operand:V64SF 1 "register_operand" "Yh")
+ [(match_operand:V64SF 1 "register_operand" "v")
(match_operand:V4SF 2 "memory_operand" "m")] UNSPEC_VP4FMADD)
(match_operand:V4SF 3 "register_operand" "0")
(match_operand:QI 4 "register_operand" "Yk")))]
@@ -20019,7 +20019,7 @@
(vec_merge:V4SF
(unspec:V4SF
[(match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V64SF 2 "register_operand" "Yh")
+ (match_operand:V64SF 2 "register_operand" "v")
(match_operand:V4SF 3 "memory_operand" "m")] UNSPEC_VP4FMADD)
(match_operand:V4SF 4 "const0_operand" "C")
(match_operand:QI 5 "register_operand" "Yk")))]
@@ -20033,7 +20033,7 @@
[(set (match_operand:V16SF 0 "register_operand" "=v")
(unspec:V16SF
[(match_operand:V16SF 1 "register_operand" "0")
- (match_operand:V64SF 2 "register_operand" "Yh")
+ (match_operand:V64SF 2 "register_operand" "v")
(match_operand:V4SF 3 "memory_operand" "m")] UNSPEC_VP4FNMADD))]
"TARGET_AVX5124FMAPS"
"v4fnmaddps\t{%3, %g2, %0|%0, %g2, %3}"
@@ -20045,7 +20045,7 @@
[(set (match_operand:V16SF 0 "register_operand" "=v")
(vec_merge:V16SF
(unspec:V16SF
- [(match_operand:V64SF 1 "register_operand" "Yh")
+ [(match_operand:V64SF 1 "register_operand" "v")
(match_operand:V4SF 2 "memory_operand" "m")] UNSPEC_VP4FNMADD)
(match_operand:V16SF 3 "register_operand" "0")
(match_operand:HI 4 "register_operand" "Yk")))]
@@ -20060,7 +20060,7 @@
(vec_merge:V16SF
(unspec:V16SF
[(match_operand:V16SF 1 "register_operand" "0")
- (match_operand:V64SF 2 "register_operand" "Yh")
+ (match_operand:V64SF 2 "register_operand" "v")
(match_operand:V4SF 3 "memory_operand" "m")] UNSPEC_VP4FNMADD)
(match_operand:V16SF 4 "const0_operand" "C")
(match_operand:HI 5 "register_operand" "Yk")))]
@@ -20074,7 +20074,7 @@
[(set (match_operand:V4SF 0 "register_operand" "=v")
(unspec:V4SF
[(match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V64SF 2 "register_operand" "Yh")
+ (match_operand:V64SF 2 "register_operand" "v")
(match_operand:V4SF 3 "memory_operand" "m")] UNSPEC_VP4FNMADD))]
"TARGET_AVX5124FMAPS"
"v4fnmaddss\t{%3, %x2, %0|%0, %x2, %3}"
@@ -20086,7 +20086,7 @@
[(set (match_operand:V4SF 0 "register_operand" "=v")
(vec_merge:V4SF
(unspec:V4SF
- [(match_operand:V64SF 1 "register_operand" "Yh")
+ [(match_operand:V64SF 1 "register_operand" "v")
(match_operand:V4SF 2 "memory_operand" "m")] UNSPEC_VP4FNMADD)
(match_operand:V4SF 3 "register_operand" "0")
(match_operand:QI 4 "register_operand" "Yk")))]
@@ -20101,7 +20101,7 @@
(vec_merge:V4SF
(unspec:V4SF
[(match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V64SF 2 "register_operand" "Yh")
+ (match_operand:V64SF 2 "register_operand" "v")
(match_operand:V4SF 3 "memory_operand" "m")] UNSPEC_VP4FNMADD)
(match_operand:V4SF 4 "const0_operand" "C")
(match_operand:QI 5 "register_operand" "Yk")))]
@@ -20115,7 +20115,7 @@
[(set (match_operand:V16SI 0 "register_operand" "=v")
(unspec:V16SI
[(match_operand:V16SI 1 "register_operand" "0")
- (match_operand:V64SI 2 "register_operand" "Yh")
+ (match_operand:V64SI 2 "register_operand" "v")
(match_operand:V4SI 3 "memory_operand" "m")] UNSPEC_VP4DPWSSD))]
"TARGET_AVX5124VNNIW"
"vp4dpwssd\t{%3, %g2, %0|%0, %g2, %3}"
@@ -20127,7 +20127,7 @@
[(set (match_operand:V16SI 0 "register_operand" "=v")
(vec_merge:V16SI
(unspec:V16SI
- [(match_operand:V64SI 1 "register_operand" "Yh")
+ [(match_operand:V64SI 1 "register_operand" "v")
(match_operand:V4SI 2 "memory_operand" "m")] UNSPEC_VP4DPWSSD)
(match_operand:V16SI 3 "register_operand" "0")
(match_operand:HI 4 "register_operand" "Yk")))]
@@ -20142,7 +20142,7 @@
(vec_merge:V16SI
(unspec:V16SI
[(match_operand:V16SI 1 "register_operand" "0")
- (match_operand:V64SI 2 "register_operand" "Yh")
+ (match_operand:V64SI 2 "register_operand" "v")
(match_operand:V4SI 3 "memory_operand" "m")] UNSPEC_VP4DPWSSD)
(match_operand:V16SI 4 "const0_operand" "C")
(match_operand:HI 5 "register_operand" "Yk")))]
@@ -20156,7 +20156,7 @@
[(set (match_operand:V16SI 0 "register_operand" "=v")
(unspec:V16SI
[(match_operand:V16SI 1 "register_operand" "0")
- (match_operand:V64SI 2 "register_operand" "Yh")
+ (match_operand:V64SI 2 "register_operand" "v")
(match_operand:V4SI 3 "memory_operand" "m")] UNSPEC_VP4DPWSSDS))]
"TARGET_AVX5124VNNIW"
"vp4dpwssds\t{%3, %g2, %0|%0, %g2, %3}"
@@ -20168,7 +20168,7 @@
[(set (match_operand:V16SI 0 "register_operand" "=v")
(vec_merge:V16SI
(unspec:V16SI
- [(match_operand:V64SI 1 "register_operand" "Yh")
+ [(match_operand:V64SI 1 "register_operand" "v")
(match_operand:V4SI 2 "memory_operand" "m")] UNSPEC_VP4DPWSSDS)
(match_operand:V16SI 3 "register_operand" "0")
(match_operand:HI 4 "register_operand" "Yk")))]
@@ -20183,7 +20183,7 @@
(vec_merge:V16SI
(unspec:V16SI
[(match_operand:V16SI 1 "register_operand" "0")
- (match_operand:V64SI 2 "register_operand" "Yh")
+ (match_operand:V64SI 2 "register_operand" "v")
(match_operand:V4SI 3 "memory_operand" "m")] UNSPEC_VP4DPWSSDS)
(match_operand:V16SI 4 "const0_operand" "C")
(match_operand:HI 5 "register_operand" "Yk")))]
diff --git a/gcc/config/i386/x86-tune-costs.h b/gcc/config/i386/x86-tune-costs.h
index ff28934..71a5854 100644
--- a/gcc/config/i386/x86-tune-costs.h
+++ b/gcc/config/i386/x86-tune-costs.h
@@ -111,6 +111,10 @@ struct processor_costs ix86_size_cost = {/* costs for tuning for size */
ix86_size_memset,
COSTS_N_BYTES (1), /* cond_taken_branch_cost. */
COSTS_N_BYTES (1), /* cond_not_taken_branch_cost. */
+ NULL, /* Loop alignment. */
+ NULL, /* Jump alignment. */
+ NULL, /* Label alignment. */
+ NULL, /* Func alignment. */
};
/* Processor costs (relative to an add) */
@@ -197,6 +201,10 @@ struct processor_costs i386_cost = { /* 386 specific costs */
i386_memset,
COSTS_N_INSNS (3), /* cond_taken_branch_cost. */
COSTS_N_INSNS (1), /* cond_not_taken_branch_cost. */
+ "4", /* Loop alignment. */
+ "4", /* Jump alignment. */
+ NULL, /* Label alignment. */
+ "4", /* Func alignment. */
};
static stringop_algs i486_memcpy[2] = {
@@ -284,6 +292,10 @@ struct processor_costs i486_cost = { /* 486 specific costs */
i486_memset,
COSTS_N_INSNS (3), /* cond_taken_branch_cost. */
COSTS_N_INSNS (1), /* cond_not_taken_branch_cost. */
+ "16", /* Loop alignment. */
+ "16", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "16", /* Func alignment. */
};
static stringop_algs pentium_memcpy[2] = {
@@ -369,6 +381,10 @@ struct processor_costs pentium_cost = {
pentium_memset,
COSTS_N_INSNS (3), /* cond_taken_branch_cost. */
COSTS_N_INSNS (1), /* cond_not_taken_branch_cost. */
+ "16:8:8", /* Loop alignment. */
+ "16:8:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "16", /* Func alignment. */
};
static const
@@ -447,6 +463,10 @@ struct processor_costs lakemont_cost = {
pentium_memset,
COSTS_N_INSNS (3), /* cond_taken_branch_cost. */
COSTS_N_INSNS (1), /* cond_not_taken_branch_cost. */
+ "16:8:8", /* Loop alignment. */
+ "16:8:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "16", /* Func alignment. */
};
/* PentiumPro has optimized rep instructions for blocks aligned by 8 bytes
@@ -540,6 +560,10 @@ struct processor_costs pentiumpro_cost = {
pentiumpro_memset,
COSTS_N_INSNS (3), /* cond_taken_branch_cost. */
COSTS_N_INSNS (1), /* cond_not_taken_branch_cost. */
+ "16", /* Loop alignment. */
+ "16:11:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "16", /* Func alignment. */
};
static stringop_algs geode_memcpy[2] = {
@@ -625,6 +649,10 @@ struct processor_costs geode_cost = {
geode_memset,
COSTS_N_INSNS (3), /* cond_taken_branch_cost. */
COSTS_N_INSNS (1), /* cond_not_taken_branch_cost. */
+ NULL, /* Loop alignment. */
+ NULL, /* Jump alignment. */
+ NULL, /* Label alignment. */
+ NULL, /* Func alignment. */
};
static stringop_algs k6_memcpy[2] = {
@@ -712,6 +740,10 @@ struct processor_costs k6_cost = {
k6_memset,
COSTS_N_INSNS (3), /* cond_taken_branch_cost. */
COSTS_N_INSNS (1), /* cond_not_taken_branch_cost. */
+ "32:8:8", /* Loop alignment. */
+ "32:8:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "32", /* Func alignment. */
};
/* For some reason, Athlon deals better with REP prefix (relative to loops)
@@ -800,6 +832,10 @@ struct processor_costs athlon_cost = {
athlon_memset,
COSTS_N_INSNS (3), /* cond_taken_branch_cost. */
COSTS_N_INSNS (1), /* cond_not_taken_branch_cost. */
+ "16:8:8", /* Loop alignment. */
+ "16:8:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "16", /* Func alignment. */
};
/* K8 has optimized REP instruction for medium sized blocks, but for very
@@ -897,6 +933,10 @@ struct processor_costs k8_cost = {
k8_memset,
COSTS_N_INSNS (3), /* cond_taken_branch_cost. */
COSTS_N_INSNS (2), /* cond_not_taken_branch_cost. */
+ "16:8:8", /* Loop alignment. */
+ "16:8:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "16", /* Func alignment. */
};
/* AMDFAM10 has optimized REP instruction for medium sized blocks, but for
@@ -1001,6 +1041,10 @@ struct processor_costs amdfam10_cost = {
amdfam10_memset,
COSTS_N_INSNS (2), /* cond_taken_branch_cost. */
COSTS_N_INSNS (1), /* cond_not_taken_branch_cost. */
+ "32:25:8", /* Loop alignment. */
+ "32:8:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "32", /* Func alignment. */
};
/* BDVER1 has optimized REP instruction for medium sized blocks, but for
@@ -1099,6 +1143,10 @@ const struct processor_costs bdver1_cost = {
bdver1_memset,
COSTS_N_INSNS (4), /* cond_taken_branch_cost. */
COSTS_N_INSNS (2), /* cond_not_taken_branch_cost. */
+ "16:11:8", /* Loop alignment. */
+ "16:8:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "11", /* Func alignment. */
};
/* BDVER2 has optimized REP instruction for medium sized blocks, but for
@@ -1198,6 +1246,10 @@ const struct processor_costs bdver2_cost = {
bdver2_memset,
COSTS_N_INSNS (4), /* cond_taken_branch_cost. */
COSTS_N_INSNS (2), /* cond_not_taken_branch_cost. */
+ "16:11:8", /* Loop alignment. */
+ "16:8:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "11", /* Func alignment. */
};
@@ -1296,6 +1348,10 @@ struct processor_costs bdver3_cost = {
bdver3_memset,
COSTS_N_INSNS (4), /* cond_taken_branch_cost. */
COSTS_N_INSNS (2), /* cond_not_taken_branch_cost. */
+ "16:11:8", /* Loop alignment. */
+ "16:8:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "11", /* Func alignment. */
};
/* BDVER4 has optimized REP instruction for medium sized blocks, but for
@@ -1393,6 +1449,10 @@ struct processor_costs bdver4_cost = {
bdver4_memset,
COSTS_N_INSNS (4), /* cond_taken_branch_cost. */
COSTS_N_INSNS (2), /* cond_not_taken_branch_cost. */
+ "16:11:8", /* Loop alignment. */
+ "16:8:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "11", /* Func alignment. */
};
@@ -1513,6 +1573,10 @@ struct processor_costs znver1_cost = {
znver1_memset,
COSTS_N_INSNS (4), /* cond_taken_branch_cost. */
COSTS_N_INSNS (2), /* cond_not_taken_branch_cost. */
+ "16", /* Loop alignment. */
+ "16", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "16", /* Func alignment. */
};
/* skylake_cost should produce code tuned for Skylake familly of CPUs. */
@@ -1605,6 +1669,10 @@ struct processor_costs skylake_cost = {
skylake_memset,
COSTS_N_INSNS (3), /* cond_taken_branch_cost. */
COSTS_N_INSNS (1), /* cond_not_taken_branch_cost. */
+ "16:11:8", /* Loop alignment. */
+ "16:11:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "16", /* Func alignment. */
};
/* BTVER1 has optimized REP instruction for medium sized blocks, but for
very small blocks it is better to use loop. For large blocks, libcall can
@@ -1694,6 +1762,10 @@ const struct processor_costs btver1_cost = {
btver1_memset,
COSTS_N_INSNS (2), /* cond_taken_branch_cost. */
COSTS_N_INSNS (1), /* cond_not_taken_branch_cost. */
+ "16:11:8", /* Loop alignment. */
+ "16:8:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "11", /* Func alignment. */
};
static stringop_algs btver2_memcpy[2] = {
@@ -1781,6 +1853,10 @@ const struct processor_costs btver2_cost = {
btver2_memset,
COSTS_N_INSNS (2), /* cond_taken_branch_cost. */
COSTS_N_INSNS (1), /* cond_not_taken_branch_cost. */
+ "16:11:8", /* Loop alignment. */
+ "16:8:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "11", /* Func alignment. */
};
static stringop_algs pentium4_memcpy[2] = {
@@ -1867,6 +1943,10 @@ struct processor_costs pentium4_cost = {
pentium4_memset,
COSTS_N_INSNS (3), /* cond_taken_branch_cost. */
COSTS_N_INSNS (1), /* cond_not_taken_branch_cost. */
+ NULL, /* Loop alignment. */
+ NULL, /* Jump alignment. */
+ NULL, /* Label alignment. */
+ NULL, /* Func alignment. */
};
static stringop_algs nocona_memcpy[2] = {
@@ -1956,6 +2036,10 @@ struct processor_costs nocona_cost = {
nocona_memset,
COSTS_N_INSNS (3), /* cond_taken_branch_cost. */
COSTS_N_INSNS (1), /* cond_not_taken_branch_cost. */
+ NULL, /* Loop alignment. */
+ NULL, /* Jump alignment. */
+ NULL, /* Label alignment. */
+ NULL, /* Func alignment. */
};
static stringop_algs atom_memcpy[2] = {
@@ -2043,6 +2127,10 @@ struct processor_costs atom_cost = {
atom_memset,
COSTS_N_INSNS (3), /* cond_taken_branch_cost. */
COSTS_N_INSNS (1), /* cond_not_taken_branch_cost. */
+ "16", /* Loop alignment. */
+ "16:8:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "16", /* Func alignment. */
};
static stringop_algs slm_memcpy[2] = {
@@ -2130,6 +2218,10 @@ struct processor_costs slm_cost = {
slm_memset,
COSTS_N_INSNS (3), /* cond_taken_branch_cost. */
COSTS_N_INSNS (1), /* cond_not_taken_branch_cost. */
+ "16", /* Loop alignment. */
+ "16:8:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "16", /* Func alignment. */
};
static stringop_algs intel_memcpy[2] = {
@@ -2217,6 +2309,10 @@ struct processor_costs intel_cost = {
intel_memset,
COSTS_N_INSNS (3), /* cond_taken_branch_cost. */
COSTS_N_INSNS (1), /* cond_not_taken_branch_cost. */
+ "16", /* Loop alignment. */
+ "16:8:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "16", /* Func alignment. */
};
/* Generic should produce code tuned for Core-i7 (and newer chips)
@@ -2313,6 +2409,10 @@ struct processor_costs generic_cost = {
generic_memset,
COSTS_N_INSNS (4), /* cond_taken_branch_cost. */
COSTS_N_INSNS (2), /* cond_not_taken_branch_cost. */
+ "16:11:8", /* Loop alignment. */
+ "16:11:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "16", /* Func alignment. */
};
/* core_cost should produce code tuned for Core familly of CPUs. */
@@ -2416,5 +2516,9 @@ struct processor_costs core_cost = {
core_memset,
COSTS_N_INSNS (3), /* cond_taken_branch_cost. */
COSTS_N_INSNS (1), /* cond_not_taken_branch_cost. */
+ "16:11:8", /* Loop alignment. */
+ "16:11:8", /* Jump alignment. */
+ "0:0:8", /* Label alignment. */
+ "16", /* Func alignment. */
};
diff --git a/gcc/config/i386/xmmintrin.h b/gcc/config/i386/xmmintrin.h
index f64f3f7..f770570 100644
--- a/gcc/config/i386/xmmintrin.h
+++ b/gcc/config/i386/xmmintrin.h
@@ -1011,7 +1011,10 @@ _mm_storer_ps (float *__P, __m128 __A)
extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_move_ss (__m128 __A, __m128 __B)
{
- return (__m128) __builtin_ia32_movss ((__v4sf)__A, (__v4sf)__B);
+ return (__m128) __builtin_shuffle ((__v4sf)__A, (__v4sf)__B,
+ __extension__
+ (__attribute__((__vector_size__ (16))) int)
+ {4,1,2,3});
}
/* Extracts one of the four words of A. The selector N must be immediate. */
diff --git a/gcc/config/ia64/ia64.opt b/gcc/config/ia64/ia64.opt
index 5a8b2b8..61f2c9f 100644
--- a/gcc/config/ia64/ia64.opt
+++ b/gcc/config/ia64/ia64.opt
@@ -164,10 +164,10 @@ Target Report Var(mflag_sched_spec_control_ldc) Init(0)
Use simple data speculation check for control speculation.
msched-prefer-non-data-spec-insns
-Target Ignore Warn(switch %qs is no longer supported)
+Target Deprecated
msched-prefer-non-control-spec-insns
-Target Ignore Warn(switch %qs is no longer supported)
+Target Deprecated
msched-count-spec-in-critical-path
Target Report Var(mflag_sched_count_spec_in_critical_path) Init(0)
diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c
index ee89ced..4b30a44 100644
--- a/gcc/config/iq2000/iq2000.c
+++ b/gcc/config/iq2000/iq2000.c
@@ -274,6 +274,9 @@ static HOST_WIDE_INT iq2000_starting_frame_offset (void);
#undef TARGET_STARTING_FRAME_OFFSET
#define TARGET_STARTING_FRAME_OFFSET iq2000_starting_frame_offset
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Return nonzero if we split the address into high and low parts. */
diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c
index 06c8085..a2bd289 100644
--- a/gcc/config/m32r/m32r.c
+++ b/gcc/config/m32r/m32r.c
@@ -226,6 +226,9 @@ static const struct attribute_spec m32r_attribute_table[] =
#undef TARGET_STARTING_FRAME_OFFSET
#define TARGET_STARTING_FRAME_OFFSET m32r_starting_frame_offset
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Called by m32r_option_override to initialize various things. */
diff --git a/gcc/config/m68k/m68k-protos.h b/gcc/config/m68k/m68k-protos.h
index 1f6a68f..f412db9 100644
--- a/gcc/config/m68k/m68k-protos.h
+++ b/gcc/config/m68k/m68k-protos.h
@@ -67,7 +67,6 @@ extern rtx m68k_function_value (const_tree, const_tree);
extern int emit_move_sequence (rtx *, machine_mode, rtx);
extern bool m68k_movem_pattern_p (rtx, rtx, HOST_WIDE_INT, bool);
extern const char *m68k_output_movem (rtx *, rtx, HOST_WIDE_INT, bool);
-extern void m68k_final_prescan_insn (rtx_insn *, rtx *, int);
extern bool m68k_epilogue_uses (int);
/* Functions from m68k.c used in constraints.md. */
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index ef8604e..ea41545 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -353,6 +353,9 @@ static machine_mode m68k_promote_function_mode (const_tree, machine_mode,
#undef TARGET_PROMOTE_FUNCTION_MODE
#define TARGET_PROMOTE_FUNCTION_MODE m68k_promote_function_mode
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
static const struct attribute_spec m68k_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req,
@@ -2326,14 +2329,11 @@ m68k_unwrap_symbol (rtx orig, bool unwrap_reloc32_p)
return m68k_unwrap_symbol_1 (orig, unwrap_reloc32_p, NULL);
}
-/* Prescan insn before outputing assembler for it. */
+/* Adjust decorated address operand before outputing assembler for it. */
-void
-m68k_final_prescan_insn (rtx_insn *insn ATTRIBUTE_UNUSED,
- rtx *operands, int n_operands)
+static void
+m68k_adjust_decorated_operand (rtx op)
{
- int i;
-
/* Combine and, possibly, other optimizations may do good job
converting
(const (unspec [(symbol)]))
@@ -2352,45 +2352,38 @@ m68k_final_prescan_insn (rtx_insn *insn ATTRIBUTE_UNUSED,
to patch up anything outside of the operand. */
subrtx_var_iterator::array_type array;
- for (i = 0; i < n_operands; ++i)
+ FOR_EACH_SUBRTX_VAR (iter, array, op, ALL)
{
- rtx op;
-
- op = operands[i];
-
- FOR_EACH_SUBRTX_VAR (iter, array, op, ALL)
+ rtx x = *iter;
+ if (m68k_unwrap_symbol (x, true) != x)
{
- rtx x = *iter;
- if (m68k_unwrap_symbol (x, true) != x)
- {
- rtx plus;
+ rtx plus;
- gcc_assert (GET_CODE (x) == CONST);
- plus = XEXP (x, 0);
+ gcc_assert (GET_CODE (x) == CONST);
+ plus = XEXP (x, 0);
- if (GET_CODE (plus) == PLUS || GET_CODE (plus) == MINUS)
- {
- rtx unspec;
- rtx addend;
+ if (GET_CODE (plus) == PLUS || GET_CODE (plus) == MINUS)
+ {
+ rtx unspec;
+ rtx addend;
- unspec = XEXP (plus, 0);
- gcc_assert (GET_CODE (unspec) == UNSPEC);
- addend = XEXP (plus, 1);
- gcc_assert (CONST_INT_P (addend));
+ unspec = XEXP (plus, 0);
+ gcc_assert (GET_CODE (unspec) == UNSPEC);
+ addend = XEXP (plus, 1);
+ gcc_assert (CONST_INT_P (addend));
- /* We now have all the pieces, rearrange them. */
+ /* We now have all the pieces, rearrange them. */
- /* Move symbol to plus. */
- XEXP (plus, 0) = XVECEXP (unspec, 0, 0);
+ /* Move symbol to plus. */
+ XEXP (plus, 0) = XVECEXP (unspec, 0, 0);
- /* Move plus inside unspec. */
- XVECEXP (unspec, 0, 0) = plus;
+ /* Move plus inside unspec. */
+ XVECEXP (unspec, 0, 0) = plus;
- /* Move unspec to top level of const. */
- XEXP (x, 0) = unspec;
- }
- iter.skip_subrtxes ();
+ /* Move unspec to top level of const. */
+ XEXP (x, 0) = unspec;
}
+ iter.skip_subrtxes ();
}
}
}
@@ -3493,7 +3486,6 @@ handle_move_double (rtx operands[2],
/* Normal case: do the two words, low-numbered first. */
- m68k_final_prescan_insn (NULL, operands, 2);
handle_movsi (operands);
/* Do the middle one of the three words for long double */
@@ -3504,7 +3496,6 @@ handle_move_double (rtx operands[2],
if (addreg1)
handle_reg_adjust (addreg1, 4);
- m68k_final_prescan_insn (NULL, middlehalf, 2);
handle_movsi (middlehalf);
}
@@ -3515,7 +3506,6 @@ handle_move_double (rtx operands[2],
handle_reg_adjust (addreg1, 4);
/* Do that word. */
- m68k_final_prescan_insn (NULL, latehalf, 2);
handle_movsi (latehalf);
/* Undo the adds we just did. */
@@ -4461,6 +4451,9 @@ floating_exact_log2 (rtx x)
void
print_operand (FILE *file, rtx op, int letter)
{
+ if (op != NULL_RTX)
+ m68k_adjust_decorated_operand (op);
+
if (letter == '.')
{
if (MOTOROLA)
@@ -4709,6 +4702,8 @@ print_operand_address (FILE *file, rtx addr)
{
struct m68k_address address;
+ m68k_adjust_decorated_operand (addr);
+
if (!m68k_decompose_address (QImode, addr, true, &address))
gcc_unreachable ();
diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
index 506fa4e..29e9be2 100644
--- a/gcc/config/m68k/m68k.h
+++ b/gcc/config/m68k/m68k.h
@@ -867,9 +867,6 @@ do { if (cc_prev_status.flags & CC_IN_68881) \
assemble_name ((FILE), (NAME)), \
fprintf ((FILE), ",%u\n", (int)(ROUNDED)))
-#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
- m68k_final_prescan_insn (INSN, OPVEC, NOPERANDS)
-
/* On the 68000, we use several CODE characters:
'.' for dot needed in Motorola-style opcode names.
'-' for an operand pushing on the stack:
diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c
index 88ea3ff..6df464d 100644
--- a/gcc/config/mcore/mcore.c
+++ b/gcc/config/mcore/mcore.c
@@ -253,6 +253,9 @@ static const struct attribute_spec mcore_attribute_table[] =
#undef TARGET_CONSTANT_ALIGNMENT
#define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Adjust the stack and return the number of bytes taken to do it. */
diff --git a/gcc/config/mips/frame-header-opt.c b/gcc/config/mips/frame-header-opt.c
index 77298dc..ed51947 100644
--- a/gcc/config/mips/frame-header-opt.c
+++ b/gcc/config/mips/frame-header-opt.c
@@ -29,13 +29,13 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "context.h"
#include "coretypes.h"
+#include "backend.h"
#include "tree.h"
#include "tree-core.h"
#include "tree-pass.h"
#include "target.h"
#include "target-globals.h"
#include "profile-count.h"
-#include "cfg.h"
#include "cgraph.h"
#include "function.h"
#include "basic-block.h"
diff --git a/gcc/config/mmix/mmix.c b/gcc/config/mmix/mmix.c
index 9da826c..0225f80 100644
--- a/gcc/config/mmix/mmix.c
+++ b/gcc/config/mmix/mmix.c
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "memmodel.h"
#include "tm_p.h"
#include "insn-config.h"
+#include "optabs.h"
#include "regs.h"
#include "emit-rtl.h"
#include "recog.h"
@@ -60,19 +61,16 @@ along with GCC; see the file COPYING3. If not see
/* We have no means to tell DWARF 2 about the register stack, so we need
to store the return address on the stack if an exception can get into
- this function. FIXME: Narrow condition. Before any whole-function
- analysis, df_regs_ever_live_p () isn't initialized. We know it's up-to-date
- after reload_completed; it may contain incorrect information some time
- before that. Within a RTL sequence (after a call to start_sequence,
- such as in RTL expanders), leaf_function_p doesn't see all insns
- (perhaps any insn). But regs_ever_live is up-to-date when
- leaf_function_p () isn't, so we "or" them together to get accurate
- information. FIXME: Some tweak to leaf_function_p might be
- preferable. */
+ this function. We'll have an "initial value" recorded for the
+ return-register if we've seen a call instruction emitted. This note
+ will be inaccurate before instructions are emitted, but the only caller
+ at that time is looking for modulo from stack-boundary, to which the
+ return-address does not contribute, and which is always 0 for MMIX
+ anyway. Beware of calling leaf_function_p here, as it'll abort if
+ called within a sequence. */
#define MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS \
(flag_exceptions \
- && ((reload_completed && df_regs_ever_live_p (MMIX_rJ_REGNUM)) \
- || !leaf_function_p ()))
+ && has_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM))
#define IS_MMIX_EH_RETURN_DATA_REG(REGNO) \
(crtl->calls_eh_return \
@@ -143,6 +141,7 @@ static void mmix_setup_incoming_varargs
(cumulative_args_t, machine_mode, tree, int *, int);
static void mmix_file_start (void);
static void mmix_file_end (void);
+static void mmix_init_libfuncs (void);
static bool mmix_rtx_costs (rtx, machine_mode, int, int, int *, bool);
static int mmix_register_move_cost (machine_mode,
reg_class_t, reg_class_t);
@@ -224,9 +223,15 @@ static HOST_WIDE_INT mmix_starting_frame_offset (void);
#undef TARGET_ASM_OUTPUT_SOURCE_FILENAME
#define TARGET_ASM_OUTPUT_SOURCE_FILENAME mmix_asm_output_source_filename
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS mmix_init_libfuncs
+
#undef TARGET_CONDITIONAL_REGISTER_USAGE
#define TARGET_CONDITIONAL_REGISTER_USAGE mmix_conditional_register_usage
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS mmix_rtx_costs
#undef TARGET_ADDRESS_COST
@@ -1308,6 +1313,20 @@ mmix_asm_output_source_filename (FILE *stream, const char *name)
fprintf (stream, "\n");
}
+/* Unfortunately, by default __builtin_ffs is expanded to ffs for
+ targets where INT_TYPE_SIZE < BITS_PER_WORD. That together with
+ newlib since 2017-07-04 implementing ffs as __builtin_ffs leads to
+ (newlib) ffs recursively calling itself. But, because of argument
+ promotion, and with ffs we're counting from the least bit, the
+ libgcc equivalent for ffsl works equally well for int arguments, so
+ just use that. */
+
+static void
+mmix_init_libfuncs (void)
+{
+ set_optab_libfunc (ffs_optab, SImode, "__ffsdi2");
+}
+
/* OUTPUT_QUOTED_STRING. */
void
@@ -1373,8 +1392,14 @@ mmix_assemble_integer (rtx x, unsigned int size, int aligned_p)
case 1:
if (GET_CODE (x) != CONST_INT)
{
- aligned_p = 0;
- break;
+ /* There is no "unaligned byte" op or generic function to
+ which we can punt, so we have to handle this here. As
+ the expression isn't a plain literal, the generated
+ assembly-code can't be mmixal-equivalent (i.e. "BYTE"
+ won't work) and thus it's ok to emit the default op
+ ".byte". */
+ assemble_integer_with_op ("\t.byte\t", x);
+ return true;
}
fputs ("\tBYTE\t", asm_out_file);
mmix_print_operand (asm_out_file, x, 'B');
diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c
index 1247f32..a7e5e6b 100644
--- a/gcc/config/mn10300/mn10300.c
+++ b/gcc/config/mn10300/mn10300.c
@@ -3437,4 +3437,7 @@ mn10300_reorg (void)
#undef TARGET_MODES_TIEABLE_P
#define TARGET_MODES_TIEABLE_P mn10300_modes_tieable_p
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
struct gcc_target targetm = TARGET_INITIALIZER;
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index 685bdc8..7d305b1 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -3871,6 +3871,9 @@ msp430_can_change_mode_class (machine_mode from, machine_mode to, reg_class_t)
return true;
}
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-msp430.h"
diff --git a/gcc/config/nds32/nds32-isr.c b/gcc/config/nds32/nds32-isr.c
index 2c3aac7..db67a0e 100644
--- a/gcc/config/nds32/nds32-isr.c
+++ b/gcc/config/nds32/nds32-isr.c
@@ -43,7 +43,260 @@
We use an array to record essential information for each vector. */
static struct nds32_isr_info nds32_isr_vectors[NDS32_N_ISR_VECTORS];
-/* ------------------------------------------------------------------------ */
+/* ------------------------------------------------------------- */
+/* FIXME:
+ FOR BACKWARD COMPATIBILITY, we need to support following patterns:
+
+ __attribute__((interrupt("XXX;YYY;id=ZZZ")))
+ __attribute__((exception("XXX;YYY;id=ZZZ")))
+ __attribute__((reset("vectors=XXX;nmi_func=YYY;warm_func=ZZZ")))
+
+ We provide several functions to parse the strings. */
+
+static void
+nds32_interrupt_attribute_parse_string (const char *original_str,
+ const char *func_name,
+ unsigned int s_level)
+{
+ char target_str[100];
+ enum nds32_isr_save_reg save_reg;
+ enum nds32_isr_nested_type nested_type;
+
+ char *save_all_regs_str, *save_caller_regs_str;
+ char *nested_str, *not_nested_str, *ready_nested_str, *critical_str;
+ char *id_str, *value_str;
+
+ /* Copy original string into a character array so that
+ the string APIs can handle it. */
+ strcpy (target_str, original_str);
+
+ /* 1. Detect 'save_all_regs' : NDS32_SAVE_ALL
+ 'save_caller_regs' : NDS32_PARTIAL_SAVE */
+ save_all_regs_str = strstr (target_str, "save_all_regs");
+ save_caller_regs_str = strstr (target_str, "save_caller_regs");
+
+ /* Note that if no argument is found,
+ use NDS32_PARTIAL_SAVE by default. */
+ if (save_all_regs_str)
+ save_reg = NDS32_SAVE_ALL;
+ else if (save_caller_regs_str)
+ save_reg = NDS32_PARTIAL_SAVE;
+ else
+ save_reg = NDS32_PARTIAL_SAVE;
+
+ /* 2. Detect 'nested' : NDS32_NESTED
+ 'not_nested' : NDS32_NOT_NESTED
+ 'ready_nested' : NDS32_NESTED_READY
+ 'critical' : NDS32_CRITICAL */
+ nested_str = strstr (target_str, "nested");
+ not_nested_str = strstr (target_str, "not_nested");
+ ready_nested_str = strstr (target_str, "ready_nested");
+ critical_str = strstr (target_str, "critical");
+
+ /* Note that if no argument is found,
+ use NDS32_NOT_NESTED by default.
+ Also, since 'not_nested' and 'ready_nested' both contains
+ 'nested' string, we check 'nested' with lowest priority. */
+ if (not_nested_str)
+ nested_type = NDS32_NOT_NESTED;
+ else if (ready_nested_str)
+ nested_type = NDS32_NESTED_READY;
+ else if (nested_str)
+ nested_type = NDS32_NESTED;
+ else if (critical_str)
+ nested_type = NDS32_CRITICAL;
+ else
+ nested_type = NDS32_NOT_NESTED;
+
+ /* 3. Traverse each id value and set corresponding information. */
+ id_str = strstr (target_str, "id=");
+
+ /* If user forgets to assign 'id', issue an error message. */
+ if (id_str == NULL)
+ error ("require id argument in the string");
+ /* Extract the value_str first. */
+ id_str = strtok (id_str, "=");
+ value_str = strtok (NULL, ";");
+
+ /* Pick up the first id value token. */
+ value_str = strtok (value_str, ",");
+ while (value_str != NULL)
+ {
+ int i;
+ i = atoi (value_str);
+
+ /* For interrupt(0..63), the actual vector number is (9..72). */
+ i = i + 9;
+ if (i < 9 || i > 72)
+ error ("invalid id value for interrupt attribute");
+
+ /* Setup nds32_isr_vectors[] array. */
+ nds32_isr_vectors[i].category = NDS32_ISR_INTERRUPT;
+ strcpy (nds32_isr_vectors[i].func_name, func_name);
+ nds32_isr_vectors[i].save_reg = save_reg;
+ nds32_isr_vectors[i].nested_type = nested_type;
+ nds32_isr_vectors[i].security_level = s_level;
+
+ /* Fetch next token. */
+ value_str = strtok (NULL, ",");
+ }
+
+ return;
+}
+
+static void
+nds32_exception_attribute_parse_string (const char *original_str,
+ const char *func_name,
+ unsigned int s_level)
+{
+ char target_str[100];
+ enum nds32_isr_save_reg save_reg;
+ enum nds32_isr_nested_type nested_type;
+
+ char *save_all_regs_str, *save_caller_regs_str;
+ char *nested_str, *not_nested_str, *ready_nested_str, *critical_str;
+ char *id_str, *value_str;
+
+ /* Copy original string into a character array so that
+ the string APIs can handle it. */
+ strcpy (target_str, original_str);
+
+ /* 1. Detect 'save_all_regs' : NDS32_SAVE_ALL
+ 'save_caller_regs' : NDS32_PARTIAL_SAVE */
+ save_all_regs_str = strstr (target_str, "save_all_regs");
+ save_caller_regs_str = strstr (target_str, "save_caller_regs");
+
+ /* Note that if no argument is found,
+ use NDS32_PARTIAL_SAVE by default. */
+ if (save_all_regs_str)
+ save_reg = NDS32_SAVE_ALL;
+ else if (save_caller_regs_str)
+ save_reg = NDS32_PARTIAL_SAVE;
+ else
+ save_reg = NDS32_PARTIAL_SAVE;
+
+ /* 2. Detect 'nested' : NDS32_NESTED
+ 'not_nested' : NDS32_NOT_NESTED
+ 'ready_nested' : NDS32_NESTED_READY
+ 'critical' : NDS32_CRITICAL */
+ nested_str = strstr (target_str, "nested");
+ not_nested_str = strstr (target_str, "not_nested");
+ ready_nested_str = strstr (target_str, "ready_nested");
+ critical_str = strstr (target_str, "critical");
+
+ /* Note that if no argument is found,
+ use NDS32_NOT_NESTED by default.
+ Also, since 'not_nested' and 'ready_nested' both contains
+ 'nested' string, we check 'nested' with lowest priority. */
+ if (not_nested_str)
+ nested_type = NDS32_NOT_NESTED;
+ else if (ready_nested_str)
+ nested_type = NDS32_NESTED_READY;
+ else if (nested_str)
+ nested_type = NDS32_NESTED;
+ else if (critical_str)
+ nested_type = NDS32_CRITICAL;
+ else
+ nested_type = NDS32_NOT_NESTED;
+
+ /* 3. Traverse each id value and set corresponding information. */
+ id_str = strstr (target_str, "id=");
+
+ /* If user forgets to assign 'id', issue an error message. */
+ if (id_str == NULL)
+ error ("require id argument in the string");
+ /* Extract the value_str first. */
+ id_str = strtok (id_str, "=");
+ value_str = strtok (NULL, ";");
+
+ /* Pick up the first id value token. */
+ value_str = strtok (value_str, ",");
+ while (value_str != NULL)
+ {
+ int i;
+ i = atoi (value_str);
+
+ /* For exception(1..8), the actual vector number is (1..8). */
+ if (i < 1 || i > 8)
+ error ("invalid id value for exception attribute");
+
+ /* Setup nds32_isr_vectors[] array. */
+ nds32_isr_vectors[i].category = NDS32_ISR_EXCEPTION;
+ strcpy (nds32_isr_vectors[i].func_name, func_name);
+ nds32_isr_vectors[i].save_reg = save_reg;
+ nds32_isr_vectors[i].nested_type = nested_type;
+ nds32_isr_vectors[i].security_level = s_level;
+
+ /* Fetch next token. */
+ value_str = strtok (NULL, ",");
+ }
+
+ return;
+}
+
+static void
+nds32_reset_attribute_parse_string (const char *original_str,
+ const char *func_name)
+{
+ char target_str[100];
+ char *vectors_str, *nmi_str, *warm_str, *value_str;
+
+ /* Deal with reset attribute. Its vector number is always 0. */
+ nds32_isr_vectors[0].category = NDS32_ISR_RESET;
+
+
+ /* 1. Parse 'vectors=XXXX'. */
+
+ /* Copy original string into a character array so that
+ the string APIs can handle it. */
+ strcpy (target_str, original_str);
+ vectors_str = strstr (target_str, "vectors=");
+ /* The total vectors = interrupt + exception numbers + reset.
+ There are 8 exception and 1 reset in nds32 architecture.
+ If user forgets to assign 'vectors', user default 16 interrupts. */
+ if (vectors_str != NULL)
+ {
+ /* Extract the value_str. */
+ vectors_str = strtok (vectors_str, "=");
+ value_str = strtok (NULL, ";");
+ nds32_isr_vectors[0].total_n_vectors = atoi (value_str) + 8 + 1;
+ }
+ else
+ nds32_isr_vectors[0].total_n_vectors = 16 + 8 + 1;
+ strcpy (nds32_isr_vectors[0].func_name, func_name);
+
+
+ /* 2. Parse 'nmi_func=YYYY'. */
+
+ /* Copy original string into a character array so that
+ the string APIs can handle it. */
+ strcpy (target_str, original_str);
+ nmi_str = strstr (target_str, "nmi_func=");
+ if (nmi_str != NULL)
+ {
+ /* Extract the value_str. */
+ nmi_str = strtok (nmi_str, "=");
+ value_str = strtok (NULL, ";");
+ strcpy (nds32_isr_vectors[0].nmi_name, value_str);
+ }
+
+ /* 3. Parse 'warm_func=ZZZZ'. */
+
+ /* Copy original string into a character array so that
+ the string APIs can handle it. */
+ strcpy (target_str, original_str);
+ warm_str = strstr (target_str, "warm_func=");
+ if (warm_str != NULL)
+ {
+ /* Extract the value_str. */
+ warm_str = strtok (warm_str, "=");
+ value_str = strtok (NULL, ";");
+ strcpy (nds32_isr_vectors[0].warm_name, value_str);
+ }
+
+ return;
+}
+/* ------------------------------------------------------------- */
/* A helper function to emit section head template. */
static void
@@ -79,6 +332,15 @@ nds32_emit_isr_jmptbl_section (int vector_id)
char section_name[100];
char symbol_name[100];
+ /* A critical isr does not need jump table section because
+ its behavior is not performed by two-level handler. */
+ if (nds32_isr_vectors[vector_id].nested_type == NDS32_CRITICAL)
+ {
+ fprintf (asm_out_file, "\t! The vector %02d is a critical isr !\n",
+ vector_id);
+ return;
+ }
+
/* Prepare jmptbl section and symbol name. */
snprintf (section_name, sizeof (section_name),
".nds32_jmptbl.%02d", vector_id);
@@ -99,7 +361,6 @@ nds32_emit_isr_vector_section (int vector_id)
const char *c_str = "CATEGORY";
const char *sr_str = "SR";
const char *nt_str = "NT";
- const char *vs_str = "VS";
char first_level_handler_name[100];
char section_name[100];
char symbol_name[100];
@@ -147,30 +408,47 @@ nds32_emit_isr_vector_section (int vector_id)
case NDS32_NESTED_READY:
nt_str = "nr";
break;
+ case NDS32_CRITICAL:
+ /* The critical isr is not performed by two-level handler. */
+ nt_str = "";
+ break;
}
- /* Currently we have 4-byte or 16-byte size for each vector.
- If it is 4-byte, the first level handler name has suffix string "_4b". */
- vs_str = (nds32_isr_vector_size == 4) ? "_4b" : "";
-
/* Now we can create first level handler name. */
- snprintf (first_level_handler_name, sizeof (first_level_handler_name),
- "_nds32_%s_%s_%s%s", c_str, sr_str, nt_str, vs_str);
+ if (nds32_isr_vectors[vector_id].security_level == 0)
+ {
+ /* For security level 0, use normal first level handler name. */
+ snprintf (first_level_handler_name, sizeof (first_level_handler_name),
+ "_nds32_%s_%s_%s", c_str, sr_str, nt_str);
+ }
+ else
+ {
+ /* For security level 1-3, use corresponding spl_1, spl_2, or spl_3. */
+ snprintf (first_level_handler_name, sizeof (first_level_handler_name),
+ "_nds32_spl_%d", nds32_isr_vectors[vector_id].security_level);
+ }
/* Prepare vector section and symbol name. */
snprintf (section_name, sizeof (section_name),
".nds32_vector.%02d", vector_id);
snprintf (symbol_name, sizeof (symbol_name),
- "_nds32_vector_%02d%s", vector_id, vs_str);
+ "_nds32_vector_%02d", vector_id);
/* Everything is ready. We can start emit vector section content. */
nds32_emit_section_head_template (section_name, symbol_name,
floor_log2 (nds32_isr_vector_size), false);
- /* According to the vector size, the instructions in the
- vector section may be different. */
- if (nds32_isr_vector_size == 4)
+ /* First we check if it is a critical isr.
+ If so, jump to user handler directly; otherwise, the instructions
+ in the vector section may be different according to the vector size. */
+ if (nds32_isr_vectors[vector_id].nested_type == NDS32_CRITICAL)
+ {
+ /* This block is for critical isr. Jump to user handler directly. */
+ fprintf (asm_out_file, "\tj\t%s ! jump to user handler directly\n",
+ nds32_isr_vectors[vector_id].func_name);
+ }
+ else if (nds32_isr_vector_size == 4)
{
/* This block is for 4-byte vector size.
Hardware $VID support is necessary and only one instruction
@@ -239,13 +517,11 @@ nds32_emit_isr_reset_content (void)
{
unsigned int i;
unsigned int total_n_vectors;
- const char *vs_str;
char reset_handler_name[100];
char section_name[100];
char symbol_name[100];
total_n_vectors = nds32_isr_vectors[0].total_n_vectors;
- vs_str = (nds32_isr_vector_size == 4) ? "_4b" : "";
fprintf (asm_out_file, "\t! RESET HANDLER CONTENT - BEGIN !\n");
@@ -261,7 +537,7 @@ nds32_emit_isr_reset_content (void)
/* Emit vector references. */
fprintf (asm_out_file, "\t ! references to vector section entries\n");
for (i = 0; i < total_n_vectors; i++)
- fprintf (asm_out_file, "\t.word\t_nds32_vector_%02d%s\n", i, vs_str);
+ fprintf (asm_out_file, "\t.word\t_nds32_vector_%02d\n", i);
/* Emit jmptbl_00 section. */
snprintf (section_name, sizeof (section_name), ".nds32_jmptbl.00");
@@ -275,9 +551,9 @@ nds32_emit_isr_reset_content (void)
/* Emit vector_00 section. */
snprintf (section_name, sizeof (section_name), ".nds32_vector.00");
- snprintf (symbol_name, sizeof (symbol_name), "_nds32_vector_00%s", vs_str);
+ snprintf (symbol_name, sizeof (symbol_name), "_nds32_vector_00");
snprintf (reset_handler_name, sizeof (reset_handler_name),
- "_nds32_reset%s", vs_str);
+ "_nds32_reset");
fprintf (asm_out_file, "\t! ....................................\n");
nds32_emit_section_head_template (section_name, symbol_name,
@@ -323,12 +599,12 @@ void
nds32_check_isr_attrs_conflict (tree func_decl, tree func_attrs)
{
int save_all_p, partial_save_p;
- int nested_p, not_nested_p, nested_ready_p;
+ int nested_p, not_nested_p, nested_ready_p, critical_p;
int intr_p, excp_p, reset_p;
/* Initialize variables. */
save_all_p = partial_save_p = 0;
- nested_p = not_nested_p = nested_ready_p = 0;
+ nested_p = not_nested_p = nested_ready_p = critical_p = 0;
intr_p = excp_p = reset_p = 0;
/* We must check at MOST one attribute to set save-reg. */
@@ -347,8 +623,10 @@ nds32_check_isr_attrs_conflict (tree func_decl, tree func_attrs)
not_nested_p = 1;
if (lookup_attribute ("nested_ready", func_attrs))
nested_ready_p = 1;
+ if (lookup_attribute ("critical", func_attrs))
+ critical_p = 1;
- if ((nested_p + not_nested_p + nested_ready_p) > 1)
+ if ((nested_p + not_nested_p + nested_ready_p + critical_p) > 1)
error ("multiple nested types attributes to function %qD", func_decl);
/* We must check at MOST one attribute to
@@ -362,6 +640,17 @@ nds32_check_isr_attrs_conflict (tree func_decl, tree func_attrs)
if ((intr_p + excp_p + reset_p) > 1)
error ("multiple interrupt attributes to function %qD", func_decl);
+
+ /* Do not allow isr attributes under linux toolchain. */
+ if (TARGET_LINUX_ABI && intr_p)
+ error ("cannot use interrupt attributes to function %qD "
+ "under linux toolchain", func_decl);
+ if (TARGET_LINUX_ABI && excp_p)
+ error ("cannot use exception attributes to function %qD "
+ "under linux toolchain", func_decl);
+ if (TARGET_LINUX_ABI && reset_p)
+ error ("cannot use reset attributes to function %qD "
+ "under linux toolchain", func_decl);
}
/* Function to construct isr vectors information array.
@@ -373,15 +662,21 @@ nds32_construct_isr_vectors_information (tree func_attrs,
const char *func_name)
{
tree save_all, partial_save;
- tree nested, not_nested, nested_ready;
+ tree nested, not_nested, nested_ready, critical;
tree intr, excp, reset;
+ tree secure;
+ tree security_level_list;
+ tree security_level;
+ unsigned int s_level;
+
save_all = lookup_attribute ("save_all", func_attrs);
partial_save = lookup_attribute ("partial_save", func_attrs);
nested = lookup_attribute ("nested", func_attrs);
not_nested = lookup_attribute ("not_nested", func_attrs);
nested_ready = lookup_attribute ("nested_ready", func_attrs);
+ critical = lookup_attribute ("critical", func_attrs);
intr = lookup_attribute ("interrupt", func_attrs);
excp = lookup_attribute ("exception", func_attrs);
@@ -391,6 +686,63 @@ nds32_construct_isr_vectors_information (tree func_attrs,
if (!intr && !excp && !reset)
return;
+ /* At first, we need to retrieve security level. */
+ secure = lookup_attribute ("secure", func_attrs);
+ if (secure != NULL)
+ {
+ security_level_list = TREE_VALUE (secure);
+ security_level = TREE_VALUE (security_level_list);
+ s_level = TREE_INT_CST_LOW (security_level);
+ }
+ else
+ {
+ /* If there is no secure attribute, the security level is set by
+ nds32_isr_secure_level, which is controlled by -misr-secure=X option.
+ By default nds32_isr_secure_level should be 0. */
+ s_level = nds32_isr_secure_level;
+ }
+
+ /* ------------------------------------------------------------- */
+ /* FIXME:
+ FOR BACKWARD COMPATIBILITY, we need to support following patterns:
+
+ __attribute__((interrupt("XXX;YYY;id=ZZZ")))
+ __attribute__((exception("XXX;YYY;id=ZZZ")))
+ __attribute__((reset("vectors=XXX;nmi_func=YYY;warm_func=ZZZ")))
+
+ If interrupt/exception/reset appears and its argument is a
+ STRING_CST, we will parse string with some auxiliary functions
+ which set necessary isr information in the nds32_isr_vectors[] array.
+ After that, we can return immediately to avoid new-syntax isr
+ information construction. */
+ if (intr != NULL_TREE
+ && TREE_CODE (TREE_VALUE (TREE_VALUE (intr))) == STRING_CST)
+ {
+ tree string_arg = TREE_VALUE (TREE_VALUE (intr));
+ nds32_interrupt_attribute_parse_string (TREE_STRING_POINTER (string_arg),
+ func_name,
+ s_level);
+ return;
+ }
+ if (excp != NULL_TREE
+ && TREE_CODE (TREE_VALUE (TREE_VALUE (excp))) == STRING_CST)
+ {
+ tree string_arg = TREE_VALUE (TREE_VALUE (excp));
+ nds32_exception_attribute_parse_string (TREE_STRING_POINTER (string_arg),
+ func_name,
+ s_level);
+ return;
+ }
+ if (reset != NULL_TREE
+ && TREE_CODE (TREE_VALUE (TREE_VALUE (reset))) == STRING_CST)
+ {
+ tree string_arg = TREE_VALUE (TREE_VALUE (reset));
+ nds32_reset_attribute_parse_string (TREE_STRING_POINTER (string_arg),
+ func_name);
+ return;
+ }
+ /* ------------------------------------------------------------- */
+
/* If we are here, either we have interrupt/exception,
or reset attribute. */
if (intr || excp)
@@ -417,6 +769,9 @@ nds32_construct_isr_vectors_information (tree func_attrs,
/* Add vector_number_offset to get actual vector number. */
vector_id = TREE_INT_CST_LOW (id) + vector_number_offset;
+ /* Set security level. */
+ nds32_isr_vectors[vector_id].security_level = s_level;
+
/* Enable corresponding vector and set function name. */
nds32_isr_vectors[vector_id].category = (intr)
? (NDS32_ISR_INTERRUPT)
@@ -436,6 +791,8 @@ nds32_construct_isr_vectors_information (tree func_attrs,
nds32_isr_vectors[vector_id].nested_type = NDS32_NOT_NESTED;
else if (nested_ready)
nds32_isr_vectors[vector_id].nested_type = NDS32_NESTED_READY;
+ else if (critical)
+ nds32_isr_vectors[vector_id].nested_type = NDS32_CRITICAL;
/* Advance to next id. */
id_list = TREE_CHAIN (id_list);
@@ -492,7 +849,6 @@ nds32_construct_isr_vectors_information (tree func_attrs,
}
}
-/* A helper function to handle isr stuff at the beginning of asm file. */
void
nds32_asm_file_start_for_isr (void)
{
@@ -505,15 +861,14 @@ nds32_asm_file_start_for_isr (void)
strcpy (nds32_isr_vectors[i].func_name, "");
nds32_isr_vectors[i].save_reg = NDS32_PARTIAL_SAVE;
nds32_isr_vectors[i].nested_type = NDS32_NOT_NESTED;
+ nds32_isr_vectors[i].security_level = 0;
nds32_isr_vectors[i].total_n_vectors = 0;
strcpy (nds32_isr_vectors[i].nmi_name, "");
strcpy (nds32_isr_vectors[i].warm_name, "");
}
}
-/* A helper function to handle isr stuff at the end of asm file. */
-void
-nds32_asm_file_end_for_isr (void)
+void nds32_asm_file_end_for_isr (void)
{
int i;
@@ -547,6 +902,8 @@ nds32_asm_file_end_for_isr (void)
/* Found one vector which is interupt or exception.
Output its jmptbl and vector section content. */
fprintf (asm_out_file, "\t! interrupt/exception vector %02d\n", i);
+ fprintf (asm_out_file, "\t! security level: %d\n",
+ nds32_isr_vectors[i].security_level);
fprintf (asm_out_file, "\t! ------------------------------------\n");
nds32_emit_isr_jmptbl_section (i);
fprintf (asm_out_file, "\t! ....................................\n");
@@ -580,4 +937,65 @@ nds32_isr_function_p (tree func)
|| (t_reset != NULL_TREE));
}
-/* ------------------------------------------------------------------------ */
+/* Return true if FUNC is a isr function with critical attribute. */
+bool
+nds32_isr_function_critical_p (tree func)
+{
+ tree t_intr;
+ tree t_excp;
+ tree t_critical;
+
+ tree attrs;
+
+ if (TREE_CODE (func) != FUNCTION_DECL)
+ abort ();
+
+ attrs = DECL_ATTRIBUTES (func);
+
+ t_intr = lookup_attribute ("interrupt", attrs);
+ t_excp = lookup_attribute ("exception", attrs);
+
+ t_critical = lookup_attribute ("critical", attrs);
+
+ /* If both interrupt and exception attribute does not appear,
+ we can return false immediately. */
+ if ((t_intr == NULL_TREE) && (t_excp == NULL_TREE))
+ return false;
+
+ /* Here we can guarantee either interrupt or ecxception attribute
+ does exist, so further check critical attribute.
+ If it also appears, we can return true. */
+ if (t_critical != NULL_TREE)
+ return true;
+
+ /* ------------------------------------------------------------- */
+ /* FIXME:
+ FOR BACKWARD COMPATIBILITY, we need to handle string type.
+ If the string 'critical' appears in the interrupt/exception
+ string argument, we can return true. */
+ if (t_intr != NULL_TREE || t_excp != NULL_TREE)
+ {
+ char target_str[100];
+ char *critical_str;
+ tree t_check;
+ tree string_arg;
+
+ t_check = t_intr ? t_intr : t_excp;
+ if (TREE_CODE (TREE_VALUE (TREE_VALUE (t_check))) == STRING_CST)
+ {
+ string_arg = TREE_VALUE (TREE_VALUE (t_check));
+ strcpy (target_str, TREE_STRING_POINTER (string_arg));
+ critical_str = strstr (target_str, "critical");
+
+ /* Found 'critical' string, so return true. */
+ if (critical_str)
+ return true;
+ }
+ }
+ /* ------------------------------------------------------------- */
+
+ /* Other cases, this isr function is not critical type. */
+ return false;
+}
+
+/* ------------------------------------------------------------- */
diff --git a/gcc/config/nds32/nds32-predicates.c b/gcc/config/nds32/nds32-predicates.c
index ba77700..b41b6c7 100644
--- a/gcc/config/nds32/nds32-predicates.c
+++ b/gcc/config/nds32/nds32-predicates.c
@@ -356,8 +356,8 @@ nds32_valid_stack_push_pop_p (rtx op, bool push_p)
}
/* Function to check if 'bclr' instruction can be used with IVAL. */
-int
-nds32_can_use_bclr_p (int ival)
+bool
+nds32_can_use_bclr_p (HOST_WIDE_INT ival)
{
int one_bit_count;
unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode);
@@ -373,8 +373,8 @@ nds32_can_use_bclr_p (int ival)
}
/* Function to check if 'bset' instruction can be used with IVAL. */
-int
-nds32_can_use_bset_p (int ival)
+bool
+nds32_can_use_bset_p (HOST_WIDE_INT ival)
{
int one_bit_count;
unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode);
@@ -389,8 +389,8 @@ nds32_can_use_bset_p (int ival)
}
/* Function to check if 'btgl' instruction can be used with IVAL. */
-int
-nds32_can_use_btgl_p (int ival)
+bool
+nds32_can_use_btgl_p (HOST_WIDE_INT ival)
{
int one_bit_count;
unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode);
@@ -405,8 +405,8 @@ nds32_can_use_btgl_p (int ival)
}
/* Function to check if 'bitci' instruction can be used with IVAL. */
-int
-nds32_can_use_bitci_p (int ival)
+bool
+nds32_can_use_bitci_p (HOST_WIDE_INT ival)
{
/* If we are using V3 ISA, we have 'bitci' instruction.
Try to see if we can present 'andi' semantic with
diff --git a/gcc/config/nds32/nds32-protos.h b/gcc/config/nds32/nds32-protos.h
index 3fa8ae1..7fb2315 100644
--- a/gcc/config/nds32/nds32-protos.h
+++ b/gcc/config/nds32/nds32-protos.h
@@ -138,11 +138,11 @@ extern bool nds32_valid_stack_push_pop_p (rtx, bool);
/* Auxiliary functions for bit operation detection. */
-extern int nds32_can_use_bclr_p (int);
-extern int nds32_can_use_bset_p (int);
-extern int nds32_can_use_btgl_p (int);
+extern bool nds32_can_use_bclr_p (HOST_WIDE_INT);
+extern bool nds32_can_use_bset_p (HOST_WIDE_INT);
+extern bool nds32_can_use_btgl_p (HOST_WIDE_INT);
-extern int nds32_can_use_bitci_p (int);
+extern bool nds32_can_use_bitci_p (HOST_WIDE_INT);
extern bool nds32_const_double_range_ok_p (rtx, machine_mode,
HOST_WIDE_INT, HOST_WIDE_INT);
@@ -307,6 +307,7 @@ extern void nds32_construct_isr_vectors_information (tree, const char *);
extern void nds32_asm_file_start_for_isr (void);
extern void nds32_asm_file_end_for_isr (void);
extern bool nds32_isr_function_p (tree);
+extern bool nds32_isr_function_critical_p (tree);
/* Auxiliary functions for cost calculation. */
diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c
index 85a2986..1ae34fc 100644
--- a/gcc/config/nds32/nds32.c
+++ b/gcc/config/nds32/nds32.c
@@ -305,6 +305,7 @@ static const struct attribute_spec nds32_attribute_table[] =
{ "nested", 0, 0, false, false, false, false, NULL, NULL },
{ "not_nested", 0, 0, false, false, false, false, NULL, NULL },
{ "nested_ready", 0, 0, false, false, false, false, NULL, NULL },
+ { "critical", 0, 0, false, false, false, false, NULL, NULL },
/* The attributes describing isr register save scheme. */
{ "save_all", 0, 0, false, false, false, false, NULL, NULL },
@@ -314,6 +315,9 @@ static const struct attribute_spec nds32_attribute_table[] =
{ "nmi", 1, 1, false, false, false, false, NULL, NULL },
{ "warm", 1, 1, false, false, false, false, NULL, NULL },
+ /* The attributes describing isr security level. */
+ { "secure", 1, 1, false, false, false, false, NULL, NULL },
+
/* The attribute telling no prologue/epilogue. */
{ "naked", 0, 0, false, false, false, false, NULL, NULL },
@@ -518,7 +522,7 @@ nds32_compute_stack_frame (void)
}
/* Check if this function can omit prologue/epilogue code fragment.
- If there is 'no_prologue'/'naked' attribute in this function,
+ If there is 'no_prologue'/'naked'/'secure' attribute in this function,
we can set 'naked_p' flag to indicate that
we do not have to generate prologue/epilogue.
Or, if all the following conditions succeed,
@@ -533,6 +537,7 @@ nds32_compute_stack_frame (void)
we do not need to adjust $sp. */
if (lookup_attribute ("no_prologue", DECL_ATTRIBUTES (current_function_decl))
|| lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl))
+ || lookup_attribute ("secure", DECL_ATTRIBUTES (current_function_decl))
|| (cfun->machine->callee_saved_first_gpr_regno == SP_REGNUM
&& cfun->machine->callee_saved_last_gpr_regno == SP_REGNUM
&& cfun->machine->callee_saved_first_fpr_regno == SP_REGNUM
@@ -2307,14 +2312,17 @@ nds32_function_ok_for_sibcall (tree decl,
/* 1. Do not apply sibling call if -mv3push is enabled,
because pop25 instruction also represents return behavior.
- 2. If this function is a variadic function, do not apply sibling call
+ 2. If this function is a isr function, do not apply sibling call
+ because it may perform the behavior that user does not expect.
+ 3. If this function is a variadic function, do not apply sibling call
because the stack layout may be a mess.
- 3. We don't want to apply sibling call optimization for indirect
+ 4. We don't want to apply sibling call optimization for indirect
sibcall because the pop behavior in epilogue may pollute the
content of caller-saved regsiter when the register is used for
indirect sibcall.
- 4. In pic mode, it may use some registers for PLT call. */
+ 5. In pic mode, it may use some registers for PLT call. */
return (!TARGET_V3PUSH
+ && !nds32_isr_function_p (current_function_decl)
&& (cfun->machine->va_args_size == 0)
&& decl
&& !flag_pic);
@@ -3968,6 +3976,38 @@ nds32_insert_attributes (tree decl, tree *attributes)
excp = lookup_attribute ("exception", func_attrs);
reset = lookup_attribute ("reset", func_attrs);
+ /* The following code may use attribute arguments. If there is no
+ argument from source code, it will cause segmentation fault.
+ Therefore, return dircetly and report error message later. */
+ if ((intr && TREE_VALUE (intr) == NULL)
+ || (excp && TREE_VALUE (excp) == NULL)
+ || (reset && TREE_VALUE (reset) == NULL))
+ return;
+
+ /* ------------------------------------------------------------- */
+ /* FIXME:
+ FOR BACKWARD COMPATIBILITY, we need to support following patterns:
+
+ __attribute__((interrupt("XXX;YYY;id=ZZZ")))
+ __attribute__((exception("XXX;YYY;id=ZZZ")))
+ __attribute__((reset("vectors=XXX;nmi_func=YYY;warm_func=ZZZ")))
+
+ If interrupt/exception/reset appears and its argument is a
+ STRING_CST, we will use other functions to parse string in the
+ nds32_construct_isr_vectors_information() and then set necessary
+ isr information in the nds32_isr_vectors[] array. Here we can
+ just return immediately to avoid new-syntax checking. */
+ if (intr != NULL_TREE
+ && TREE_CODE (TREE_VALUE (TREE_VALUE (intr))) == STRING_CST)
+ return;
+ if (excp != NULL_TREE
+ && TREE_CODE (TREE_VALUE (TREE_VALUE (excp))) == STRING_CST)
+ return;
+ if (reset != NULL_TREE
+ && TREE_CODE (TREE_VALUE (TREE_VALUE (reset))) == STRING_CST)
+ return;
+ /* ------------------------------------------------------------- */
+
if (intr || excp)
{
/* Deal with interrupt/exception. */
@@ -4211,6 +4251,16 @@ nds32_cpu_cpp_builtins(struct cpp_reader *pfile)
builtin_define ("__nds32__");
builtin_define ("__NDS32__");
+ /* We need to provide builtin macro to describe the size of
+ each vector for interrupt handler under elf toolchain. */
+ if (!TARGET_LINUX_ABI)
+ {
+ if (TARGET_ISR_VECTOR_SIZE_4_BYTE)
+ builtin_define ("__NDS32_ISR_VECTOR_SIZE_4__");
+ else
+ builtin_define ("__NDS32_ISR_VECTOR_SIZE_16__");
+ }
+
if (TARGET_HARD_FLOAT)
builtin_define ("__NDS32_ABI_2FP_PLUS__");
else
@@ -4342,7 +4392,7 @@ nds32_hard_regno_nregs (unsigned regno ATTRIBUTE_UNUSED,
static bool
nds32_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
{
- if (regno > FIRST_PSEUDO_REGISTER)
+ if (regno >= FIRST_PSEUDO_REGISTER)
return true;
if ((TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE) && NDS32_IS_FPR_REGNUM (regno))
@@ -4713,9 +4763,11 @@ nds32_expand_prologue (void)
if (flag_pic && df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM))
nds32_emit_load_gp ();
- /* Prevent the instruction scheduler from
- moving instructions across the boundary. */
- emit_insn (gen_blockage ());
+ /* If user applies -mno-sched-prolog-epilog option,
+ we need to prevent instructions of function body from being
+ scheduled with stack adjustment in prologue. */
+ if (!flag_sched_prolog_epilog)
+ emit_insn (gen_blockage ());
}
/* Function for normal multiple pop epilogue. */
@@ -4729,9 +4781,11 @@ nds32_expand_epilogue (bool sibcall_p)
The result will be in cfun->machine. */
nds32_compute_stack_frame ();
- /* Prevent the instruction scheduler from
- moving instructions across the boundary. */
- emit_insn (gen_blockage ());
+ /* If user applies -mno-sched-prolog-epilog option,
+ we need to prevent instructions of function body from being
+ scheduled with stack adjustment in epilogue. */
+ if (!flag_sched_prolog_epilog)
+ emit_insn (gen_blockage ());
/* If the function is 'naked', we do not have to generate
epilogue code fragment BUT 'ret' instruction.
@@ -5823,6 +5877,9 @@ nds32_use_blocks_for_constant_p (machine_mode mode,
#undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
#define TARGET_USE_BLOCKS_FOR_CONSTANT_P nds32_use_blocks_for_constant_p
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
/* ------------------------------------------------------------------------ */
diff --git a/gcc/config/nds32/nds32.h b/gcc/config/nds32/nds32.h
index 3aac6a2..cec15be 100644
--- a/gcc/config/nds32/nds32.h
+++ b/gcc/config/nds32/nds32.h
@@ -367,7 +367,8 @@ enum nds32_isr_nested_type
{
NDS32_NESTED,
NDS32_NOT_NESTED,
- NDS32_NESTED_READY
+ NDS32_NESTED_READY,
+ NDS32_CRITICAL
};
/* Define structure to record isr information.
@@ -395,6 +396,13 @@ struct nds32_isr_info
unless user specifies attribute to change it. */
enum nds32_isr_nested_type nested_type;
+ /* Secure isr level.
+ Currently we have 0-3 security level.
+ It should be set to 0 by default.
+ For security processors, this is determined by secure
+ attribute or compiler options. */
+ unsigned int security_level;
+
/* Total vectors.
The total vectors = interrupt + exception numbers + reset.
It should be set to 0 by default.
@@ -849,8 +857,10 @@ enum nds32_builtins
/* ------------------------------------------------------------------------ */
-#define TARGET_ISA_V2 (nds32_arch_option == ARCH_V2)
+#define TARGET_ISR_VECTOR_SIZE_4_BYTE \
+ (nds32_isr_vector_size == 4)
+#define TARGET_ISA_V2 (nds32_arch_option == ARCH_V2)
#define TARGET_ISA_V3 \
(nds32_arch_option == ARCH_V3 \
|| nds32_arch_option == ARCH_V3J \
diff --git a/gcc/config/nds32/nds32.md b/gcc/config/nds32/nds32.md
index 92e90dd..f5349d7 100644
--- a/gcc/config/nds32/nds32.md
+++ b/gcc/config/nds32/nds32.md
@@ -1993,6 +1993,9 @@
[(simple_return)]
""
{
+ if (nds32_isr_function_critical_p (current_function_decl))
+ return "iret";
+
if (TARGET_16_BIT)
return "ret5";
else
@@ -2001,9 +2004,11 @@
[(set_attr "type" "branch")
(set_attr "enabled" "yes")
(set (attr "length")
- (if_then_else (match_test "TARGET_16_BIT")
- (const_int 2)
- (const_int 4)))])
+ (if_then_else (match_test "nds32_isr_function_critical_p (current_function_decl)")
+ (const_int 4)
+ (if_then_else (match_test "TARGET_16_BIT")
+ (const_int 2)
+ (const_int 4))))])
;; ----------------------------------------------------------------------------
diff --git a/gcc/config/nds32/nds32.opt b/gcc/config/nds32/nds32.opt
index a9ffae1..0e50c99 100644
--- a/gcc/config/nds32/nds32.opt
+++ b/gcc/config/nds32/nds32.opt
@@ -158,6 +158,10 @@ misr-vector-size=
Target RejectNegative Joined UInteger Var(nds32_isr_vector_size) Init(NDS32_DEFAULT_ISR_VECTOR_SIZE)
Specify the size of each interrupt vector, which must be 4 or 16.
+misr-secure=
+Target RejectNegative Joined UInteger Var(nds32_isr_secure_level) Init(0)
+Specify the security level of c-isr for the whole file.
+
mcache-block-size=
Target RejectNegative Joined UInteger Var(nds32_cache_block_size) Init(NDS32_DEFAULT_CACHE_BLOCK_SIZE)
Specify the size of each cache block, which must be a power of 2 between 4 and 512.
@@ -440,6 +444,10 @@ mforce-no-ext-dsp
Target Undocumented Report Mask(FORCE_NO_EXT_DSP)
Force disable hardware loop, even use -mext-dsp.
+msched-prolog-epilog
+Target Var(flag_sched_prolog_epilog) Init(0)
+Permit scheduling of a function's prologue and epilogue sequence.
+
mret-in-naked-func
Target Var(flag_ret_in_naked_func) Init(1)
Generate return instruction in naked function.
diff --git a/gcc/config/nds32/nds32_init.inc b/gcc/config/nds32/nds32_init.inc
new file mode 100644
index 0000000..1084ad0
--- /dev/null
+++ b/gcc/config/nds32/nds32_init.inc
@@ -0,0 +1,43 @@
+/*
+ * nds32_init.inc
+ *
+ * NDS32 architecture startup assembler header file
+ *
+ */
+
+.macro nds32_init
+
+ ! Initialize GP for data access
+ la $gp, _SDA_BASE_
+
+#if defined(__NDS32_EXT_EX9__)
+ ! Check HW for EX9
+ mfsr $r0, $MSC_CFG
+ li $r1, (1 << 24)
+ and $r2, $r0, $r1
+ beqz $r2, 1f
+
+ ! Initialize the table base of EX9 instruction
+ la $r0, _ITB_BASE_
+ mtusr $r0, $ITB
+1:
+#endif
+
+#if defined(__NDS32_EXT_FPU_DP__) || defined(__NDS32_EXT_FPU_SP__)
+ ! Enable FPU
+ mfsr $r0, $FUCOP_CTL
+ ori $r0, $r0, #0x1
+ mtsr $r0, $FUCOP_CTL
+ dsb
+
+ ! Enable denormalized flush-to-Zero mode
+ fmfcsr $r0
+ ori $r0,$r0,#0x1000
+ fmtcsr $r0
+ dsb
+#endif
+
+ ! Initialize default stack pointer
+ la $sp, _stack
+
+.endm
diff --git a/gcc/config/nds32/nds32_isr.h b/gcc/config/nds32/nds32_isr.h
new file mode 100644
index 0000000..8ea58f9
--- /dev/null
+++ b/gcc/config/nds32/nds32_isr.h
@@ -0,0 +1,526 @@
+/* Intrinsic definitions of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2018 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ 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/>. */
+
+#ifndef _NDS32_ISR_H
+#define _NDS32_ISR_H
+
+/* Attribute of a interrupt or exception handler:
+
+ NDS32_READY_NESTED: This handler is interruptible if user re-enable GIE bit.
+ NDS32_NESTED : This handler is interruptible. This is not suitable
+ exception handler.
+ NDS32_NOT_NESTED : This handler is NOT interruptible. Users have to do
+ some work if nested is wanted
+ NDS32_CRITICAL : This handler is critical ISR, which means it is small
+ and efficient. */
+#define NDS32_READY_NESTED 0
+#define NDS32_NESTED 1
+#define NDS32_NOT_NESTED 2
+#define NDS32_CRITICAL 3
+
+/* Attribute of a interrupt or exception handler:
+
+ NDS32_SAVE_ALL_REGS : Save all registers in a table.
+ NDS32_SAVE_PARTIAL_REGS: Save partial registers. */
+#define NDS32_SAVE_CALLER_REGS 0
+#define NDS32_SAVE_ALL_REGS 1
+
+/* There are two version of Register table for interrupt and exception handler,
+ one for 16-register CPU the other for 32-register CPU. These structures are
+ used for context switching or system call handling. The address of this
+ data can be get from the input argument of the handler functions.
+
+ For system call handling, r0 to r5 are used to pass arguments. If more
+ arguments are used they are put into the stack and its starting address is
+ in sp. Return value of system call can be put into r0 and r1 upon exit from
+ system call handler. System call ID is in a system register and it can be
+ fetched via intrinsic function. For more information please read ABI and
+ other related documents.
+
+ For context switching, at least 2 values need to saved in kernel. One is
+ IPC and the other is the stack address of current task. Use intrinsic
+ function to get IPC and the input argument of the handler functions + 8 to
+ get stack address of current task. To do context switching, you replace
+ new_sp with the stack address of new task and replace IPC system register
+ with IPC of new task, then, just return from handler. The context switching
+ will happen. */
+
+/* Register table for exception handler; 32-register version. */
+typedef struct
+{
+ int r0;
+ int r1;
+ int r2;
+ int r3;
+ int r4;
+ int r5;
+ int r6;
+ int r7;
+ int r8;
+ int r9;
+ int r10;
+ int r11;
+ int r12;
+ int r13;
+ int r14;
+ int r15;
+ int r16;
+ int r17;
+ int r18;
+ int r19;
+ int r20;
+ int r21;
+ int r22;
+ int r23;
+ int r24;
+ int r25;
+ int r26;
+ int r27;
+ int fp;
+ int gp;
+ int lp;
+ int sp;
+} NDS32_GPR32;
+
+/* Register table for exception handler; 16-register version. */
+typedef struct
+{
+ int r0;
+ int r1;
+ int r2;
+ int r3;
+ int r4;
+ int r5;
+ int r6;
+ int r7;
+ int r8;
+ int r9;
+ int r10;
+ int r15;
+ int fp;
+ int gp;
+ int lp;
+ int sp;
+} NDS32_GPR16;
+
+
+/* Use NDS32_REG32_TAB or NDS32_REG16_TAB in your program to
+ access register table. */
+typedef struct
+{
+ union
+ {
+ int reg_a[32] ;
+ NDS32_GPR32 reg_s ;
+ } u ;
+} NDS32_REG32_TAB;
+
+typedef struct
+{
+ union
+ {
+ int reg_a[16] ;
+ NDS32_GPR16 reg_s ;
+ } u ;
+} NDS32_REG16_TAB;
+
+typedef struct
+{
+ int d0lo;
+ int d0hi;
+ int d1lo;
+ int d1hi;
+} NDS32_DX_TAB;
+
+typedef struct
+{
+#ifdef __NDS32_EB__
+ float fsr0;
+ float fsr1;
+ float fsr2;
+ float fsr3;
+ float fsr4;
+ float fsr5;
+ float fsr6;
+ float fsr7;
+#else
+ float fsr1;
+ float fsr0;
+ float fsr3;
+ float fsr2;
+ float fsr5;
+ float fsr4;
+ float fsr7;
+ float fsr6;
+#endif
+} NDS32_FSR8;
+
+typedef struct
+{
+ double dsr0;
+ double dsr1;
+ double dsr2;
+ double dsr3;
+} NDS32_DSR4;
+
+typedef struct
+{
+#ifdef __NDS32_EB__
+ float fsr0;
+ float fsr1;
+ float fsr2;
+ float fsr3;
+ float fsr4;
+ float fsr5;
+ float fsr6;
+ float fsr7;
+ float fsr8;
+ float fsr9;
+ float fsr10;
+ float fsr11;
+ float fsr12;
+ float fsr13;
+ float fsr14;
+ float fsr15;
+#else
+ float fsr1;
+ float fsr0;
+ float fsr3;
+ float fsr2;
+ float fsr5;
+ float fsr4;
+ float fsr7;
+ float fsr6;
+ float fsr9;
+ float fsr8;
+ float fsr11;
+ float fsr10;
+ float fsr13;
+ float fsr12;
+ float fsr15;
+ float fsr14;
+#endif
+} NDS32_FSR16;
+
+typedef struct
+{
+ double dsr0;
+ double dsr1;
+ double dsr2;
+ double dsr3;
+ double dsr4;
+ double dsr5;
+ double dsr6;
+ double dsr7;
+} NDS32_DSR8;
+
+typedef struct
+{
+#ifdef __NDS32_EB__
+ float fsr0;
+ float fsr1;
+ float fsr2;
+ float fsr3;
+ float fsr4;
+ float fsr5;
+ float fsr6;
+ float fsr7;
+ float fsr8;
+ float fsr9;
+ float fsr10;
+ float fsr11;
+ float fsr12;
+ float fsr13;
+ float fsr14;
+ float fsr15;
+ float fsr16;
+ float fsr17;
+ float fsr18;
+ float fsr19;
+ float fsr20;
+ float fsr21;
+ float fsr22;
+ float fsr23;
+ float fsr24;
+ float fsr25;
+ float fsr26;
+ float fsr27;
+ float fsr28;
+ float fsr29;
+ float fsr30;
+ float fsr31;
+#else
+ float fsr1;
+ float fsr0;
+ float fsr3;
+ float fsr2;
+ float fsr5;
+ float fsr4;
+ float fsr7;
+ float fsr6;
+ float fsr9;
+ float fsr8;
+ float fsr11;
+ float fsr10;
+ float fsr13;
+ float fsr12;
+ float fsr15;
+ float fsr14;
+ float fsr17;
+ float fsr16;
+ float fsr19;
+ float fsr18;
+ float fsr21;
+ float fsr20;
+ float fsr23;
+ float fsr22;
+ float fsr25;
+ float fsr24;
+ float fsr27;
+ float fsr26;
+ float fsr29;
+ float fsr28;
+ float fsr31;
+ float fsr30;
+#endif
+} NDS32_FSR32;
+
+typedef struct
+{
+ double dsr0;
+ double dsr1;
+ double dsr2;
+ double dsr3;
+ double dsr4;
+ double dsr5;
+ double dsr6;
+ double dsr7;
+ double dsr8;
+ double dsr9;
+ double dsr10;
+ double dsr11;
+ double dsr12;
+ double dsr13;
+ double dsr14;
+ double dsr15;
+} NDS32_DSR16;
+
+typedef struct
+{
+ double dsr0;
+ double dsr1;
+ double dsr2;
+ double dsr3;
+ double dsr4;
+ double dsr5;
+ double dsr6;
+ double dsr7;
+ double dsr8;
+ double dsr9;
+ double dsr10;
+ double dsr11;
+ double dsr12;
+ double dsr13;
+ double dsr14;
+ double dsr15;
+ double dsr16;
+ double dsr17;
+ double dsr18;
+ double dsr19;
+ double dsr20;
+ double dsr21;
+ double dsr22;
+ double dsr23;
+ double dsr24;
+ double dsr25;
+ double dsr26;
+ double dsr27;
+ double dsr28;
+ double dsr29;
+ double dsr30;
+ double dsr31;
+} NDS32_DSR32;
+
+typedef struct
+{
+ union
+ {
+ NDS32_FSR8 fsr_s ;
+ NDS32_DSR4 dsr_s ;
+ } u ;
+} NDS32_FPU8_TAB;
+
+typedef struct
+{
+ union
+ {
+ NDS32_FSR16 fsr_s ;
+ NDS32_DSR8 dsr_s ;
+ } u ;
+} NDS32_FPU16_TAB;
+
+typedef struct
+{
+ union
+ {
+ NDS32_FSR32 fsr_s ;
+ NDS32_DSR16 dsr_s ;
+ } u ;
+} NDS32_FPU32_TAB;
+
+typedef struct
+{
+ union
+ {
+ NDS32_FSR32 fsr_s ;
+ NDS32_DSR32 dsr_s ;
+ } u ;
+} NDS32_FPU64_TAB;
+
+typedef struct
+{
+ int ipc;
+ int ipsw;
+#if defined(NDS32_EXT_FPU_CONFIG_0)
+ NDS32_FPU8_TAB fpr;
+#elif defined(NDS32_EXT_FPU_CONFIG_1)
+ NDS32_FPU16_TAB fpr;
+#elif defined(NDS32_EXT_FPU_CONFIG_2)
+ NDS32_FPU32_TAB fpr;
+#elif defined(NDS32_EXT_FPU_CONFIG_3)
+ NDS32_FPU64_TAB fpr;
+#endif
+#if __NDS32_DX_REGS__
+ NDS32_DX_TAB dxr;
+#endif
+#if __NDS32_EXT_IFC__
+ int ifc_lp;
+ int filler;
+#endif
+#if __NDS32_REDUCED_REGS__ || __NDS32_REDUCE_REGS
+ NDS32_REG16_TAB gpr;
+#else
+ NDS32_REG32_TAB gpr;
+#endif
+} NDS32_CONTEXT;
+
+/* Predefined Vector Definition.
+
+ For IVIC Mode: 9 to 14 are for hardware interrupt
+ and 15 is for software interrupt.
+ For EVIC Mode: 9 to 72 are for hardware interrupt
+ and software interrupt can be routed to any one of them.
+
+ You may want to define your hardware interrupts in the following way
+ for easy maintainance.
+
+ IVIC mode:
+ #define MY_HW_IVIC_TIMER NDS32_VECTOR_INTERRUPT_HW0 + 1
+ #define MY_HW_IVIC_USB NDS32_VECTOR_INTERRUPT_HW0 + 3
+ EVIC mode:
+ #define MY_HW_EVIC_DMA NDS32_VECTOR_INTERRUPT_HW0 + 2
+ #define MY_HW_EVIC_SWI NDS32_VECTOR_INTERRUPT_HW0 + 10 */
+#define NDS32_VECTOR_RESET 0
+#define NDS32_VECTOR_TLB_FILL 1
+#define NDS32_VECTOR_PTE_NOT_PRESENT 2
+#define NDS32_VECTOR_TLB_MISC 3
+#define NDS32_VECTOR_TLB_VLPT_MISS 4
+#define NDS32_VECTOR_MACHINE_ERROR 5
+#define NDS32_VECTOR_DEBUG_RELATED 6
+#define NDS32_VECTOR_GENERAL_EXCEPTION 7
+#define NDS32_VECTOR_SYSCALL 8
+#define NDS32_VECTOR_INTERRUPT_HW0 9
+#define NDS32_VECTOR_INTERRUPT_HW1 10
+#define NDS32_VECTOR_INTERRUPT_HW2 11
+#define NDS32_VECTOR_INTERRUPT_HW3 12
+#define NDS32_VECTOR_INTERRUPT_HW4 13
+#define NDS32_VECTOR_INTERRUPT_HW5 14
+#define NDS32_VECTOR_INTERRUPT_HW6 15
+#define NDS32_VECTOR_SWI 15 /* THIS IS FOR IVIC MODE ONLY */
+#define NDS32_VECTOR_INTERRUPT_HW7 16
+#define NDS32_VECTOR_INTERRUPT_HW8 17
+#define NDS32_VECTOR_INTERRUPT_HW9 18
+#define NDS32_VECTOR_INTERRUPT_HW10 19
+#define NDS32_VECTOR_INTERRUPT_HW11 20
+#define NDS32_VECTOR_INTERRUPT_HW12 21
+#define NDS32_VECTOR_INTERRUPT_HW13 22
+#define NDS32_VECTOR_INTERRUPT_HW14 23
+#define NDS32_VECTOR_INTERRUPT_HW15 24
+#define NDS32_VECTOR_INTERRUPT_HW16 25
+#define NDS32_VECTOR_INTERRUPT_HW17 26
+#define NDS32_VECTOR_INTERRUPT_HW18 27
+#define NDS32_VECTOR_INTERRUPT_HW19 28
+#define NDS32_VECTOR_INTERRUPT_HW20 29
+#define NDS32_VECTOR_INTERRUPT_HW21 30
+#define NDS32_VECTOR_INTERRUPT_HW22 31
+#define NDS32_VECTOR_INTERRUPT_HW23 32
+#define NDS32_VECTOR_INTERRUPT_HW24 33
+#define NDS32_VECTOR_INTERRUPT_HW25 34
+#define NDS32_VECTOR_INTERRUPT_HW26 35
+#define NDS32_VECTOR_INTERRUPT_HW27 36
+#define NDS32_VECTOR_INTERRUPT_HW28 37
+#define NDS32_VECTOR_INTERRUPT_HW29 38
+#define NDS32_VECTOR_INTERRUPT_HW30 39
+#define NDS32_VECTOR_INTERRUPT_HW31 40
+#define NDS32_VECTOR_INTERRUPT_HW32 41
+#define NDS32_VECTOR_INTERRUPT_HW33 42
+#define NDS32_VECTOR_INTERRUPT_HW34 43
+#define NDS32_VECTOR_INTERRUPT_HW35 44
+#define NDS32_VECTOR_INTERRUPT_HW36 45
+#define NDS32_VECTOR_INTERRUPT_HW37 46
+#define NDS32_VECTOR_INTERRUPT_HW38 47
+#define NDS32_VECTOR_INTERRUPT_HW39 48
+#define NDS32_VECTOR_INTERRUPT_HW40 49
+#define NDS32_VECTOR_INTERRUPT_HW41 50
+#define NDS32_VECTOR_INTERRUPT_HW42 51
+#define NDS32_VECTOR_INTERRUPT_HW43 52
+#define NDS32_VECTOR_INTERRUPT_HW44 53
+#define NDS32_VECTOR_INTERRUPT_HW45 54
+#define NDS32_VECTOR_INTERRUPT_HW46 55
+#define NDS32_VECTOR_INTERRUPT_HW47 56
+#define NDS32_VECTOR_INTERRUPT_HW48 57
+#define NDS32_VECTOR_INTERRUPT_HW49 58
+#define NDS32_VECTOR_INTERRUPT_HW50 59
+#define NDS32_VECTOR_INTERRUPT_HW51 60
+#define NDS32_VECTOR_INTERRUPT_HW52 61
+#define NDS32_VECTOR_INTERRUPT_HW53 62
+#define NDS32_VECTOR_INTERRUPT_HW54 63
+#define NDS32_VECTOR_INTERRUPT_HW55 64
+#define NDS32_VECTOR_INTERRUPT_HW56 65
+#define NDS32_VECTOR_INTERRUPT_HW57 66
+#define NDS32_VECTOR_INTERRUPT_HW58 67
+#define NDS32_VECTOR_INTERRUPT_HW59 68
+#define NDS32_VECTOR_INTERRUPT_HW60 69
+#define NDS32_VECTOR_INTERRUPT_HW61 70
+#define NDS32_VECTOR_INTERRUPT_HW62 71
+#define NDS32_VECTOR_INTERRUPT_HW63 72
+
+#define NDS32ATTR_RESET(option) __attribute__((reset(option)))
+#define NDS32ATTR_EXCEPT(type) __attribute__((exception(type)))
+#define NDS32ATTR_EXCEPTION(type) __attribute__((exception(type)))
+#define NDS32ATTR_INTERRUPT(type) __attribute__((interrupt(type)))
+#define NDS32ATTR_ISR(type) __attribute__((interrupt(type)))
+
+#endif /* nds32_isr.h */
diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c
index 344181a..c57d6cd 100644
--- a/gcc/config/nios2/nios2.c
+++ b/gcc/config/nios2/nios2.c
@@ -5572,6 +5572,9 @@ nios2_adjust_reg_alloc_order (void)
#undef TARGET_CONSTANT_ALIGNMENT
#define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-nios2.h"
diff --git a/gcc/config/nvptx/nvptx-opts.h b/gcc/config/nvptx/nvptx-opts.h
new file mode 100644
index 0000000..55d9599
--- /dev/null
+++ b/gcc/config/nvptx/nvptx-opts.h
@@ -0,0 +1,30 @@
+/* Definitions for the NVPTX port needed for option handling.
+ Copyright (C) 2015-2018 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 NVPTX_OPTS_H
+#define NVPTX_OPTS_H
+
+enum ptx_isa
+{
+ PTX_ISA_SM30,
+ PTX_ISA_SM35
+};
+
+#endif
+
diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c
index c1946e7..9903a27 100644
--- a/gcc/config/nvptx/nvptx.c
+++ b/gcc/config/nvptx/nvptx.c
@@ -4931,7 +4931,10 @@ nvptx_file_start (void)
{
fputs ("// BEGIN PREAMBLE\n", asm_out_file);
fputs ("\t.version\t3.1\n", asm_out_file);
- fputs ("\t.target\tsm_30\n", asm_out_file);
+ if (TARGET_SM35)
+ fputs ("\t.target\tsm_35\n", asm_out_file);
+ else
+ fputs ("\t.target\tsm_30\n", asm_out_file);
fprintf (asm_out_file, "\t.address_size %d\n", GET_MODE_BITSIZE (Pmode));
fputs ("// END PREAMBLE\n", asm_out_file);
}
@@ -6048,6 +6051,9 @@ nvptx_can_change_mode_class (machine_mode, machine_mode, reg_class_t)
#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS nvptx_can_change_mode_class
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-nvptx.h"
diff --git a/gcc/config/nvptx/nvptx.h b/gcc/config/nvptx/nvptx.h
index dfa1e9a..a2fe8b6 100644
--- a/gcc/config/nvptx/nvptx.h
+++ b/gcc/config/nvptx/nvptx.h
@@ -21,10 +21,16 @@
#ifndef GCC_NVPTX_H
#define GCC_NVPTX_H
+#ifndef NVPTX_OPTS_H
+#include "config/nvptx/nvptx-opts.h"
+#endif
+
/* Run-time Target. */
#define STARTFILE_SPEC "%{mmainkernel:crt0.o}"
+#define ASM_SPEC "%{misa=*:-m %*}"
+
#define TARGET_CPU_CPP_BUILTINS() \
do \
{ \
@@ -87,6 +93,8 @@
#define Pmode (TARGET_ABI64 ? DImode : SImode)
#define STACK_SIZE_MODE Pmode
+#define TARGET_SM35 (ptx_isa_option >= PTX_ISA_SM35)
+
/* Registers. Since ptx is a virtual target, we just define a few
hard registers for special purposes and leave pseudos unallocated.
We have to have some available hard registers, to keep gcc setup
diff --git a/gcc/config/nvptx/nvptx.md b/gcc/config/nvptx/nvptx.md
index 2988f5d..ca00b1d 100644
--- a/gcc/config/nvptx/nvptx.md
+++ b/gcc/config/nvptx/nvptx.md
@@ -1440,7 +1440,6 @@
(define_code_iterator any_logic [and ior xor])
(define_code_attr logic [(and "and") (ior "or") (xor "xor")])
-;; Currently disabled until we add better subtarget support - requires sm_32.
(define_insn "atomic_fetch_<logic><mode>"
[(set (match_operand:SDIM 1 "memory_operand" "+m")
(unspec_volatile:SDIM
@@ -1450,7 +1449,7 @@
UNSPECV_LOCK))
(set (match_operand:SDIM 0 "nvptx_register_operand" "=R")
(match_dup 1))]
- "0"
+ "<MODE>mode == SImode || TARGET_SM35"
"%.\\tatom%A1.b%T0.<logic>\\t%0, %1, %2;"
[(set_attr "atomic" "true")])
diff --git a/gcc/config/nvptx/nvptx.opt b/gcc/config/nvptx/nvptx.opt
index 04277d1..8194c03 100644
--- a/gcc/config/nvptx/nvptx.opt
+++ b/gcc/config/nvptx/nvptx.opt
@@ -48,3 +48,17 @@ Generate code that can keep local state uniform across all lanes.
mgomp
Target Report Mask(GOMP)
Generate code for OpenMP offloading: enables -msoft-stack and -muniform-simt.
+
+Enum
+Name(ptx_isa) Type(int)
+Known PTX ISA versions (for use with the -misa= option):
+
+EnumValue
+Enum(ptx_isa) String(sm_30) Value(PTX_ISA_SM30)
+
+EnumValue
+Enum(ptx_isa) String(sm_35) Value(PTX_ISA_SM35)
+
+misa=
+Target RejectNegative ToLower Joined Enum(ptx_isa) Var(ptx_isa_option) Init(PTX_ISA_SM30)
+Specify the version of the ptx ISA to use.
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 715700e..2bf48e4 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -122,7 +122,6 @@ static void pa_output_function_prologue (FILE *);
static void update_total_code_bytes (unsigned int);
static void pa_output_function_epilogue (FILE *);
static int pa_adjust_cost (rtx_insn *, int, rtx_insn *, int, unsigned int);
-static int pa_adjust_priority (rtx_insn *, int);
static int pa_issue_rate (void);
static int pa_reloc_rw_mask (void);
static void pa_som_asm_init_sections (void) ATTRIBUTE_UNUSED;
@@ -280,8 +279,6 @@ static size_t n_deferred_plabels = 0;
#undef TARGET_SCHED_ADJUST_COST
#define TARGET_SCHED_ADJUST_COST pa_adjust_cost
-#undef TARGET_SCHED_ADJUST_PRIORITY
-#define TARGET_SCHED_ADJUST_PRIORITY pa_adjust_priority
#undef TARGET_SCHED_ISSUE_RATE
#define TARGET_SCHED_ISSUE_RATE pa_issue_rate
@@ -428,6 +425,9 @@ static size_t n_deferred_plabels = 0;
#undef TARGET_STARTING_FRAME_OFFSET
#define TARGET_STARTING_FRAME_OFFSET pa_starting_frame_offset
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Parse the -mfixed-range= option string. */
@@ -4992,37 +4992,6 @@ pa_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost,
}
}
-/* Adjust scheduling priorities. We use this to try and keep addil
- and the next use of %r1 close together. */
-static int
-pa_adjust_priority (rtx_insn *insn, int priority)
-{
- rtx set = single_set (insn);
- rtx src, dest;
- if (set)
- {
- src = SET_SRC (set);
- dest = SET_DEST (set);
- if (GET_CODE (src) == LO_SUM
- && symbolic_operand (XEXP (src, 1), VOIDmode)
- && ! read_only_operand (XEXP (src, 1), VOIDmode))
- priority >>= 3;
-
- else if (GET_CODE (src) == MEM
- && GET_CODE (XEXP (src, 0)) == LO_SUM
- && symbolic_operand (XEXP (XEXP (src, 0), 1), VOIDmode)
- && ! read_only_operand (XEXP (XEXP (src, 0), 1), VOIDmode))
- priority >>= 1;
-
- else if (GET_CODE (dest) == MEM
- && GET_CODE (XEXP (dest, 0)) == LO_SUM
- && symbolic_operand (XEXP (XEXP (dest, 0), 1), VOIDmode)
- && ! read_only_operand (XEXP (XEXP (dest, 0), 1), VOIDmode))
- priority >>= 3;
- }
- return priority;
-}
-
/* The 700 can only issue a single insn at a time.
The 7XXX processors can issue two insns at a time.
The 8000 can issue 4 insns at a time. */
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index e748f05..7761150 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -84,6 +84,7 @@
UNSPEC_TLSGD_PIC
UNSPEC_TLSLDM_PIC
UNSPEC_TLSIE_PIC
+ UNSPEC_MEMORY_BARRIER
])
;; UNSPEC_VOLATILE:
@@ -9955,14 +9956,8 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
;; doubleword loads and stores are not guaranteed to be atomic
;; when referencing the I/O address space.
-;; The kernel cmpxchg operation on linux is not atomic with respect to
-;; memory stores on SMP machines, so we must do stores using a cmpxchg
-;; operation.
-
;; These patterns are at the bottom so the non atomic versions are preferred.
-;; Implement atomic QImode store using exchange.
-
(define_expand "atomic_storeqi"
[(match_operand:QI 0 "memory_operand") ;; memory
(match_operand:QI 1 "register_operand") ;; val out
@@ -10015,25 +10010,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
FAIL;
})
-;; Implement atomic SFmode store using exchange.
-
-(define_expand "atomic_storesf"
- [(match_operand:SF 0 "memory_operand") ;; memory
- (match_operand:SF 1 "register_operand") ;; val out
- (match_operand:SI 2 "const_int_operand")] ;; model
- ""
-{
- if (TARGET_SYNC_LIBCALL)
- {
- rtx mem = operands[0];
- rtx val = operands[1];
- if (pa_maybe_emit_compare_and_swap_exchange_loop (NULL_RTX, mem, val))
- DONE;
- }
- FAIL;
-})
-
-;; Implement atomic DImode load using 64-bit floating point load.
+;; Implement atomic DImode load.
(define_expand "atomic_loaddi"
[(match_operand:DI 0 "register_operand") ;; val out
@@ -10048,29 +10025,27 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
model = memmodel_from_int (INTVAL (operands[2]));
operands[1] = force_reg (SImode, XEXP (operands[1], 0));
- expand_mem_thread_fence (model);
- emit_insn (gen_atomic_loaddi_1 (operands[0], operands[1]));
if (is_mm_seq_cst (model))
expand_mem_thread_fence (model);
+ emit_insn (gen_atomic_loaddi_1 (operands[0], operands[1]));
+ expand_mem_thread_fence (model);
DONE;
})
(define_insn "atomic_loaddi_1"
- [(set (match_operand:DI 0 "register_operand" "=f,r")
- (mem:DI (match_operand:SI 1 "register_operand" "r,r")))
- (clobber (match_scratch:DI 2 "=X,f"))]
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (mem:DI (match_operand:SI 1 "register_operand" "r")))
+ (clobber (match_scratch:DI 2 "=f"))]
"!TARGET_64BIT && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT"
- "@
- {fldds|fldd} 0(%1),%0
- {fldds|fldd} 0(%1),%2\n\t{fstds|fstd} %2,-16(%%sp)\n\t{ldws|ldw} -16(%%sp),%0\n\t{ldws|ldw} -12(%%sp),%R0"
- [(set_attr "type" "move,move")
- (set_attr "length" "4,16")])
+ "{fldds|fldd} 0(%1),%2\n\t{fstds|fstd} %2,-16(%%sp)\n\t{ldws|ldw} -16(%%sp),%0\n\t{ldws|ldw} -12(%%sp),%R0"
+ [(set_attr "type" "move")
+ (set_attr "length" "16")])
;; Implement atomic DImode store.
(define_expand "atomic_storedi"
[(match_operand:DI 0 "memory_operand") ;; memory
- (match_operand:DI 1 "register_operand") ;; val out
+ (match_operand:DI 1 "reg_or_cint_move_operand") ;; val out
(match_operand:SI 2 "const_int_operand")] ;; model
""
{
@@ -10089,6 +10064,8 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
model = memmodel_from_int (INTVAL (operands[2]));
operands[0] = force_reg (SImode, XEXP (operands[0], 0));
+ if (operands[1] != CONST0_RTX (DImode))
+ operands[1] = force_reg (DImode, operands[1]);
expand_mem_thread_fence (model);
emit_insn (gen_atomic_storedi_1 (operands[0], operands[1]));
if (is_mm_seq_cst (model))
@@ -10098,87 +10075,33 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
(define_insn "atomic_storedi_1"
[(set (mem:DI (match_operand:SI 0 "register_operand" "r,r"))
- (match_operand:DI 1 "register_operand" "f,r"))
+ (match_operand:DI 1 "reg_or_0_operand" "M,r"))
(clobber (match_scratch:DI 2 "=X,f"))]
- "!TARGET_64BIT && !TARGET_DISABLE_FPREGS
- && !TARGET_SOFT_FLOAT && !TARGET_SYNC_LIBCALL"
+ "!TARGET_64BIT && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT"
"@
- {fstds|fstd} %1,0(%0)
+ {fstds|fstd} %%fr0,0(%0)
{stws|stw} %1,-16(%%sp)\n\t{stws|stw} %R1,-12(%%sp)\n\t{fldds|fldd} -16(%%sp),%2\n\t{fstds|fstd} %2,0(%0)"
[(set_attr "type" "move,move")
(set_attr "length" "4,16")])
-;; Implement atomic DFmode load using 64-bit floating point load.
+;; PA 2.0 hardware supports out-of-order execution of loads and stores, so
+;; we need a memory barrier to enforce program order for memory references.
+;; Since we want PA 1.x code to be PA 2.0 compatible, we also need the
+;; barrier when generating PA 1.x code.
-(define_expand "atomic_loaddf"
- [(match_operand:DF 0 "register_operand") ;; val out
- (match_operand:DF 1 "memory_operand") ;; memory
- (match_operand:SI 2 "const_int_operand")] ;; model
+(define_expand "memory_barrier"
+ [(set (match_dup 0)
+ (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))]
""
{
- enum memmodel model;
-
- if (TARGET_64BIT || TARGET_DISABLE_FPREGS || TARGET_SOFT_FLOAT)
- FAIL;
-
- model = memmodel_from_int (INTVAL (operands[2]));
- operands[1] = force_reg (SImode, XEXP (operands[1], 0));
- expand_mem_thread_fence (model);
- emit_insn (gen_atomic_loaddf_1 (operands[0], operands[1]));
- if (is_mm_seq_cst (model))
- expand_mem_thread_fence (model);
- DONE;
+ operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+ MEM_VOLATILE_P (operands[0]) = 1;
})
-(define_insn "atomic_loaddf_1"
- [(set (match_operand:DF 0 "register_operand" "=f,r")
- (mem:DF (match_operand:SI 1 "register_operand" "r,r")))
- (clobber (match_scratch:DF 2 "=X,f"))]
- "!TARGET_64BIT && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT"
- "@
- {fldds|fldd} 0(%1),%0
- {fldds|fldd} 0(%1),%2\n\t{fstds|fstd} %2,-16(%%sp)\n\t{ldws|ldw} -16(%%sp),%0\n\t{ldws|ldw} -12(%%sp),%R0"
- [(set_attr "type" "move,move")
- (set_attr "length" "4,16")])
-
-;; Implement atomic DFmode store using 64-bit floating point store.
-
-(define_expand "atomic_storedf"
- [(match_operand:DF 0 "memory_operand") ;; memory
- (match_operand:DF 1 "register_operand") ;; val out
- (match_operand:SI 2 "const_int_operand")] ;; model
+(define_insn "*memory_barrier"
+ [(set (match_operand:BLK 0 "" "")
+ (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))]
""
-{
- enum memmodel model;
-
- if (TARGET_SYNC_LIBCALL)
- {
- rtx mem = operands[0];
- rtx val = operands[1];
- if (pa_maybe_emit_compare_and_swap_exchange_loop (NULL_RTX, mem, val))
- DONE;
- }
-
- if (TARGET_64BIT || TARGET_DISABLE_FPREGS || TARGET_SOFT_FLOAT)
- FAIL;
-
- model = memmodel_from_int (INTVAL (operands[2]));
- operands[0] = force_reg (SImode, XEXP (operands[0], 0));
- expand_mem_thread_fence (model);
- emit_insn (gen_atomic_storedf_1 (operands[0], operands[1]));
- if (is_mm_seq_cst (model))
- expand_mem_thread_fence (model);
- DONE;
-})
-
-(define_insn "atomic_storedf_1"
- [(set (mem:DF (match_operand:SI 0 "register_operand" "r,r"))
- (match_operand:DF 1 "register_operand" "f,r"))
- (clobber (match_scratch:DF 2 "=X,f"))]
- "!TARGET_64BIT && !TARGET_DISABLE_FPREGS
- && !TARGET_SOFT_FLOAT && !TARGET_SYNC_LIBCALL"
- "@
- {fstds|fstd} %1,0(%0)
- {stws|stw} %1,-16(%%sp)\n\t{stws|stw} %R1,-12(%%sp)\n\t{fldds|fldd} -16(%%sp),%2\n\t{fstds|fstd} %2,0(%0)"
- [(set_attr "type" "move,move")
- (set_attr "length" "4,16")])
+ "sync"
+ [(set_attr "type" "binary")
+ (set_attr "length" "4")])
diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c
index 1bcdaed..62c653f 100644
--- a/gcc/config/pdp11/pdp11.c
+++ b/gcc/config/pdp11/pdp11.c
@@ -291,6 +291,9 @@ static bool pdp11_scalar_mode_supported_p (scalar_mode);
#undef TARGET_INVALID_WITHIN_DOLOOP
#define TARGET_INVALID_WITHIN_DOLOOP hook_constcharptr_const_rtx_insn_null
+
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
/* A helper function to determine if REGNO should be saved in the
current function's stack frame. */
diff --git a/gcc/config/powerpcspe/powerpcspe-c.c b/gcc/config/powerpcspe/powerpcspe-c.c
index 157c185..0e69ebb 100644
--- a/gcc/config/powerpcspe/powerpcspe-c.c
+++ b/gcc/config/powerpcspe/powerpcspe-c.c
@@ -220,21 +220,22 @@ rs6000_macro_to_expand (cpp_reader *pfile, const cpp_token *tok)
else if (ident && (ident != C_CPP_HASHNODE (__vector_keyword)))
{
enum rid rid_code = (enum rid)(ident->rid_code);
- enum node_type itype = ident->type;
+ bool is_macro = cpp_macro_p (ident);
+
/* If there is a function-like macro, check if it is going to be
invoked with or without arguments. Without following ( treat
it like non-macro, otherwise the following cpp_get_token eats
what should be preserved. */
- if (itype == NT_MACRO && cpp_fun_like_macro_p (ident))
+ if (is_macro && cpp_fun_like_macro_p (ident))
{
int idx2 = idx;
do
tok = cpp_peek_token (pfile, idx2++);
while (tok->type == CPP_PADDING);
if (tok->type != CPP_OPEN_PAREN)
- itype = NT_VOID;
+ is_macro = false;
}
- if (itype == NT_MACRO)
+ if (is_macro)
{
do
(void) cpp_get_token (pfile);
diff --git a/gcc/config/powerpcspe/powerpcspe.c b/gcc/config/powerpcspe/powerpcspe.c
index 7dd24e4..dea1eab 100644
--- a/gcc/config/powerpcspe/powerpcspe.c
+++ b/gcc/config/powerpcspe/powerpcspe.c
@@ -6030,6 +6030,7 @@ rs6000_density_test (rs6000_cost_data *data)
struct loop *loop = data->loop_info;
basic_block *bbs = get_loop_body (loop);
int nbbs = loop->num_nodes;
+ loop_vec_info loop_vinfo = loop_vec_info_for_loop (data->loop_info);
int vec_cost = data->cost[vect_body], not_vec_cost = 0;
int i, density_pct;
@@ -6041,7 +6042,7 @@ rs6000_density_test (rs6000_cost_data *data)
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple *stmt = gsi_stmt (gsi);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (stmt);
if (!STMT_VINFO_RELEVANT_P (stmt_info)
&& !STMT_VINFO_IN_PATTERN_P (stmt_info))
diff --git a/gcc/config/riscv/pic.md b/gcc/config/riscv/pic.md
index a4a9732..9425020 100644
--- a/gcc/config/riscv/pic.md
+++ b/gcc/config/riscv/pic.md
@@ -22,71 +22,100 @@
;; Simplify PIC loads to static variables.
;; These should go away once we figure out how to emit auipc discretely.
-(define_insn "*local_pic_load_s<mode>"
+(define_insn "*local_pic_load<mode>"
[(set (match_operand:ANYI 0 "register_operand" "=r")
- (sign_extend:ANYI (mem:ANYI (match_operand 1 "absolute_symbolic_operand" ""))))]
+ (mem:ANYI (match_operand 1 "absolute_symbolic_operand" "")))]
+ "USE_LOAD_ADDRESS_MACRO (operands[1])"
+ "<default_load>\t%0,%1"
+ [(set (attr "length") (const_int 8))])
+
+(define_insn "*local_pic_load_s<mode>"
+ [(set (match_operand:SUPERQI 0 "register_operand" "=r")
+ (sign_extend:SUPERQI (mem:SUBX (match_operand 1 "absolute_symbolic_operand" ""))))]
"USE_LOAD_ADDRESS_MACRO (operands[1])"
- "<load>\t%0,%1"
+ "<SUBX:load>\t%0,%1"
[(set (attr "length") (const_int 8))])
(define_insn "*local_pic_load_u<mode>"
- [(set (match_operand:ZERO_EXTEND_LOAD 0 "register_operand" "=r")
- (zero_extend:ZERO_EXTEND_LOAD (mem:ZERO_EXTEND_LOAD (match_operand 1 "absolute_symbolic_operand" ""))))]
+ [(set (match_operand:SUPERQI 0 "register_operand" "=r")
+ (zero_extend:SUPERQI (mem:SUBX (match_operand 1 "absolute_symbolic_operand" ""))))]
"USE_LOAD_ADDRESS_MACRO (operands[1])"
- "<load>u\t%0,%1"
+ "<SUBX:load>u\t%0,%1"
[(set (attr "length") (const_int 8))])
-(define_insn "*local_pic_load<mode>"
- [(set (match_operand:ANYF 0 "register_operand" "=f")
+;; We can support ANYF loads into X register if there is no double support
+;; or if the target is 64-bit.
+
+(define_insn "*local_pic_load<ANYF:mode>"
+ [(set (match_operand:ANYF 0 "register_operand" "=f,*r")
(mem:ANYF (match_operand 1 "absolute_symbolic_operand" "")))
- (clobber (match_scratch:DI 2 "=r"))]
- "TARGET_HARD_FLOAT && TARGET_64BIT && USE_LOAD_ADDRESS_MACRO (operands[1])"
- "<load>\t%0,%1,%2"
+ (clobber (match_scratch:P 2 "=r,X"))]
+ "TARGET_HARD_FLOAT && USE_LOAD_ADDRESS_MACRO (operands[1])
+ && (!TARGET_DOUBLE_FLOAT || TARGET_64BIT)"
+ "@
+ <ANYF:load>\t%0,%1,%2
+ <softload>\t%0,%1"
[(set (attr "length") (const_int 8))])
-(define_insn "*local_pic_load<mode>"
+;; ??? For a 32-bit target with double float, a DF load into a X reg isn't
+;; supported. ld is not valid in that case. Punt for now. Maybe add a split
+;; for this later.
+
+(define_insn "*local_pic_load_32d<ANYF:mode>"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(mem:ANYF (match_operand 1 "absolute_symbolic_operand" "")))
- (clobber (match_scratch:SI 2 "=r"))]
- "TARGET_HARD_FLOAT && !TARGET_64BIT && USE_LOAD_ADDRESS_MACRO (operands[1])"
- "<load>\t%0,%1,%2"
+ (clobber (match_scratch:P 2 "=r"))]
+ "TARGET_HARD_FLOAT && USE_LOAD_ADDRESS_MACRO (operands[1])
+ && (TARGET_DOUBLE_FLOAT && !TARGET_64BIT)"
+ "<ANYF:load>\t%0,%1,%2"
[(set (attr "length") (const_int 8))])
-(define_insn "*local_pic_loadu<mode>"
- [(set (match_operand:SUPERQI 0 "register_operand" "=r")
- (zero_extend:SUPERQI (mem:SUBX (match_operand 1 "absolute_symbolic_operand" ""))))]
- "USE_LOAD_ADDRESS_MACRO (operands[1])"
- "<load>u\t%0,%1"
+(define_insn "*local_pic_load_sf<mode>"
+ [(set (match_operand:SOFTF 0 "register_operand" "=r")
+ (mem:SOFTF (match_operand 1 "absolute_symbolic_operand" "")))]
+ "!TARGET_HARD_FLOAT && USE_LOAD_ADDRESS_MACRO (operands[1])"
+ "<softload>\t%0,%1"
[(set (attr "length") (const_int 8))])
-(define_insn "*local_pic_storedi<mode>"
- [(set (mem:ANYI (match_operand 0 "absolute_symbolic_operand" ""))
- (match_operand:ANYI 1 "reg_or_0_operand" "rJ"))
- (clobber (match_scratch:DI 2 "=&r"))]
- "TARGET_64BIT && USE_LOAD_ADDRESS_MACRO (operands[0])"
- "<store>\t%z1,%0,%2"
- [(set (attr "length") (const_int 8))])
+;; Simplify PIC stores to static variables.
+;; These should go away once we figure out how to emit auipc discretely.
-(define_insn "*local_pic_storesi<mode>"
+(define_insn "*local_pic_store<ANYI:mode>"
[(set (mem:ANYI (match_operand 0 "absolute_symbolic_operand" ""))
(match_operand:ANYI 1 "reg_or_0_operand" "rJ"))
- (clobber (match_scratch:SI 2 "=&r"))]
- "!TARGET_64BIT && USE_LOAD_ADDRESS_MACRO (operands[0])"
- "<store>\t%z1,%0,%2"
+ (clobber (match_scratch:P 2 "=&r"))]
+ "USE_LOAD_ADDRESS_MACRO (operands[0])"
+ "<ANYI:store>\t%z1,%0,%2"
[(set (attr "length") (const_int 8))])
-(define_insn "*local_pic_storedi<mode>"
+(define_insn "*local_pic_store<ANYF:mode>"
[(set (mem:ANYF (match_operand 0 "absolute_symbolic_operand" ""))
- (match_operand:ANYF 1 "register_operand" "f"))
- (clobber (match_scratch:DI 2 "=r"))]
- "TARGET_HARD_FLOAT && TARGET_64BIT && USE_LOAD_ADDRESS_MACRO (operands[0])"
- "<store>\t%1,%0,%2"
+ (match_operand:ANYF 1 "register_operand" "f,*r"))
+ (clobber (match_scratch:P 2 "=r,&r"))]
+ "TARGET_HARD_FLOAT && USE_LOAD_ADDRESS_MACRO (operands[0])
+ && (!TARGET_DOUBLE_FLOAT || TARGET_64BIT)"
+ "@
+ <ANYF:store>\t%1,%0,%2
+ <softstore>\t%1,%0,%2"
[(set (attr "length") (const_int 8))])
-(define_insn "*local_pic_storesi<mode>"
- [(set (mem:ANYF (match_operand 0 "absolute_symbolic_operand" ""))
- (match_operand:ANYF 1 "register_operand" "f"))
- (clobber (match_scratch:SI 2 "=r"))]
- "TARGET_HARD_FLOAT && !TARGET_64BIT && USE_LOAD_ADDRESS_MACRO (operands[0])"
- "<store>\t%1,%0,%2"
+;; ??? For a 32-bit target with double float, a DF store from a X reg isn't
+;; supported. sd is not valid in that case. Punt for now. Maybe add a split
+;; for this later.
+
+(define_insn "*local_pic_store_32d<ANYF:mode>"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (mem:ANYF (match_operand 1 "absolute_symbolic_operand" "")))
+ (clobber (match_scratch:P 2 "=r"))]
+ "TARGET_HARD_FLOAT && USE_LOAD_ADDRESS_MACRO (operands[1])
+ && (TARGET_DOUBLE_FLOAT && !TARGET_64BIT)"
+ "<ANYF:store>\t%1,%0,%2"
+ [(set (attr "length") (const_int 8))])
+
+(define_insn "*local_pic_store_sf<SOFTF:mode>"
+ [(set (mem:SOFTF (match_operand 0 "absolute_symbolic_operand" ""))
+ (match_operand:SOFTF 1 "register_operand" "r"))
+ (clobber (match_scratch:P 2 "=&r"))]
+ "!TARGET_HARD_FLOAT && USE_LOAD_ADDRESS_MACRO (operands[0])"
+ "<softstore>\t%1,%0,%2"
[(set (attr "length") (const_int 8))])
diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
index 69e70fe..9d6d981 100644
--- a/gcc/config/riscv/riscv.c
+++ b/gcc/config/riscv/riscv.c
@@ -802,7 +802,13 @@ riscv_address_insns (rtx x, machine_mode mode, bool might_split_p)
int n = 1;
if (!riscv_classify_address (&addr, x, mode, false))
- return 0;
+ {
+ /* This could be a pattern from the pic.md file. In which case we want
+ this address to always have a cost of 3 to make it as expensive as the
+ most expensive symbol. This prevents constant propagation from
+ preferring symbols over register plus offset. */
+ return 3;
+ }
/* BLKmode is used for single unaligned loads and stores and should
not count as a multiword mode. */
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 613af9d..95fbb28 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -269,9 +269,6 @@
;; Iterator for QImode extension patterns.
(define_mode_iterator SUPERQI [HI SI (DI "TARGET_64BIT")])
-;; Iterator for extending loads.
-(define_mode_iterator ZERO_EXTEND_LOAD [QI HI (SI "TARGET_64BIT")])
-
;; Iterator for hardware integer modes narrower than XLEN.
(define_mode_iterator SUBX [QI HI (SI "TARGET_64BIT")])
@@ -282,6 +279,9 @@
(define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT")
(DF "TARGET_DOUBLE_FLOAT")])
+;; Iterator for floating-point modes that can be loaded into X registers.
+(define_mode_iterator SOFTF [SF (DF "TARGET_64BIT")])
+
;; This attribute gives the length suffix for a sign- or zero-extension
;; instruction.
(define_mode_attr size [(QI "b") (HI "h")])
@@ -289,9 +289,19 @@
;; Mode attributes for loads.
(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (SF "flw") (DF "fld")])
+;; Instruction names for integer loads that aren't explicitly sign or zero
+;; extended. See riscv_output_move and LOAD_EXTEND_OP.
+(define_mode_attr default_load [(QI "lbu") (HI "lhu") (SI "lw") (DI "ld")])
+
+;; Mode attribute for FP loads into integer registers.
+(define_mode_attr softload [(SF "lw") (DF "ld")])
+
;; Instruction names for stores.
(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (SF "fsw") (DF "fsd")])
+;; Instruction names for FP stores from integer registers.
+(define_mode_attr softstore [(SF "sw") (DF "sd")])
+
;; This attribute gives the best constraint to use for registers of
;; a given mode.
(define_mode_attr reg [(SI "d") (DI "d") (CC "d")])
diff --git a/gcc/config/rs6000/aix43.h b/gcc/config/rs6000/aix43.h
deleted file mode 100644
index bac8b53..0000000
--- a/gcc/config/rs6000/aix43.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/* Definitions of target machine for GNU compiler,
- for IBM RS/6000 POWER running AIX version 4.3.
- Copyright (C) 1998-2018 Free Software Foundation, Inc.
- Contributed by David Edelsohn (edelsohn@gnu.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.
-
- 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/>. */
-
-/* The macro SUBTARGET_OVERRIDE_OPTIONS is provided for subtargets, to
- get control in TARGET_OPTION_OVERRIDE. */
-
-#define SUBTARGET_OVERRIDE_OPTIONS \
-do { \
- if (TARGET_64BIT && ! TARGET_POWERPC64) \
- { \
- rs6000_isa_flags |= OPTION_MASK_POWERPC64; \
- warning (0, "-maix64 requires PowerPC64 architecture remain enabled"); \
- } \
- if (TARGET_SOFT_FLOAT && TARGET_LONG_DOUBLE_128) \
- { \
- rs6000_long_double_type_size = 64; \
- if (global_options_set.x_rs6000_long_double_type_size) \
- warning (0, "soft-float and long-double-128 are incompatible"); \
- } \
- if (TARGET_POWERPC64 && ! TARGET_64BIT) \
- { \
- error ("-maix64 required: 64-bit computation with 32-bit addressing not yet supported"); \
- } \
-} while (0)
-
-#undef ASM_SPEC
-#define ASM_SPEC "-u %{maix64:-a64 %{!mcpu*:-mppc64}} %(asm_cpu)"
-
-/* Common ASM definitions used by ASM_SPEC amongst the various targets
- for handling -mcpu=xxx switches. */
-#undef ASM_CPU_SPEC
-#define ASM_CPU_SPEC \
-"%{!mcpu*: %{!maix64: \
- %{!mpowerpc64: %(asm_default)} \
- %{mpowerpc64: -mppc64}}} \
-%{mcpu=power3: -m620} \
-%{mcpu=power4: -m620} \
-%{mcpu=powerpc: -mppc} \
-%{mcpu=rs64a: -mppc} \
-%{mcpu=601: -m601} \
-%{mcpu=602: -mppc} \
-%{mcpu=603: -m603} \
-%{mcpu=603e: -m603} \
-%{mcpu=604: -m604} \
-%{mcpu=604e: -m604} \
-%{mcpu=620: -m620} \
-%{mcpu=630: -m620}"
-
-#undef ASM_DEFAULT_SPEC
-#define ASM_DEFAULT_SPEC "-mppc"
-
-#undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define ("_AIX43"); \
- TARGET_OS_AIX_CPP_BUILTINS (); \
- } \
- while (0)
-
-#undef CPP_SPEC
-#define CPP_SPEC "%{posix: -D_POSIX_SOURCE}\
- %{ansi: -D_ANSI_C_SOURCE}\
- %{maix64: -D__64BIT__}\
- %{mpe: -I%R/usr/lpp/ppe.poe/include}\
- %{pthread: -D_THREAD_SAFE}"
-
-/* The GNU C++ standard library requires that these macros be
- defined. */
-#undef CPLUSPLUS_CPP_SPEC
-#define CPLUSPLUS_CPP_SPEC \
- "-D_ALL_SOURCE \
- %{maix64: -D__64BIT__} \
- %{mpe: -I%R/usr/lpp/ppe.poe/include} \
- %{pthread: -D_THREAD_SAFE}"
-
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT 0
-
-#undef PROCESSOR_DEFAULT
-#define PROCESSOR_DEFAULT PROCESSOR_PPC604e
-
-/* AIX does not support Altivec. */
-#undef TARGET_ALTIVEC
-#define TARGET_ALTIVEC 0
-#undef TARGET_ALTIVEC_ABI
-#define TARGET_ALTIVEC_ABI 0
-#undef TARGET_EXTRA_BUILTINS
-#define TARGET_EXTRA_BUILTINS 0
-
-
-/* Define this macro as a C expression for the initializer of an
- array of string to tell the driver program which options are
- defaults for this target and thus do not need to be handled
- specially when using `MULTILIB_OPTIONS'.
-
- Do not define this macro if `MULTILIB_OPTIONS' is not defined in
- the target makefile fragment or if none of the options listed in
- `MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */
-
-#undef MULTILIB_DEFAULTS
-#define MULTILIB_DEFAULTS { "mcpu=common" }
-
-#undef LIB_SPEC
-#define LIB_SPEC "%{pg:-L%R/lib/profiled -L%R/usr/lib/profiled}\
- %{p:-L%R/lib/profiled -L%R/usr/lib/profiled}\
- %{!maix64:%{!shared:%{g*:-lg}}}\
- %{mpe:-L%R/usr/lpp/ppe.poe/lib -lmpi -lvtd}\
- %{pthread:-L%R/usr/lib/threads -lpthreads -lc_r %R/usr/lib/libc.a}\
- %{!pthread:-lc}"
-
-#undef LINK_SPEC
-#define LINK_SPEC "-bpT:0x10000000 -bpD:0x20000000 %{!r:-btextro} -bnodelcsect\
- %{static:-bnso %(link_syscalls) } %{shared:-bM:SRE %{!e:-bnoentry}}\
- %{!maix64:%{!shared:%{g*: %(link_libg) }}} %{maix64:-b64}\
- %{mpe:-binitfini:poe_remote_main}"
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "%{!shared:\
- %{maix64:%{pg:gcrt0_64%O%s}%{!pg:%{p:mcrt0_64%O%s}%{!p:crt0_64%O%s}}}\
- %{!maix64:\
- %{pthread:%{pg:gcrt0_r%O%s}%{!pg:%{p:mcrt0_r%O%s}%{!p:crt0_r%O%s}}}\
- %{!pthread:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}}}"
-
-/* AIX 4.3 typedefs ptrdiff_t as "long" while earlier releases used "int". */
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "long int"
-
-/* AIX 4.2 and above provides initialization and finalization function
- support from linker command line. */
-#undef HAS_INIT_SECTION
-#define HAS_INIT_SECTION
-
-#undef LD_INIT_SWITCH
-#define LD_INIT_SWITCH "-binitfini"
-
-/* The IBM AIX 4.x assembler doesn't support forward references in
- .set directives. We handle this by deferring the output of .set
- directives to the end of the compilation unit. */
-#define TARGET_DEFERRED_OUTPUT_DEFS(DECL,TARGET) true
-
-/* This target uses the aix64.opt file. */
-#define TARGET_USES_AIX64_OPT 1
-
-#define TARGET_AIX_VERSION 43
-
-#undef TARGET_LIBC_HAS_FUNCTION
-#define TARGET_LIBC_HAS_FUNCTION no_c99_libc_has_function
diff --git a/gcc/config/rs6000/aix51.h b/gcc/config/rs6000/aix51.h
deleted file mode 100644
index 457d411..0000000
--- a/gcc/config/rs6000/aix51.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/* Definitions of target machine for GNU compiler,
- for IBM RS/6000 POWER running AIX V5.
- Copyright (C) 2001-2018 Free Software Foundation, Inc.
- Contributed by David Edelsohn (edelsohn@gnu.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.
-
- 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/>. */
-
-/* The macro SUBTARGET_OVERRIDE_OPTIONS is provided for subtargets, to
- get control in TARGET_OPTION_OVERRIDE. */
-
-#define SUBTARGET_OVERRIDE_OPTIONS \
-do { \
- if (TARGET_64BIT && ! TARGET_POWERPC64) \
- { \
- rs6000_isa_flags |= OPTION_MASK_POWERPC64; \
- warning (0, "-maix64 requires PowerPC64 architecture remain enabled"); \
- } \
- if (TARGET_POWERPC64 && ! TARGET_64BIT) \
- { \
- error ("-maix64 required: 64-bit computation with 32-bit addressing not yet supported"); \
- } \
-} while (0)
-
-#undef ASM_SPEC
-#define ASM_SPEC "-u %{maix64:-a64 %{!mcpu*:-mppc64}} %(asm_cpu)"
-
-/* Common ASM definitions used by ASM_SPEC amongst the various targets
- for handling -mcpu=xxx switches. */
-#undef ASM_CPU_SPEC
-#define ASM_CPU_SPEC \
-"%{!mcpu*: %{!maix64: \
- %{!mpowerpc64: %(asm_default)} \
- %{mpowerpc64: -mppc64}}} \
-%{mcpu=power3: -m620} \
-%{mcpu=power4: -m620} \
-%{mcpu=powerpc: -mppc} \
-%{mcpu=rs64a: -mppc} \
-%{mcpu=601: -m601} \
-%{mcpu=602: -mppc} \
-%{mcpu=603: -m603} \
-%{mcpu=603e: -m603} \
-%{mcpu=604: -m604} \
-%{mcpu=604e: -m604} \
-%{mcpu=620: -m620} \
-%{mcpu=630: -m620} \
-%{mcpu=970: -m620} \
-%{mcpu=G5: -m620}"
-
-#undef ASM_DEFAULT_SPEC
-#define ASM_DEFAULT_SPEC "-mppc"
-
-#undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define ("_AIX43"); \
- builtin_define ("_AIX51"); \
- TARGET_OS_AIX_CPP_BUILTINS (); \
- } \
- while (0)
-
-#undef CPP_SPEC
-#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} \
- %{ansi: -D_ANSI_C_SOURCE} \
- %{maix64: -D__64BIT__} \
- %{mpe: -I%R/usr/lpp/ppe.poe/include} \
- %{pthread: -D_THREAD_SAFE}"
-
-/* The GNU C++ standard library requires that these macros be
- defined. */
-#undef CPLUSPLUS_CPP_SPEC
-#define CPLUSPLUS_CPP_SPEC \
- "-D_ALL_SOURCE \
- %{maix64: -D__64BIT__} \
- %{mpe: -I%R/usr/lpp/ppe.poe/include} \
- %{pthread: -D_THREAD_SAFE}"
-
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT 0
-
-#undef PROCESSOR_DEFAULT
-#define PROCESSOR_DEFAULT PROCESSOR_PPC604e
-
-/* AIX does not support Altivec. */
-#undef TARGET_ALTIVEC
-#define TARGET_ALTIVEC 0
-#undef TARGET_ALTIVEC_ABI
-#define TARGET_ALTIVEC_ABI 0
-#undef TARGET_EXTRA_BUILTINS
-#define TARGET_EXTRA_BUILTINS 0
-
-
-/* Define this macro as a C expression for the initializer of an
- array of string to tell the driver program which options are
- defaults for this target and thus do not need to be handled
- specially when using `MULTILIB_OPTIONS'.
-
- Do not define this macro if `MULTILIB_OPTIONS' is not defined in
- the target makefile fragment or if none of the options listed in
- `MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */
-
-#undef MULTILIB_DEFAULTS
-#define MULTILIB_DEFAULTS { "mcpu=common" }
-
-#undef LIB_SPEC
-#define LIB_SPEC "%{pg:-L%R/lib/profiled -L%R/usr/lib/profiled}\
- %{p:-L%R/lib/profiled -L%R/usr/lib/profiled}\
- %{!maix64:%{!shared:%{g*:-lg}}}\
- %{mpe:-L%R/usr/lpp/ppe.poe/lib -lmpi -lvtd}\
- %{pthread:-lpthreads} -lc"
-
-#undef LINK_SPEC
-#define LINK_SPEC "-bpT:0x10000000 -bpD:0x20000000 %{!r:-btextro}\
- %{static:-bnso %(link_syscalls) } %{shared:-bM:SRE %{!e:-bnoentry}}\
- %{!maix64:%{!shared:%{g*: %(link_libg) }}} %{maix64:-b64}\
- %{mpe:-binitfini:poe_remote_main}"
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "%{!shared:\
- %{maix64:%{pg:gcrt0_64%O%s}%{!pg:%{p:mcrt0_64%O%s}%{!p:crt0_64%O%s}}}\
- %{!maix64:\
- %{pthread:%{pg:gcrt0_r%O%s}%{!pg:%{p:mcrt0_r%O%s}%{!p:crt0_r%O%s}}}\
- %{!pthread:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}}}"
-
-/* AIX V5 typedefs ptrdiff_t as "long" while earlier releases used "int". */
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "long int"
-
-/* Type used for wchar_t, as a string used in a declaration. */
-#undef WCHAR_TYPE
-#define WCHAR_TYPE (!TARGET_64BIT ? "short unsigned int" : "unsigned int")
-
-/* Width of wchar_t in bits. */
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE (!TARGET_64BIT ? 16 : 32)
-
-/* AIX 4.2 and above provides initialization and finalization function
- support from linker command line. */
-#undef HAS_INIT_SECTION
-#define HAS_INIT_SECTION
-
-#undef LD_INIT_SWITCH
-#define LD_INIT_SWITCH "-binitfini"
-
-/* This target uses the aix64.opt file. */
-#define TARGET_USES_AIX64_OPT 1
-
-/* This target defines SUPPORTS_WEAK and TARGET_ASM_NAMED_SECTION,
- but does not have crtbegin/end. */
-
-#define TARGET_AIX_VERSION 51
-
-#undef TARGET_LIBC_HAS_FUNCTION
-#define TARGET_LIBC_HAS_FUNCTION no_c99_libc_has_function
diff --git a/gcc/config/rs6000/aix52.h b/gcc/config/rs6000/aix52.h
deleted file mode 100644
index 7a85897..0000000
--- a/gcc/config/rs6000/aix52.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Definitions of target machine for GNU compiler,
- for IBM RS/6000 POWER running AIX V5.2.
- Copyright (C) 2002-2018 Free Software Foundation, Inc.
- Contributed by David Edelsohn (edelsohn@gnu.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.
-
- 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/>. */
-
-/* The macro SUBTARGET_OVERRIDE_OPTIONS is provided for subtargets, to
- get control in TARGET_OPTION_OVERRIDE. */
-
-#define SUBTARGET_OVERRIDE_OPTIONS \
-do { \
- if (TARGET_64BIT && ! TARGET_POWERPC64) \
- { \
- rs6000_isa_flags |= OPTION_MASK_POWERPC64; \
- warning (0, "-maix64 requires PowerPC64 architecture remain enabled"); \
- } \
- if (TARGET_SOFT_FLOAT && TARGET_LONG_DOUBLE_128) \
- { \
- rs6000_long_double_type_size = 64; \
- if (global_options_set.x_rs6000_long_double_type_size) \
- warning (0, "soft-float and long-double-128 are incompatible"); \
- } \
- if (TARGET_POWERPC64 && ! TARGET_64BIT) \
- { \
- error ("-maix64 required: 64-bit computation with 32-bit addressing not yet supported"); \
- } \
-} while (0)
-
-#undef ASM_SPEC
-#define ASM_SPEC "-u %{maix64:-a64 %{!mcpu*:-mppc64}} %(asm_cpu)"
-
-/* Common ASM definitions used by ASM_SPEC amongst the various targets
- for handling -mcpu=xxx switches. */
-#undef ASM_CPU_SPEC
-#define ASM_CPU_SPEC \
-"%{!mcpu*: %{!maix64: \
- %{mpowerpc64: -mppc64} \
- %{!mpowerpc64: %(asm_default)}}} \
-%{mcpu=power3: -m620} \
-%{mcpu=power4: -m620} \
-%{mcpu=power5: -m620} \
-%{mcpu=power5+: -m620} \
-%{mcpu=power6: -m620} \
-%{mcpu=power6x: -m620} \
-%{mcpu=powerpc: -mppc} \
-%{mcpu=rs64a: -mppc} \
-%{mcpu=603: -m603} \
-%{mcpu=603e: -m603} \
-%{mcpu=604: -m604} \
-%{mcpu=604e: -m604} \
-%{mcpu=620: -m620} \
-%{mcpu=630: -m620} \
-%{mcpu=970: -m620} \
-%{mcpu=G5: -m620}"
-
-#undef ASM_DEFAULT_SPEC
-#define ASM_DEFAULT_SPEC "-mppc"
-
-#undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define ("_AIX43"); \
- builtin_define ("_AIX51"); \
- builtin_define ("_AIX52"); \
- TARGET_OS_AIX_CPP_BUILTINS (); \
- } \
- while (0)
-
-#undef CPP_SPEC
-#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} \
- %{ansi: -D_ANSI_C_SOURCE} \
- %{maix64: -D__64BIT__} \
- %{mpe: -I%R/usr/lpp/ppe.poe/include} \
- %{pthread: -D_THREAD_SAFE}"
-
-/* The GNU C++ standard library requires that these macros be
- defined. Synchronize with libstdc++ os_defines.h. */
-#undef CPLUSPLUS_CPP_SPEC
-#define CPLUSPLUS_CPP_SPEC \
- "-D_ALL_SOURCE \
- %{maix64: -D__64BIT__} \
- %{mpe: -I%R/usr/lpp/ppe.poe/include} \
- %{pthread: -D_THREAD_SAFE}"
-
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT 0
-
-#undef PROCESSOR_DEFAULT
-#define PROCESSOR_DEFAULT PROCESSOR_POWER4
-#undef PROCESSOR_DEFAULT64
-#define PROCESSOR_DEFAULT64 PROCESSOR_POWER4
-
-/* AIX does not support Altivec. */
-#undef TARGET_ALTIVEC
-#define TARGET_ALTIVEC 0
-#undef TARGET_ALTIVEC_ABI
-#define TARGET_ALTIVEC_ABI 0
-#undef TARGET_EXTRA_BUILTINS
-#define TARGET_EXTRA_BUILTINS 0
-
-/* Define this macro as a C expression for the initializer of an
- array of string to tell the driver program which options are
- defaults for this target and thus do not need to be handled
- specially when using `MULTILIB_OPTIONS'.
-
- Do not define this macro if `MULTILIB_OPTIONS' is not defined in
- the target makefile fragment or if none of the options listed in
- `MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */
-
-#undef MULTILIB_DEFAULTS
-
-#undef LIB_SPEC
-#define LIB_SPEC "%{pg:-L%R/lib/profiled -L%R/usr/lib/profiled}\
- %{p:-L%R/lib/profiled -L%R/usr/lib/profiled}\
- %{!maix64:%{!shared:%{g*:-lg}}}\
- %{mpe:-L%R/usr/lpp/ppe.poe/lib -lmpi -lvtd}\
- %{pthread:-lpthreads} -lc"
-
-#undef LINK_SPEC
-#define LINK_SPEC "-bpT:0x10000000 -bpD:0x20000000 %{!r:-btextro}\
- %{static:-bnso %(link_syscalls) } %{shared:-bM:SRE %{!e:-bnoentry}}\
- %{!maix64:%{!shared:%{g*: %(link_libg) }}} %{maix64:-b64}\
- %{mpe:-binitfini:poe_remote_main}"
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "%{!shared:\
- %{maix64:%{pg:gcrt0_64%O%s}%{!pg:%{p:mcrt0_64%O%s}%{!p:crt0_64%O%s}}}\
- %{!maix64:\
- %{pthread:%{pg:gcrt0_r%O%s}%{!pg:%{p:mcrt0_r%O%s}%{!p:crt0_r%O%s}}}\
- %{!pthread:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}}}"
-
-/* AIX V5 typedefs ptrdiff_t as "long" while earlier releases used "int". */
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "long int"
-
-/* Type used for wchar_t, as a string used in a declaration. */
-#undef WCHAR_TYPE
-#define WCHAR_TYPE (!TARGET_64BIT ? "short unsigned int" : "unsigned int")
-
-/* Width of wchar_t in bits. */
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE (!TARGET_64BIT ? 16 : 32)
-
-/* AIX 4.2 and above provides initialization and finalization function
- support from linker command line. */
-#undef HAS_INIT_SECTION
-#define HAS_INIT_SECTION
-
-#undef LD_INIT_SWITCH
-#define LD_INIT_SWITCH "-binitfini"
-
-#ifndef _AIX52
-extern long long int atoll(const char *);
-#endif
-
-/* This target uses the aix64.opt file. */
-#define TARGET_USES_AIX64_OPT 1
-
-/* This target defines SUPPORTS_WEAK and TARGET_ASM_NAMED_SECTION,
- but does not have crtbegin/end. */
-
-#define TARGET_AIX_VERSION 52
diff --git a/gcc/config/rs6000/aix53.h b/gcc/config/rs6000/aix53.h
deleted file mode 100644
index e708108..0000000
--- a/gcc/config/rs6000/aix53.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/* Definitions of target machine for GNU compiler,
- for IBM RS/6000 POWER running AIX V5.3.
- Copyright (C) 2002-2018 Free Software Foundation, Inc.
- Contributed by David Edelsohn (edelsohn@gnu.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.
-
- 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/>. */
-
-/* The macro SUBTARGET_OVERRIDE_OPTIONS is provided for subtargets, to
- get control in TARGET_OPTION_OVERRIDE. */
-
-#define SUBTARGET_OVERRIDE_OPTIONS \
-do { \
- if (TARGET_64BIT && ! TARGET_POWERPC64) \
- { \
- rs6000_isa_flags |= OPTION_MASK_POWERPC64; \
- warning (0, "-maix64 requires PowerPC64 architecture remain enabled"); \
- } \
- if (TARGET_SOFT_FLOAT && TARGET_LONG_DOUBLE_128) \
- { \
- rs6000_long_double_type_size = 64; \
- if (global_options_set.x_rs6000_long_double_type_size) \
- warning (0, "soft-float and long-double-128 are incompatible"); \
- } \
- if (TARGET_POWERPC64 && ! TARGET_64BIT) \
- { \
- error ("-maix64 required: 64-bit computation with 32-bit addressing not yet supported"); \
- } \
-} while (0)
-
-#undef ASM_SPEC
-#define ASM_SPEC "-u %{maix64:-a64 %{!mcpu*:-mppc64}} %(asm_cpu)"
-
-/* Common ASM definitions used by ASM_SPEC amongst the various targets for
- handling -mcpu=xxx switches. There is a parallel list in driver-rs6000.c to
- provide the default assembler options if the user uses -mcpu=native, so if
- you make changes here, make them there also. */
-#undef ASM_CPU_SPEC
-#define ASM_CPU_SPEC \
-"%{!mcpu*: %{!maix64: \
- %{mpowerpc64: -mppc64} \
- %{maltivec: -m970} \
- %{!maltivec: %{!mpowerpc64: %(asm_default)}}}} \
-%{mcpu=native: %(asm_cpu_native)} \
-%{mcpu=power3: -m620} \
-%{mcpu=power4: -mpwr4} \
-%{mcpu=power5: -mpwr5} \
-%{mcpu=power5+: -mpwr5x} \
-%{mcpu=power6: -mpwr6} \
-%{mcpu=power6x: -mpwr6} \
-%{mcpu=power7: -mpwr7} \
-%{mcpu=power8: -mpwr8} \
-%{mcpu=power9: -mpwr9} \
-%{mcpu=powerpc: -mppc} \
-%{mcpu=rs64a: -mppc} \
-%{mcpu=603: -m603} \
-%{mcpu=603e: -m603} \
-%{mcpu=604: -m604} \
-%{mcpu=604e: -m604} \
-%{mcpu=620: -m620} \
-%{mcpu=630: -m620} \
-%{mcpu=970: -m970} \
-%{mcpu=G5: -m970}"
-
-#undef ASM_DEFAULT_SPEC
-#define ASM_DEFAULT_SPEC "-mppc"
-
-#undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define ("_AIX43"); \
- builtin_define ("_AIX51"); \
- builtin_define ("_AIX52"); \
- builtin_define ("_AIX53"); \
- TARGET_OS_AIX_CPP_BUILTINS (); \
- } \
- while (0)
-
-#undef CPP_SPEC
-#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} \
- %{ansi: -D_ANSI_C_SOURCE} \
- %{maix64: -D__64BIT__} \
- %{mpe: -I%R/usr/lpp/ppe.poe/include} \
- %{pthread: -D_THREAD_SAFE}"
-
-/* The GNU C++ standard library requires that these macros be
- defined. Synchronize with libstdc++ os_defines.h. */
-#undef CPLUSPLUS_CPP_SPEC
-#define CPLUSPLUS_CPP_SPEC \
- "-D_ALL_SOURCE \
- %{maix64: -D__64BIT__} \
- %{mpe: -I%R/usr/lpp/ppe.poe/include} \
- %{pthread: -D_THREAD_SAFE}"
-
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT 0
-
-#undef PROCESSOR_DEFAULT
-#define PROCESSOR_DEFAULT PROCESSOR_POWER5
-#undef PROCESSOR_DEFAULT64
-#define PROCESSOR_DEFAULT64 PROCESSOR_POWER5
-
-/* Define this macro as a C expression for the initializer of an
- array of string to tell the driver program which options are
- defaults for this target and thus do not need to be handled
- specially when using `MULTILIB_OPTIONS'.
-
- Do not define this macro if `MULTILIB_OPTIONS' is not defined in
- the target makefile fragment or if none of the options listed in
- `MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */
-
-#undef MULTILIB_DEFAULTS
-
-#undef LIB_SPEC
-#define LIB_SPEC "%{pg:-L%R/lib/profiled -L%R/usr/lib/profiled}\
- %{p:-L%R/lib/profiled -L%R/usr/lib/profiled}\
- %{!maix64:%{!shared:%{g*:-lg}}}\
- %{fprofile-arcs|fprofile-generate*|coverage:-lpthreads}\
- %{mpe:-L%R/usr/lpp/ppe.poe/lib -lmpi -lvtd}\
- %{pthread:-lpthreads} -lc"
-
-#undef LINK_SPEC
-#define LINK_SPEC "-bpT:0x10000000 -bpD:0x20000000 %{!r:-btextro}\
- %{static:-bnso %(link_syscalls) } %{shared:-bM:SRE %{!e:-bnoentry}}\
- %{!maix64:%{!shared:%{g*: %(link_libg) }}} %{maix64:-b64}\
- %{mpe:-binitfini:poe_remote_main}"
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "%{!shared:\
- %{maix64:%{pg:gcrt0_64%O%s}%{!pg:%{p:mcrt0_64%O%s}%{!p:crt0_64%O%s}}}\
- %{!maix64:\
- %{pthread:%{pg:gcrt0_r%O%s}%{!pg:%{p:mcrt0_r%O%s}%{!p:crt0_r%O%s}}}\
- %{!pthread:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}}}"
-
-/* AIX V5 typedefs ptrdiff_t as "long" while earlier releases used "int". */
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "long int"
-
-/* Type used for wchar_t, as a string used in a declaration. */
-#undef WCHAR_TYPE
-#define WCHAR_TYPE (!TARGET_64BIT ? "short unsigned int" : "unsigned int")
-
-/* Width of wchar_t in bits. */
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE (!TARGET_64BIT ? 16 : 32)
-
-/* AIX 4.2 and above provides initialization and finalization function
- support from linker command line. */
-#undef HAS_INIT_SECTION
-#define HAS_INIT_SECTION
-
-#undef LD_INIT_SWITCH
-#define LD_INIT_SWITCH "-binitfini"
-
-#ifndef _AIX52
-extern long long int atoll(const char *);
-#endif
-
-/* This target uses the aix64.opt file. */
-#define TARGET_USES_AIX64_OPT 1
-
-/* This target defines SUPPORTS_WEAK and TARGET_ASM_NAMED_SECTION,
- but does not have crtbegin/end. */
-
-#define TARGET_AIX_VERSION 53
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 8ee42ae..1ddf580 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -413,8 +413,7 @@
(use (match_operand:SI 1 "call_operand" "s"))])]
"TARGET_MACHO && (DEFAULT_ABI == ABI_DARWIN) && TARGET_32BIT"
"bl %z1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*restore_world"
[(match_parallel 0 "restore_world_operation"
@@ -441,8 +440,7 @@
(match_operand:V4SI 4 "altivec_register_operand" "v"))])]
"TARGET_ALTIVEC"
"bl %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*save_vregs_<mode>_r12"
[(match_parallel 0 "any_parallel_operand"
@@ -455,8 +453,7 @@
(match_operand:V4SI 4 "altivec_register_operand" "v"))])]
"TARGET_ALTIVEC"
"bl %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*restore_vregs_<mode>_r11"
[(match_parallel 0 "any_parallel_operand"
@@ -469,8 +466,7 @@
(match_operand:P 4 "short_cint_operand" "I"))))])]
"TARGET_ALTIVEC"
"bl %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*restore_vregs_<mode>_r12"
[(match_parallel 0 "any_parallel_operand"
@@ -483,8 +479,7 @@
(match_operand:P 4 "short_cint_operand" "I"))))])]
"TARGET_ALTIVEC"
"bl %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
;; Simple binary operations.
@@ -608,7 +603,7 @@
"vcmpbfp %0,%1,%2"
[(set_attr "type" "veccmp")])
-(define_insn "*altivec_eq<mode>"
+(define_insn "altivec_eq<mode>"
[(set (match_operand:VI2 0 "altivec_register_operand" "=v")
(eq:VI2 (match_operand:VI2 1 "altivec_register_operand" "v")
(match_operand:VI2 2 "altivec_register_operand" "v")))]
@@ -2047,8 +2042,7 @@
"@
vperm %0,%1,%2,%3
xxperm %x0,%x1,%x3"
- [(set_attr "type" "vecperm")
- (set_attr "length" "4")])
+ [(set_attr "type" "vecperm")])
(define_insn "altivec_vperm_v8hiv16qi"
[(set (match_operand:V16QI 0 "register_operand" "=v,?wo")
@@ -2060,8 +2054,7 @@
"@
vperm %0,%1,%2,%3
xxperm %x0,%x1,%x3"
- [(set_attr "type" "vecperm")
- (set_attr "length" "4")])
+ [(set_attr "type" "vecperm")])
(define_expand "altivec_vperm_<mode>_uns"
[(set (match_operand:VM 0 "register_operand")
@@ -2088,8 +2081,7 @@
"@
vperm %0,%1,%2,%3
xxperm %x0,%x1,%x3"
- [(set_attr "type" "vecperm")
- (set_attr "length" "4")])
+ [(set_attr "type" "vecperm")])
(define_expand "vec_permv16qi"
[(set (match_operand:V16QI 0 "register_operand")
@@ -2115,8 +2107,7 @@
"@
vpermr %0,%1,%2,%3
xxpermr %x0,%x1,%x3"
- [(set_attr "type" "vecperm")
- (set_attr "length" "4")])
+ [(set_attr "type" "vecperm")])
(define_insn "altivec_vrfip" ; ceil
[(set (match_operand:V4SF 0 "register_operand" "=v")
@@ -2313,7 +2304,7 @@
;; Compare vectors producing a vector result and a predicate, setting CR6 to
;; indicate a combined status
-(define_insn "*altivec_vcmpequ<VI_char>_p"
+(define_insn "altivec_vcmpequ<VI_char>_p"
[(set (reg:CC CR6_REGNO)
(unspec:CC [(eq:CC (match_operand:VI2 1 "register_operand" "v")
(match_operand:VI2 2 "register_operand" "v"))]
@@ -3273,8 +3264,7 @@
"@
vperm %0,%1,%2,%3
xxperm %x0,%x1,%x3"
- [(set_attr "type" "vecperm")
- (set_attr "length" "4")])
+ [(set_attr "type" "vecperm")])
(define_insn "vperm_v16qiv8hi"
[(set (match_operand:V8HI 0 "register_operand" "=v,?wo")
@@ -3286,8 +3276,7 @@
"@
vperm %0,%1,%2,%3
xxperm %x0,%x1,%x3"
- [(set_attr "type" "vecperm")
- (set_attr "length" "4")])
+ [(set_attr "type" "vecperm")])
(define_expand "vec_unpacku_hi_v16qi"
@@ -3862,8 +3851,7 @@
(clz:VI2 (match_operand:VI2 1 "register_operand" "v")))]
"TARGET_P8_VECTOR"
"vclz<wd> %0,%1"
- [(set_attr "length" "4")
- (set_attr "type" "vecsimple")])
+ [(set_attr "type" "vecsimple")])
;; Vector absolute difference unsigned
(define_expand "vadu<mode>3"
@@ -3889,8 +3877,7 @@
(ctz:VI2 (match_operand:VI2 1 "register_operand" "v")))]
"TARGET_P9_VECTOR"
"vctz<wd> %0,%1"
- [(set_attr "length" "4")
- (set_attr "type" "vecsimple")])
+ [(set_attr "type" "vecsimple")])
;; Vector population count
(define_insn "*p8v_popcount<mode>2"
@@ -3898,8 +3885,7 @@
(popcount:VI2 (match_operand:VI2 1 "register_operand" "v")))]
"TARGET_P8_VECTOR"
"vpopcnt<wd> %0,%1"
- [(set_attr "length" "4")
- (set_attr "type" "vecsimple")])
+ [(set_attr "type" "vecsimple")])
;; Vector parity
(define_insn "*p9v_parity<mode>2"
@@ -3907,8 +3893,7 @@
(parity:VParity (match_operand:VParity 1 "register_operand" "v")))]
"TARGET_P9_VECTOR"
"vprtyb<wd> %0,%1"
- [(set_attr "length" "4")
- (set_attr "type" "vecsimple")])
+ [(set_attr "type" "vecsimple")])
;; Vector Gather Bits by Bytes by Doubleword
(define_insn "p8v_vgbbd"
@@ -3917,8 +3902,7 @@
UNSPEC_VGBBD))]
"TARGET_P8_VECTOR"
"vgbbd %0,%1"
- [(set_attr "length" "4")
- (set_attr "type" "vecsimple")])
+ [(set_attr "type" "vecsimple")])
;; 128-bit binary integer arithmetic
@@ -3932,8 +3916,7 @@
(match_operand:V1TI 2 "register_operand" "v")))]
"TARGET_VADDUQM"
"vadduqm %0,%1,%2"
- [(set_attr "length" "4")
- (set_attr "type" "vecsimple")])
+ [(set_attr "type" "vecsimple")])
(define_insn "altivec_vaddcuq"
[(set (match_operand:V1TI 0 "register_operand" "=v")
@@ -3942,8 +3925,7 @@
UNSPEC_VADDCUQ))]
"TARGET_VADDUQM"
"vaddcuq %0,%1,%2"
- [(set_attr "length" "4")
- (set_attr "type" "vecsimple")])
+ [(set_attr "type" "vecsimple")])
(define_insn "altivec_vsubuqm"
[(set (match_operand:V1TI 0 "register_operand" "=v")
@@ -3951,8 +3933,7 @@
(match_operand:V1TI 2 "register_operand" "v")))]
"TARGET_VADDUQM"
"vsubuqm %0,%1,%2"
- [(set_attr "length" "4")
- (set_attr "type" "vecsimple")])
+ [(set_attr "type" "vecsimple")])
(define_insn "altivec_vsubcuq"
[(set (match_operand:V1TI 0 "register_operand" "=v")
@@ -3961,8 +3942,7 @@
UNSPEC_VSUBCUQ))]
"TARGET_VADDUQM"
"vsubcuq %0,%1,%2"
- [(set_attr "length" "4")
- (set_attr "type" "vecsimple")])
+ [(set_attr "type" "vecsimple")])
(define_insn "altivec_vaddeuqm"
[(set (match_operand:V1TI 0 "register_operand" "=v")
@@ -3972,8 +3952,7 @@
UNSPEC_VADDEUQM))]
"TARGET_VADDUQM"
"vaddeuqm %0,%1,%2,%3"
- [(set_attr "length" "4")
- (set_attr "type" "vecsimple")])
+ [(set_attr "type" "vecsimple")])
(define_insn "altivec_vaddecuq"
[(set (match_operand:V1TI 0 "register_operand" "=v")
@@ -3983,8 +3962,7 @@
UNSPEC_VADDECUQ))]
"TARGET_VADDUQM"
"vaddecuq %0,%1,%2,%3"
- [(set_attr "length" "4")
- (set_attr "type" "vecsimple")])
+ [(set_attr "type" "vecsimple")])
(define_insn "altivec_vsubeuqm"
[(set (match_operand:V1TI 0 "register_operand" "=v")
@@ -3994,8 +3972,7 @@
UNSPEC_VSUBEUQM))]
"TARGET_VADDUQM"
"vsubeuqm %0,%1,%2,%3"
- [(set_attr "length" "4")
- (set_attr "type" "vecsimple")])
+ [(set_attr "type" "vecsimple")])
(define_insn "altivec_vsubecuq"
[(set (match_operand:V1TI 0 "register_operand" "=v")
@@ -4005,8 +3982,7 @@
UNSPEC_VSUBECUQ))]
"TARGET_VADDUQM"
"vsubecuq %0,%1,%2,%3"
- [(set_attr "length" "4")
- (set_attr "type" "vecsimple")])
+ [(set_attr "type" "vecsimple")])
;; We use V2DI as the output type to simplify converting the permute
;; bits into an integer
@@ -4098,8 +4074,7 @@
(clobber (reg:CCFP CR6_REGNO))]
"TARGET_P8_VECTOR"
"bcd<bcd_add_sub>. %0,%1,%2,%3"
- [(set_attr "length" "4")
- (set_attr "type" "vecsimple")])
+ [(set_attr "type" "vecsimple")])
;; Use a floating point type (V2DFmode) for the compare to set CR6 so that we
;; can use the unordered test for BCD nans and add/subtracts that overflow. An
@@ -4117,8 +4092,7 @@
(clobber (match_scratch:V1TI 0 "=v"))]
"TARGET_P8_VECTOR"
"bcd<bcd_add_sub>. %0,%1,%2,%3"
- [(set_attr "length" "4")
- (set_attr "type" "vecsimple")])
+ [(set_attr "type" "vecsimple")])
(define_insn "*bcd<bcd_add_sub>_test2"
[(set (match_operand:V1TI 0 "register_operand" "=v")
@@ -4135,8 +4109,7 @@
(match_operand:V2DF 4 "zero_constant" "j")))]
"TARGET_P8_VECTOR"
"bcd<bcd_add_sub>. %0,%1,%2,%3"
- [(set_attr "length" "4")
- (set_attr "type" "vecsimple")])
+ [(set_attr "type" "vecsimple")])
(define_insn "darn_32"
[(set (match_operand:SI 0 "register_operand" "=r")
diff --git a/gcc/config/rs6000/darwin.h b/gcc/config/rs6000/darwin.h
index cea1aa9..6b0f18e 100644
--- a/gcc/config/rs6000/darwin.h
+++ b/gcc/config/rs6000/darwin.h
@@ -119,6 +119,13 @@ extern int darwin_emit_branch_islands;
mcpu=G5:ppc970; \
:ppc}}"
+/* We need to jam the crt to 10.5 for 10.6 (Rosetta) use. */
+#undef DARWIN_CRT1_SPEC
+#define DARWIN_CRT1_SPEC \
+ "%:version-compare(!> 10.5 mmacosx-version-min= -lcrt1.o) \
+ %:version-compare(>< 10.5 10.7 mmacosx-version-min= -lcrt1.10.5.o) \
+ %{fgnu-tm: -lcrttms.o}"
+
/* crt2.o is at least partially required for 10.3.x and earlier. */
#define DARWIN_CRT2_SPEC \
"%{!m64:%:version-compare(!> 10.4 mmacosx-version-min= crt2.o%s)}"
@@ -130,6 +137,12 @@ extern int darwin_emit_branch_islands;
{ "darwin_crt2", DARWIN_CRT2_SPEC }, \
{ "darwin_subarch", DARWIN_SUBARCH_SPEC },
+/* We need to jam the dylib crt to 10.5 for 10.6 (Rosetta) use. */
+#undef DARWIN_DYLIB1_SPEC
+#define DARWIN_DYLIB1_SPEC \
+ "%:version-compare(!> 10.5 mmacosx-version-min= -ldylib1.o) \
+ %:version-compare(>< 10.5 10.7 mmacosx-version-min= -ldylib1.10.5.o)"
+
/* Output a .machine directive. */
#undef TARGET_ASM_FILE_START
#define TARGET_ASM_FILE_START rs6000_darwin_file_start
diff --git a/gcc/config/rs6000/darwin.md b/gcc/config/rs6000/darwin.md
index 48fd5b96..37acb31 100644
--- a/gcc/config/rs6000/darwin.md
+++ b/gcc/config/rs6000/darwin.md
@@ -23,8 +23,7 @@ You should have received a copy of the GNU General Public License
(plus:DI (match_operand:DI 1 "gpc_reg_operand" "b")
(high:DI (match_operand 2 "" ""))))]
"TARGET_MACHO && TARGET_64BIT"
- "addis %0,%1,ha16(%2)"
- [(set_attr "length" "4")])
+ "addis %0,%1,ha16(%2)")
(define_insn "movdf_low_si"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f,!r")
@@ -72,8 +71,7 @@ You should have received a copy of the GNU General Public License
gcc_unreachable ();
}
}
- [(set_attr "type" "load")
- (set_attr "length" "4,4")])
+ [(set_attr "type" "load")])
(define_insn "movdf_low_st_si"
[(set (mem:DF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
@@ -81,8 +79,7 @@ You should have received a copy of the GNU General Public License
(match_operand:DF 0 "gpc_reg_operand" "f"))]
"TARGET_MACHO && TARGET_HARD_FLOAT && ! TARGET_64BIT"
"stfd %0,lo16(%2)(%1)"
- [(set_attr "type" "store")
- (set_attr "length" "4")])
+ [(set_attr "type" "store")])
(define_insn "movdf_low_st_di"
[(set (mem:DF (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b")
@@ -90,8 +87,7 @@ You should have received a copy of the GNU General Public License
(match_operand:DF 0 "gpc_reg_operand" "f"))]
"TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_64BIT"
"stfd %0,lo16(%2)(%1)"
- [(set_attr "type" "store")
- (set_attr "length" "4")])
+ [(set_attr "type" "store")])
(define_insn "movsf_low_si"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f,!r")
@@ -101,8 +97,7 @@ You should have received a copy of the GNU General Public License
"@
lfs %0,lo16(%2)(%1)
lwz %0,lo16(%2)(%1)"
- [(set_attr "type" "load")
- (set_attr "length" "4")])
+ [(set_attr "type" "load")])
(define_insn "movsf_low_di"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f,!r")
@@ -112,8 +107,7 @@ You should have received a copy of the GNU General Public License
"@
lfs %0,lo16(%2)(%1)
lwz %0,lo16(%2)(%1)"
- [(set_attr "type" "load")
- (set_attr "length" "4")])
+ [(set_attr "type" "load")])
(define_insn "movsf_low_st_si"
[(set (mem:SF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,b")
@@ -123,8 +117,7 @@ You should have received a copy of the GNU General Public License
"@
stfs %0,lo16(%2)(%1)
stw %0,lo16(%2)(%1)"
- [(set_attr "type" "store")
- (set_attr "length" "4")])
+ [(set_attr "type" "store")])
(define_insn "movsf_low_st_di"
[(set (mem:SF (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b,b")
@@ -134,8 +127,7 @@ You should have received a copy of the GNU General Public License
"@
stfs %0,lo16(%2)(%1)
stw %0,lo16(%2)(%1)"
- [(set_attr "type" "store")
- (set_attr "length" "4")])
+ [(set_attr "type" "store")])
;; 64-bit MachO load/store support
(define_insn "movdi_low"
@@ -146,8 +138,7 @@ You should have received a copy of the GNU General Public License
"@
ld %0,lo16(%2)(%1)
lfd %0,lo16(%2)(%1)"
- [(set_attr "type" "load")
- (set_attr "length" "4")])
+ [(set_attr "type" "load")])
(define_insn "movsi_low_st"
[(set (mem:SI (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
@@ -155,8 +146,7 @@ You should have received a copy of the GNU General Public License
(match_operand:SI 0 "gpc_reg_operand" "r"))]
"TARGET_MACHO && ! TARGET_64BIT"
"stw %0,lo16(%2)(%1)"
- [(set_attr "type" "store")
- (set_attr "length" "4")])
+ [(set_attr "type" "store")])
(define_insn "movdi_low_st"
[(set (mem:DI (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b,b")
@@ -166,8 +156,7 @@ You should have received a copy of the GNU General Public License
"@
std %0,lo16(%2)(%1)
stfd %0,lo16(%2)(%1)"
- [(set_attr "type" "store")
- (set_attr "length" "4")])
+ [(set_attr "type" "store")])
;; Mach-O PIC trickery.
(define_expand "macho_high"
@@ -263,8 +252,7 @@ You should have received a copy of the GNU General Public License
return "bcl 20,31,%0\n%0:";
}
[(set_attr "type" "branch")
- (set_attr "cannot_copy" "yes")
- (set_attr "length" "4")])
+ (set_attr "cannot_copy" "yes")])
(define_insn "load_macho_picbase_di"
[(set (reg:DI LR_REGNO)
@@ -280,8 +268,7 @@ You should have received a copy of the GNU General Public License
return "bcl 20,31,%0\n%0:";
}
[(set_attr "type" "branch")
- (set_attr "cannot_copy" "yes")
- (set_attr "length" "4")])
+ (set_attr "cannot_copy" "yes")])
(define_expand "macho_correct_pic"
[(set (match_operand 0 "")
@@ -416,8 +403,7 @@ You should have received a copy of the GNU General Public License
return "bcl 20,31,%0\n%0:";
}
[(set_attr "type" "branch")
- (set_attr "cannot_copy" "yes")
- (set_attr "length" "4")])
+ (set_attr "cannot_copy" "yes")])
(define_insn "reload_macho_picbase_di"
[(set (reg:DI LR_REGNO)
@@ -440,8 +426,7 @@ You should have received a copy of the GNU General Public License
return "bcl 20,31,%0\n%0:";
}
[(set_attr "type" "branch")
- (set_attr "cannot_copy" "yes")
- (set_attr "length" "4")])
+ (set_attr "cannot_copy" "yes")])
;; We need to restore the PIC register, at the site of nonlocal label.
diff --git a/gcc/config/rs6000/dfp.md b/gcc/config/rs6000/dfp.md
index cd15aa8..9bc98f9 100644
--- a/gcc/config/rs6000/dfp.md
+++ b/gcc/config/rs6000/dfp.md
@@ -37,8 +37,7 @@
|| gpc_reg_operand (operands[1], SDmode))
&& TARGET_HARD_FLOAT"
"stfd%U0%X0 %1,%0"
- [(set_attr "type" "fpstore")
- (set_attr "length" "4")])
+ [(set_attr "type" "fpstore")])
(define_insn "movsd_load"
[(set (match_operand:SD 0 "nonimmediate_operand" "=f")
@@ -48,8 +47,7 @@
|| gpc_reg_operand (operands[1], DDmode))
&& TARGET_HARD_FLOAT"
"lfd%U1%X1 %0,%1"
- [(set_attr "type" "fpload")
- (set_attr "length" "4")])
+ [(set_attr "type" "fpload")])
;; Hardware support for decimal floating point operations.
diff --git a/gcc/config/rs6000/emmintrin.h b/gcc/config/rs6000/emmintrin.h
index 412ece7..aed1625 100644
--- a/gcc/config/rs6000/emmintrin.h
+++ b/gcc/config/rs6000/emmintrin.h
@@ -85,6 +85,9 @@ typedef double __m128d __attribute__ ((__vector_size__ (16), __may_alias__));
typedef long long __m128i_u __attribute__ ((__vector_size__ (16), __may_alias__, __aligned__ (1)));
typedef double __m128d_u __attribute__ ((__vector_size__ (16), __may_alias__, __aligned__ (1)));
+/* Define two value permute mask */
+#define _MM_SHUFFLE2(x,y) (((x) << 1) | (y))
+
/* Create a vector with element 0 as F and the rest zero. */
extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_set_sd (double __F)
diff --git a/gcc/config/rs6000/htm.md b/gcc/config/rs6000/htm.md
index 44a52c5..96c8288 100644
--- a/gcc/config/rs6000/htm.md
+++ b/gcc/config/rs6000/htm.md
@@ -72,8 +72,7 @@
(set (match_operand:BLK 2) (unspec:BLK [(match_dup 2)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"tabort. %0"
- [(set_attr "type" "htmsimple")
- (set_attr "length" "4")])
+ [(set_attr "type" "htmsimple")])
(define_expand "tabort<wd>c"
[(parallel
@@ -98,8 +97,7 @@
(set (match_operand:BLK 4) (unspec:BLK [(match_dup 4)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"tabort<wd>c. %0,%1,%2"
- [(set_attr "type" "htmsimple")
- (set_attr "length" "4")])
+ [(set_attr "type" "htmsimple")])
(define_expand "tabort<wd>ci"
[(parallel
@@ -124,8 +122,7 @@
(set (match_operand:BLK 4) (unspec:BLK [(match_dup 4)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"tabort<wd>ci. %0,%1,%2"
- [(set_attr "type" "htmsimple")
- (set_attr "length" "4")])
+ [(set_attr "type" "htmsimple")])
(define_expand "tbegin"
[(parallel
@@ -146,8 +143,7 @@
(set (match_operand:BLK 2) (unspec:BLK [(match_dup 2)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"tbegin. %0"
- [(set_attr "type" "htm")
- (set_attr "length" "4")])
+ [(set_attr "type" "htm")])
(define_expand "tcheck"
[(parallel
@@ -166,8 +162,7 @@
(set (match_operand:BLK 1) (unspec:BLK [(match_dup 1)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"tcheck %0"
- [(set_attr "type" "htm")
- (set_attr "length" "4")])
+ [(set_attr "type" "htm")])
(define_expand "tend"
[(parallel
@@ -188,8 +183,7 @@
(set (match_operand:BLK 2) (unspec:BLK [(match_dup 2)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"tend. %0"
- [(set_attr "type" "htm")
- (set_attr "length" "4")])
+ [(set_attr "type" "htm")])
(define_expand "trechkpt"
[(parallel
@@ -208,8 +202,7 @@
(set (match_operand:BLK 1) (unspec:BLK [(match_dup 1)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"trechkpt."
- [(set_attr "type" "htmsimple")
- (set_attr "length" "4")])
+ [(set_attr "type" "htmsimple")])
(define_expand "treclaim"
[(parallel
@@ -230,8 +223,7 @@
(set (match_operand:BLK 2) (unspec:BLK [(match_dup 2)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"treclaim. %0"
- [(set_attr "type" "htmsimple")
- (set_attr "length" "4")])
+ [(set_attr "type" "htmsimple")])
(define_expand "tsr"
[(parallel
@@ -252,8 +244,7 @@
(set (match_operand:BLK 2) (unspec:BLK [(match_dup 2)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"tsr. %0"
- [(set_attr "type" "htmsimple")
- (set_attr "length" "4")])
+ [(set_attr "type" "htmsimple")])
(define_expand "ttest"
[(parallel
@@ -272,8 +263,7 @@
(set (match_operand:BLK 1) (unspec:BLK [(match_dup 1)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"tabortwci. 0,1,0"
- [(set_attr "type" "htmsimple")
- (set_attr "length" "4")])
+ [(set_attr "type" "htmsimple")])
(define_insn "htm_mfspr_<mode>"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
@@ -282,8 +272,7 @@
UNSPECV_HTM_MFSPR))]
"TARGET_HTM"
"mfspr %0,%1";
- [(set_attr "type" "htm")
- (set_attr "length" "4")])
+ [(set_attr "type" "htm")])
(define_insn "htm_mtspr_<mode>"
[(set (match_operand:GPR 2 "htm_spr_reg_operand" "")
@@ -292,5 +281,4 @@
UNSPECV_HTM_MTSPR))]
"TARGET_HTM"
"mtspr %1,%0";
- [(set_attr "type" "htm")
- (set_attr "length" "4")])
+ [(set_attr "type" "htm")])
diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c
index f37f0b1..4d5e3c2 100644
--- a/gcc/config/rs6000/rs6000-c.c
+++ b/gcc/config/rs6000/rs6000-c.c
@@ -220,21 +220,23 @@ rs6000_macro_to_expand (cpp_reader *pfile, const cpp_token *tok)
else if (ident && (ident != C_CPP_HASHNODE (__vector_keyword)))
{
enum rid rid_code = (enum rid)(ident->rid_code);
- enum node_type itype = ident->type;
+ bool is_macro = cpp_macro_p (ident);
+
/* If there is a function-like macro, check if it is going to be
invoked with or without arguments. Without following ( treat
it like non-macro, otherwise the following cpp_get_token eats
what should be preserved. */
- if (itype == NT_MACRO && cpp_fun_like_macro_p (ident))
+ if (is_macro && cpp_fun_like_macro_p (ident))
{
int idx2 = idx;
do
tok = cpp_peek_token (pfile, idx2++);
while (tok->type == CPP_PADDING);
if (tok->type != CPP_OPEN_PAREN)
- itype = NT_VOID;
+ is_macro = false;
}
- if (itype == NT_MACRO)
+
+ if (is_macro)
{
do
(void) cpp_get_token (pfile);
diff --git a/gcc/config/rs6000/rs6000-opts.h b/gcc/config/rs6000/rs6000-opts.h
index bd0eea3..1212d11 100644
--- a/gcc/config/rs6000/rs6000-opts.h
+++ b/gcc/config/rs6000/rs6000-opts.h
@@ -137,8 +137,7 @@ enum rs6000_vector {
VECTOR_NONE, /* Type is not a vector or not supported */
VECTOR_ALTIVEC, /* Use altivec for vector processing */
VECTOR_VSX, /* Use VSX for vector processing */
- VECTOR_P8_VECTOR, /* Use ISA 2.07 VSX for vector processing */
- VECTOR_OTHER /* Some other vector unit */
+ VECTOR_P8_VECTOR /* Use ISA 2.07 VSX for vector processing */
};
/* Where to get the canary for the stack protector. */
diff --git a/gcc/config/rs6000/rs6000-string.c b/gcc/config/rs6000/rs6000-string.c
index f9dd54e..ff04145 100644
--- a/gcc/config/rs6000/rs6000-string.c
+++ b/gcc/config/rs6000/rs6000-string.c
@@ -157,6 +157,33 @@ do_load_for_compare (rtx reg, rtx mem, machine_mode mode)
{
switch (GET_MODE (reg))
{
+ case E_V16QImode:
+ switch (mode)
+ {
+ case E_V16QImode:
+ if (!BYTES_BIG_ENDIAN)
+ {
+ if (TARGET_P9_VECTOR)
+ emit_insn (gen_vsx_ld_elemrev_v16qi_internal (reg, mem));
+ else
+ {
+ rtx reg_v2di = simplify_gen_subreg (V2DImode, reg,
+ V16QImode, 0);
+ gcc_assert (MEM_P (mem));
+ rtx addr = XEXP (mem, 0);
+ rtx mem_v2di = gen_rtx_MEM (V2DImode, addr);
+ MEM_COPY_ATTRIBUTES (mem_v2di, mem);
+ set_mem_size (mem, GET_MODE_SIZE (V2DImode));
+ emit_insn (gen_vsx_ld_elemrev_v2di (reg_v2di, mem_v2di));
+ }
+ }
+ else
+ emit_insn (gen_vsx_movv2di_64bit (reg, mem));
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ break;
case E_DImode:
switch (mode)
{
@@ -227,6 +254,12 @@ do_load_for_compare (rtx reg, rtx mem, machine_mode mode)
gcc_unreachable ();
}
break;
+
+ case E_QImode:
+ gcc_assert (mode == E_QImode);
+ emit_move_insn (reg, mem);
+ break;
+
default:
gcc_unreachable ();
break;
@@ -238,13 +271,11 @@ do_load_for_compare (rtx reg, rtx mem, machine_mode mode)
OFFSET is the current read offset from the beginning of the block.
BYTES is the number of bytes remaining to be read.
- ALIGN is the minimum alignment of the memory blocks being compared in bytes.
- WORD_MODE_OK indicates using WORD_MODE is allowed, else SImode is
- the largest allowable mode. */
+ ALIGN is the minimum alignment of the memory blocks being compared in bytes. */
static machine_mode
select_block_compare_mode (unsigned HOST_WIDE_INT offset,
unsigned HOST_WIDE_INT bytes,
- unsigned HOST_WIDE_INT align, bool word_mode_ok)
+ unsigned HOST_WIDE_INT align)
{
/* First see if we can do a whole load unit
as that will be more efficient than a larger load + shift. */
@@ -257,6 +288,11 @@ select_block_compare_mode (unsigned HOST_WIDE_INT offset,
/* The most we can read without potential page crossing. */
unsigned HOST_WIDE_INT maxread = ROUND_UP (bytes, align);
+ /* If we have an LE target without ldbrx and word_mode is DImode,
+ then we must avoid using word_mode. */
+ int word_mode_ok = !(!BYTES_BIG_ENDIAN && !TARGET_LDBRX
+ && word_mode == DImode);
+
if (word_mode_ok && bytes >= UNITS_PER_WORD)
return word_mode;
else if (bytes == GET_MODE_SIZE (SImode))
@@ -1382,16 +1418,11 @@ expand_block_compare (rtx operands[])
else
cond = gen_reg_rtx (CCmode);
- /* If we have an LE target without ldbrx and word_mode is DImode,
- then we must avoid using word_mode. */
- int word_mode_ok = !(!BYTES_BIG_ENDIAN && !TARGET_LDBRX
- && word_mode == DImode);
-
/* Strategy phase. How many ops will this take and should we expand it? */
unsigned HOST_WIDE_INT offset = 0;
machine_mode load_mode =
- select_block_compare_mode (offset, bytes, base_align, word_mode_ok);
+ select_block_compare_mode (offset, bytes, base_align);
unsigned int load_mode_size = GET_MODE_SIZE (load_mode);
/* We don't want to generate too much code. The loop code can take
@@ -1445,8 +1476,7 @@ expand_block_compare (rtx operands[])
while (bytes > 0)
{
unsigned int align = compute_current_alignment (base_align, offset);
- load_mode = select_block_compare_mode (offset, bytes,
- align, word_mode_ok);
+ load_mode = select_block_compare_mode (offset, bytes, align);
load_mode_size = GET_MODE_SIZE (load_mode);
if (bytes >= load_mode_size)
cmp_bytes = load_mode_size;
@@ -1698,6 +1728,363 @@ expand_strncmp_align_check (rtx strncmp_label, rtx src_addr, HOST_WIDE_INT bytes
LABEL_NUSES (strncmp_label) += 1;
}
+/* Generate the sequence of compares for strcmp/strncmp using gpr instructions.
+ BYTES_TO_COMPARE is the number of bytes to be compared.
+ BASE_ALIGN is the smaller of the alignment of the two strings.
+ ORIG_SRC1 is the unmodified rtx for the first string.
+ ORIG_SRC2 is the unmodified rtx for the second string.
+ TMP_REG_SRC1 is the register for loading the first string.
+ TMP_REG_SRC2 is the register for loading the second string.
+ RESULT_REG is the rtx for the result register.
+ EQUALITY_COMPARE_REST is a flag to indicate we need to make a cleanup call
+ to strcmp/strncmp if we have equality at the end of the inline comparison.
+ P_CLEANUP_LABEL is a pointer to rtx for a label we generate if we need code
+ to clean up and generate the final comparison result.
+ FINAL_MOVE_LABEL is rtx for a label we can branch to when we can just
+ set the final result. */
+static void
+expand_strncmp_gpr_sequence (unsigned HOST_WIDE_INT bytes_to_compare,
+ unsigned int base_align,
+ rtx orig_src1, rtx orig_src2,
+ rtx tmp_reg_src1, rtx tmp_reg_src2, rtx result_reg,
+ bool equality_compare_rest, rtx *p_cleanup_label,
+ rtx final_move_label)
+{
+ unsigned int word_mode_size = GET_MODE_SIZE (word_mode);
+ machine_mode load_mode;
+ unsigned int load_mode_size;
+ unsigned HOST_WIDE_INT cmp_bytes = 0;
+ unsigned HOST_WIDE_INT offset = 0;
+ rtx src1_addr = force_reg (Pmode, XEXP (orig_src1, 0));
+ rtx src2_addr = force_reg (Pmode, XEXP (orig_src2, 0));
+ gcc_assert (p_cleanup_label != NULL);
+ rtx cleanup_label = *p_cleanup_label;
+
+ while (bytes_to_compare > 0)
+ {
+ /* GPR compare sequence:
+ check each 8B with: ld/ld cmpd bne
+ If equal, use rldicr/cmpb to check for zero byte.
+ cleanup code at end:
+ cmpb get byte that differs
+ cmpb look for zero byte
+ orc combine
+ cntlzd get bit of first zero/diff byte
+ subfic convert for rldcl use
+ rldcl rldcl extract diff/zero byte
+ subf subtract for final result
+
+ The last compare can branch around the cleanup code if the
+ result is zero because the strings are exactly equal. */
+
+ unsigned int align = compute_current_alignment (base_align, offset);
+ load_mode = select_block_compare_mode (offset, bytes_to_compare, align);
+ load_mode_size = GET_MODE_SIZE (load_mode);
+ if (bytes_to_compare >= load_mode_size)
+ cmp_bytes = load_mode_size;
+ else if (TARGET_EFFICIENT_OVERLAPPING_UNALIGNED)
+ {
+ /* Move this load back so it doesn't go past the end.
+ P8/P9 can do this efficiently. */
+ unsigned int extra_bytes = load_mode_size - bytes_to_compare;
+ cmp_bytes = bytes_to_compare;
+ if (extra_bytes < offset)
+ {
+ offset -= extra_bytes;
+ cmp_bytes = load_mode_size;
+ bytes_to_compare = cmp_bytes;
+ }
+ }
+ else
+ /* P7 and earlier can't do the overlapping load trick fast,
+ so this forces a non-overlapping load and a shift to get
+ rid of the extra bytes. */
+ cmp_bytes = bytes_to_compare;
+
+ rtx addr1 = gen_rtx_PLUS (Pmode, src1_addr, GEN_INT (offset));
+ do_load_for_compare_from_addr (load_mode, tmp_reg_src1, addr1, orig_src1);
+ rtx addr2 = gen_rtx_PLUS (Pmode, src2_addr, GEN_INT (offset));
+ do_load_for_compare_from_addr (load_mode, tmp_reg_src2, addr2, orig_src2);
+
+ /* We must always left-align the data we read, and
+ clear any bytes to the right that are beyond the string.
+ Otherwise the cmpb sequence won't produce the correct
+ results. The beginning of the compare will be done
+ with word_mode so will not have any extra shifts or
+ clear rights. */
+
+ if (load_mode_size < word_mode_size)
+ {
+ /* Rotate left first. */
+ rtx sh = GEN_INT (BITS_PER_UNIT * (word_mode_size - load_mode_size));
+ do_rotl3 (tmp_reg_src1, tmp_reg_src1, sh);
+ do_rotl3 (tmp_reg_src2, tmp_reg_src2, sh);
+ }
+
+ if (cmp_bytes < word_mode_size)
+ {
+ /* Now clear right. This plus the rotate can be
+ turned into a rldicr instruction. */
+ HOST_WIDE_INT mb = BITS_PER_UNIT * (word_mode_size - cmp_bytes);
+ rtx mask = GEN_INT (HOST_WIDE_INT_M1U << mb);
+ do_and3 (tmp_reg_src1, tmp_reg_src1, mask);
+ do_and3 (tmp_reg_src2, tmp_reg_src2, mask);
+ }
+
+ /* Cases to handle. A and B are chunks of the two strings.
+ 1: Not end of comparison:
+ A != B: branch to cleanup code to compute result.
+ A == B: check for 0 byte, next block if not found.
+ 2: End of the inline comparison:
+ A != B: branch to cleanup code to compute result.
+ A == B: check for 0 byte, call strcmp/strncmp
+ 3: compared requested N bytes:
+ A == B: branch to result 0.
+ A != B: cleanup code to compute result. */
+
+ unsigned HOST_WIDE_INT remain = bytes_to_compare - cmp_bytes;
+
+ rtx dst_label;
+ if (remain > 0 || equality_compare_rest)
+ {
+ /* Branch to cleanup code, otherwise fall through to do
+ more compares. */
+ if (!cleanup_label)
+ cleanup_label = gen_label_rtx ();
+ dst_label = cleanup_label;
+ }
+ else
+ /* Branch to end and produce result of 0. */
+ dst_label = final_move_label;
+
+ rtx lab_ref = gen_rtx_LABEL_REF (VOIDmode, dst_label);
+ rtx cond = gen_reg_rtx (CCmode);
+
+ /* Always produce the 0 result, it is needed if
+ cmpb finds a 0 byte in this chunk. */
+ rtx tmp = gen_rtx_MINUS (word_mode, tmp_reg_src1, tmp_reg_src2);
+ rs6000_emit_dot_insn (result_reg, tmp, 1, cond);
+
+ rtx cmp_rtx;
+ if (remain == 0 && !equality_compare_rest)
+ cmp_rtx = gen_rtx_EQ (VOIDmode, cond, const0_rtx);
+ else
+ cmp_rtx = gen_rtx_NE (VOIDmode, cond, const0_rtx);
+
+ rtx ifelse = gen_rtx_IF_THEN_ELSE (VOIDmode, cmp_rtx,
+ lab_ref, pc_rtx);
+ rtx j = emit_jump_insn (gen_rtx_SET (pc_rtx, ifelse));
+ JUMP_LABEL (j) = dst_label;
+ LABEL_NUSES (dst_label) += 1;
+
+ if (remain > 0 || equality_compare_rest)
+ {
+ /* Generate a cmpb to test for a 0 byte and branch
+ to final result if found. */
+ rtx cmpb_zero = gen_reg_rtx (word_mode);
+ rtx lab_ref_fin = gen_rtx_LABEL_REF (VOIDmode, final_move_label);
+ rtx condz = gen_reg_rtx (CCmode);
+ rtx zero_reg = gen_reg_rtx (word_mode);
+ emit_move_insn (zero_reg, GEN_INT (0));
+ do_cmpb3 (cmpb_zero, tmp_reg_src1, zero_reg);
+
+ if (cmp_bytes < word_mode_size)
+ {
+ /* Don't want to look at zero bytes past end. */
+ HOST_WIDE_INT mb =
+ BITS_PER_UNIT * (word_mode_size - cmp_bytes);
+ rtx mask = GEN_INT (HOST_WIDE_INT_M1U << mb);
+ do_and3 (cmpb_zero, cmpb_zero, mask);
+ }
+
+ emit_move_insn (condz, gen_rtx_COMPARE (CCmode, cmpb_zero, zero_reg));
+ rtx cmpnz_rtx = gen_rtx_NE (VOIDmode, condz, const0_rtx);
+ rtx ifelse = gen_rtx_IF_THEN_ELSE (VOIDmode, cmpnz_rtx,
+ lab_ref_fin, pc_rtx);
+ rtx j2 = emit_jump_insn (gen_rtx_SET (pc_rtx, ifelse));
+ JUMP_LABEL (j2) = final_move_label;
+ LABEL_NUSES (final_move_label) += 1;
+
+ }
+
+ offset += cmp_bytes;
+ bytes_to_compare -= cmp_bytes;
+ }
+
+ *p_cleanup_label = cleanup_label;
+ return;
+}
+
+/* Generate the sequence of compares for strcmp/strncmp using vec/vsx
+ instructions.
+
+ BYTES_TO_COMPARE is the number of bytes to be compared.
+ ORIG_SRC1 is the unmodified rtx for the first string.
+ ORIG_SRC2 is the unmodified rtx for the second string.
+ S1ADDR is the register to use for the base address of the first string.
+ S2ADDR is the register to use for the base address of the second string.
+ OFF_REG is the register to use for the string offset for loads.
+ S1DATA is the register for loading the first string.
+ S2DATA is the register for loading the second string.
+ VEC_RESULT is the rtx for the vector result indicating the byte difference.
+ EQUALITY_COMPARE_REST is a flag to indicate we need to make a cleanup call
+ to strcmp/strncmp if we have equality at the end of the inline comparison.
+ P_CLEANUP_LABEL is a pointer to rtx for a label we generate if we need code to clean up
+ and generate the final comparison result.
+ FINAL_MOVE_LABEL is rtx for a label we can branch to when we can just
+ set the final result. */
+static void
+expand_strncmp_vec_sequence (unsigned HOST_WIDE_INT bytes_to_compare,
+ rtx orig_src1, rtx orig_src2,
+ rtx s1addr, rtx s2addr, rtx off_reg,
+ rtx s1data, rtx s2data,
+ rtx vec_result, bool equality_compare_rest,
+ rtx *p_cleanup_label, rtx final_move_label)
+{
+ machine_mode load_mode;
+ unsigned int load_mode_size;
+ unsigned HOST_WIDE_INT cmp_bytes = 0;
+ unsigned HOST_WIDE_INT offset = 0;
+
+ gcc_assert (p_cleanup_label != NULL);
+ rtx cleanup_label = *p_cleanup_label;
+
+ emit_move_insn (s1addr, force_reg (Pmode, XEXP (orig_src1, 0)));
+ emit_move_insn (s2addr, force_reg (Pmode, XEXP (orig_src2, 0)));
+
+ unsigned int i;
+ rtx zr[16];
+ for (i = 0; i < 16; i++)
+ zr[i] = GEN_INT (0);
+ rtvec zv = gen_rtvec_v (16, zr);
+ rtx zero_reg = gen_reg_rtx (V16QImode);
+ rs6000_expand_vector_init (zero_reg, gen_rtx_PARALLEL (V16QImode, zv));
+
+ while (bytes_to_compare > 0)
+ {
+ /* VEC/VSX compare sequence for P8:
+ check each 16B with:
+ lxvd2x 32,28,8
+ lxvd2x 33,29,8
+ vcmpequb 2,0,1 # compare strings
+ vcmpequb 4,0,3 # compare w/ 0
+ xxlorc 37,36,34 # first FF byte is either mismatch or end of string
+ vcmpequb. 7,5,3 # reg 7 contains 0
+ bnl 6,.Lmismatch
+
+ For the P8 LE case, we use lxvd2x and compare full 16 bytes
+ but then use use vgbbd and a shift to get two bytes with the
+ information we need in the correct order.
+
+ VEC/VSX compare sequence if TARGET_P9_VECTOR:
+ lxvb16x/lxvb16x # load 16B of each string
+ vcmpnezb. # produces difference location or zero byte location
+ bne 6,.Lmismatch
+
+ Use the overlapping compare trick for the last block if it is
+ less than 16 bytes.
+ */
+
+ load_mode = V16QImode;
+ load_mode_size = GET_MODE_SIZE (load_mode);
+
+ if (bytes_to_compare >= load_mode_size)
+ cmp_bytes = load_mode_size;
+ else
+ {
+ /* Move this load back so it doesn't go past the end. P8/P9
+ can do this efficiently. This is never called with less
+ than 16 bytes so we should always be able to do this. */
+ unsigned int extra_bytes = load_mode_size - bytes_to_compare;
+ cmp_bytes = bytes_to_compare;
+ gcc_assert (offset > extra_bytes);
+ offset -= extra_bytes;
+ cmp_bytes = load_mode_size;
+ bytes_to_compare = cmp_bytes;
+ }
+
+ /* The offset currently used is always kept in off_reg so that the
+ cleanup code on P8 can use it to extract the differing byte. */
+ emit_move_insn (off_reg, GEN_INT (offset));
+
+ rtx addr1 = gen_rtx_PLUS (Pmode, s1addr, off_reg);
+ do_load_for_compare_from_addr (load_mode, s1data, addr1, orig_src1);
+ rtx addr2 = gen_rtx_PLUS (Pmode, s2addr, off_reg);
+ do_load_for_compare_from_addr (load_mode, s2data, addr2, orig_src2);
+
+ /* Cases to handle. A and B are chunks of the two strings.
+ 1: Not end of comparison:
+ A != B: branch to cleanup code to compute result.
+ A == B: next block
+ 2: End of the inline comparison:
+ A != B: branch to cleanup code to compute result.
+ A == B: call strcmp/strncmp
+ 3: compared requested N bytes:
+ A == B: branch to result 0.
+ A != B: cleanup code to compute result. */
+
+ unsigned HOST_WIDE_INT remain = bytes_to_compare - cmp_bytes;
+
+ if (TARGET_P9_VECTOR)
+ emit_insn (gen_vcmpnezb_p (vec_result, s1data, s2data));
+ else
+ {
+ /* Emit instructions to do comparison and zero check. */
+ rtx cmp_res = gen_reg_rtx (load_mode);
+ rtx cmp_zero = gen_reg_rtx (load_mode);
+ rtx cmp_combined = gen_reg_rtx (load_mode);
+ emit_insn (gen_altivec_eqv16qi (cmp_res, s1data, s2data));
+ emit_insn (gen_altivec_eqv16qi (cmp_zero, s1data, zero_reg));
+ emit_insn (gen_orcv16qi3 (vec_result, cmp_zero, cmp_res));
+ emit_insn (gen_altivec_vcmpequb_p (cmp_combined, vec_result, zero_reg));
+ }
+
+ bool branch_to_cleanup = (remain > 0 || equality_compare_rest);
+ rtx cr6 = gen_rtx_REG (CCmode, CR6_REGNO);
+ rtx dst_label;
+ rtx cmp_rtx;
+ if (branch_to_cleanup)
+ {
+ /* Branch to cleanup code, otherwise fall through to do more
+ compares. P8 and P9 use different CR bits because on P8
+ we are looking at the result of a comparsion vs a
+ register of zeroes so the all-true condition means no
+ difference or zero was found. On P9, vcmpnezb sets a byte
+ to 0xff if there is a mismatch or zero, so the all-false
+ condition indicates we found no difference or zero. */
+ if (!cleanup_label)
+ cleanup_label = gen_label_rtx ();
+ dst_label = cleanup_label;
+ if (TARGET_P9_VECTOR)
+ cmp_rtx = gen_rtx_NE (VOIDmode, cr6, const0_rtx);
+ else
+ cmp_rtx = gen_rtx_GE (VOIDmode, cr6, const0_rtx);
+ }
+ else
+ {
+ /* Branch to final return or fall through to cleanup,
+ result is already set to 0. */
+ dst_label = final_move_label;
+ if (TARGET_P9_VECTOR)
+ cmp_rtx = gen_rtx_EQ (VOIDmode, cr6, const0_rtx);
+ else
+ cmp_rtx = gen_rtx_LT (VOIDmode, cr6, const0_rtx);
+ }
+
+ rtx lab_ref = gen_rtx_LABEL_REF (VOIDmode, dst_label);
+ rtx ifelse = gen_rtx_IF_THEN_ELSE (VOIDmode, cmp_rtx,
+ lab_ref, pc_rtx);
+ rtx j2 = emit_jump_insn (gen_rtx_SET (pc_rtx, ifelse));
+ JUMP_LABEL (j2) = dst_label;
+ LABEL_NUSES (dst_label) += 1;
+
+ offset += cmp_bytes;
+ bytes_to_compare -= cmp_bytes;
+ }
+ *p_cleanup_label = cleanup_label;
+ return;
+}
+
/* Generate the final sequence that identifies the differing
byte and generates the final result, taking into account
zero bytes:
@@ -1768,6 +2155,96 @@ emit_final_str_compare_gpr (rtx str1, rtx str2, rtx result)
return;
}
+/* Generate the final sequence that identifies the differing
+ byte and generates the final result, taking into account
+ zero bytes:
+
+ P8:
+ vgbbd 0,0
+ vsldoi 0,0,0,9
+ mfvsrd 9,32
+ addi 10,9,-1 # count trailing zero bits
+ andc 9,10,9
+ popcntd 9,9
+ lbzx 10,28,9 # use that offset to load differing byte
+ lbzx 3,29,9
+ subf 3,3,10 # subtract for final result
+
+ P9:
+ vclzlsbb # counts trailing bytes with lsb=0
+ vextublx # extract differing byte
+
+ STR1 is the reg rtx for data from string 1.
+ STR2 is the reg rtx for data from string 2.
+ RESULT is the reg rtx for the comparison result.
+ S1ADDR is the register to use for the base address of the first string.
+ S2ADDR is the register to use for the base address of the second string.
+ ORIG_SRC1 is the unmodified rtx for the first string.
+ ORIG_SRC2 is the unmodified rtx for the second string.
+ OFF_REG is the register to use for the string offset for loads.
+ VEC_RESULT is the rtx for the vector result indicating the byte difference.
+ */
+
+static void
+emit_final_str_compare_vec (rtx str1, rtx str2, rtx result,
+ rtx s1addr, rtx s2addr,
+ rtx orig_src1, rtx orig_src2,
+ rtx off_reg, rtx vec_result)
+{
+ if (TARGET_P9_VECTOR)
+ {
+ rtx diffix = gen_reg_rtx (SImode);
+ rtx chr1 = gen_reg_rtx (SImode);
+ rtx chr2 = gen_reg_rtx (SImode);
+ rtx chr1_di = simplify_gen_subreg (DImode, chr1, SImode, 0);
+ rtx chr2_di = simplify_gen_subreg (DImode, chr2, SImode, 0);
+ emit_insn (gen_vclzlsbb_v16qi (diffix, vec_result));
+ emit_insn (gen_vextublx (chr1, diffix, str1));
+ emit_insn (gen_vextublx (chr2, diffix, str2));
+ do_sub3 (result, chr1_di, chr2_di);
+ }
+ else
+ {
+ rtx diffix = gen_reg_rtx (DImode);
+ rtx result_gbbd = gen_reg_rtx (V16QImode);
+ /* Since each byte of the input is either 00 or FF, the bytes in
+ dw0 and dw1 after vgbbd are all identical to each other. */
+ emit_insn (gen_p8v_vgbbd (result_gbbd, vec_result));
+ /* For LE, we shift by 9 and get BA in the low two bytes then CTZ.
+ For BE, we shift by 7 and get AB in the high two bytes then CLZ. */
+ rtx result_shifted = gen_reg_rtx (V16QImode);
+ int shift_amt = (BYTES_BIG_ENDIAN) ? 7 : 9;
+ emit_insn (gen_altivec_vsldoi_v16qi (result_shifted,result_gbbd,result_gbbd, GEN_INT (shift_amt)));
+
+ rtx diffix_df = simplify_gen_subreg (DFmode, diffix, DImode, 0);
+ emit_insn (gen_p8_mfvsrd_3_v16qi (diffix_df, result_shifted));
+ rtx count = gen_reg_rtx (DImode);
+
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_clzdi2 (count, diffix));
+ else
+ emit_insn (gen_ctzdi2 (count, diffix));
+
+ /* P8 doesn't have a good solution for extracting one byte from
+ a vsx reg like vextublx on P9 so we just compute the offset
+ of the differing byte and load it from each string. */
+ do_add3 (off_reg, off_reg, count);
+
+ rtx chr1 = gen_reg_rtx (QImode);
+ rtx chr2 = gen_reg_rtx (QImode);
+ rtx addr1 = gen_rtx_PLUS (Pmode, s1addr, off_reg);
+ do_load_for_compare_from_addr (QImode, chr1, addr1, orig_src1);
+ rtx addr2 = gen_rtx_PLUS (Pmode, s2addr, off_reg);
+ do_load_for_compare_from_addr (QImode, chr2, addr2, orig_src2);
+ machine_mode rmode = GET_MODE (result);
+ rtx chr1_rm = simplify_gen_subreg (rmode, chr1, QImode, 0);
+ rtx chr2_rm = simplify_gen_subreg (rmode, chr2, QImode, 0);
+ do_sub3 (result, chr1_rm, chr2_rm);
+ }
+
+ return;
+}
+
/* Expand a string compare operation with length, and return
true if successful. Return false if we should let the
compiler generate normal code, probably a strncmp call.
@@ -1797,7 +2274,7 @@ expand_strn_compare (rtx operands[], int no_length)
bytes_rtx = operands[3];
align_rtx = operands[4];
}
- unsigned HOST_WIDE_INT cmp_bytes = 0;
+
rtx src1_addr = force_reg (Pmode, XEXP (orig_src1, 0));
rtx src2_addr = force_reg (Pmode, XEXP (orig_src2, 0));
@@ -1822,26 +2299,43 @@ expand_strn_compare (rtx operands[], int no_length)
gcc_assert (GET_MODE (target) == SImode);
- /* If we have an LE target without ldbrx and word_mode is DImode,
- then we must avoid using word_mode. */
- int word_mode_ok = !(!BYTES_BIG_ENDIAN && !TARGET_LDBRX
- && word_mode == DImode);
-
- unsigned int word_mode_size = GET_MODE_SIZE (word_mode);
+ unsigned int required_align = 8;
unsigned HOST_WIDE_INT offset = 0;
unsigned HOST_WIDE_INT bytes; /* N from the strncmp args if available. */
unsigned HOST_WIDE_INT compare_length; /* How much to compare inline. */
+
if (no_length)
- /* Use this as a standin to determine the mode to use. */
- bytes = rs6000_string_compare_inline_limit * word_mode_size;
+ bytes = rs6000_string_compare_inline_limit;
else
bytes = UINTVAL (bytes_rtx);
- machine_mode load_mode =
- select_block_compare_mode (offset, bytes, base_align, word_mode_ok);
- unsigned int load_mode_size = GET_MODE_SIZE (load_mode);
- compare_length = rs6000_string_compare_inline_limit * load_mode_size;
+ /* Is it OK to use vec/vsx for this. TARGET_VSX means we have at
+ least POWER7 but we use TARGET_EFFICIENT_UNALIGNED_VSX which is
+ at least POWER8. That way we can rely on overlapping compares to
+ do the final comparison of less than 16 bytes. Also I do not want
+ to deal with making this work for 32 bits. */
+ int use_vec = (bytes >= 16 && !TARGET_32BIT && TARGET_EFFICIENT_UNALIGNED_VSX);
+
+ if (use_vec)
+ required_align = 16;
+
+ machine_mode load_mode;
+ rtx tmp_reg_src1, tmp_reg_src2;
+ if (use_vec)
+ {
+ load_mode = V16QImode;
+ tmp_reg_src1 = gen_reg_rtx (V16QImode);
+ tmp_reg_src2 = gen_reg_rtx (V16QImode);
+ }
+ else
+ {
+ load_mode = select_block_compare_mode (0, bytes, base_align);
+ tmp_reg_src1 = gen_reg_rtx (word_mode);
+ tmp_reg_src2 = gen_reg_rtx (word_mode);
+ }
+
+ compare_length = rs6000_string_compare_inline_limit;
/* If we have equality at the end of the last compare and we have not
found the end of the string, we need to call strcmp/strncmp to
@@ -1865,8 +2359,7 @@ expand_strn_compare (rtx operands[], int no_length)
rtx final_move_label = gen_label_rtx ();
rtx final_label = gen_label_rtx ();
rtx begin_compare_label = NULL;
- unsigned int required_align = 8;
-
+
if (base_align < required_align)
{
/* Generate code that checks distance to 4k boundary for this case. */
@@ -1883,7 +2376,7 @@ expand_strn_compare (rtx operands[], int no_length)
the subsequent code generation are in agreement so we do not
go past the length we tested for a 4k boundary crossing. */
unsigned HOST_WIDE_INT align_test = compare_length;
- if (align_test < 8)
+ if (align_test < required_align)
{
align_test = HOST_WIDE_INT_1U << ceil_log2 (align_test);
base_align = align_test;
@@ -1925,7 +2418,7 @@ expand_strn_compare (rtx operands[], int no_length)
else
{
/* -m32 -mpowerpc64 results in word_mode being DImode even
- though otherwise it is 32-bit. The length arg to strncmp
+ though otherwise it is 32-bit. The length arg to strncmp
is a size_t which will be the same size as pointers. */
rtx len_rtx = gen_reg_rtx (Pmode);
emit_move_insn (len_rtx, gen_int_mode (bytes, Pmode));
@@ -1947,164 +2440,35 @@ expand_strn_compare (rtx operands[], int no_length)
}
rtx cleanup_label = NULL;
- rtx tmp_reg_src1 = gen_reg_rtx (word_mode);
- rtx tmp_reg_src2 = gen_reg_rtx (word_mode);
+ rtx s1addr = NULL, s2addr = NULL, off_reg = NULL, vec_result = NULL;
/* Generate a sequence of GPR or VEC/VSX instructions to compare out
to the length specified. */
- unsigned HOST_WIDE_INT bytes_to_compare = compare_length;
- while (bytes_to_compare > 0)
+ if (use_vec)
{
- /* GPR compare sequence:
- check each 8B with: ld/ld cmpd bne
- If equal, use rldicr/cmpb to check for zero byte.
- cleanup code at end:
- cmpb get byte that differs
- cmpb look for zero byte
- orc combine
- cntlzd get bit of first zero/diff byte
- subfic convert for rldcl use
- rldcl rldcl extract diff/zero byte
- subf subtract for final result
-
- The last compare can branch around the cleanup code if the
- result is zero because the strings are exactly equal. */
-
- unsigned int align = compute_current_alignment (base_align, offset);
- load_mode = select_block_compare_mode (offset, bytes_to_compare,
- align, word_mode_ok);
- load_mode_size = GET_MODE_SIZE (load_mode);
- if (bytes_to_compare >= load_mode_size)
- cmp_bytes = load_mode_size;
- else if (TARGET_EFFICIENT_OVERLAPPING_UNALIGNED)
- {
- /* Move this load back so it doesn't go past the end.
- P8/P9 can do this efficiently. */
- unsigned int extra_bytes = load_mode_size - bytes_to_compare;
- cmp_bytes = bytes_to_compare;
- if (extra_bytes < offset)
- {
- offset -= extra_bytes;
- cmp_bytes = load_mode_size;
- bytes_to_compare = cmp_bytes;
- }
- }
- else
- /* P7 and earlier can't do the overlapping load trick fast,
- so this forces a non-overlapping load and a shift to get
- rid of the extra bytes. */
- cmp_bytes = bytes_to_compare;
-
- rtx addr1 = gen_rtx_PLUS (Pmode, src1_addr, GEN_INT (offset));
- do_load_for_compare_from_addr (load_mode, tmp_reg_src1, addr1, orig_src1);
- rtx addr2 = gen_rtx_PLUS (Pmode, src2_addr, GEN_INT (offset));
- do_load_for_compare_from_addr (load_mode, tmp_reg_src2, addr2, orig_src2);
-
- /* We must always left-align the data we read, and
- clear any bytes to the right that are beyond the string.
- Otherwise the cmpb sequence won't produce the correct
- results. The beginning of the compare will be done
- with word_mode so will not have any extra shifts or
- clear rights. */
-
- if (load_mode_size < word_mode_size)
- {
- /* Rotate left first. */
- rtx sh = GEN_INT (BITS_PER_UNIT * (word_mode_size - load_mode_size));
- do_rotl3 (tmp_reg_src1, tmp_reg_src1, sh);
- do_rotl3 (tmp_reg_src2, tmp_reg_src2, sh);
- }
-
- if (cmp_bytes < word_mode_size)
- {
- /* Now clear right. This plus the rotate can be
- turned into a rldicr instruction. */
- HOST_WIDE_INT mb = BITS_PER_UNIT * (word_mode_size - cmp_bytes);
- rtx mask = GEN_INT (HOST_WIDE_INT_M1U << mb);
- do_and3 (tmp_reg_src1, tmp_reg_src1, mask);
- do_and3 (tmp_reg_src2, tmp_reg_src2, mask);
- }
-
- /* Cases to handle. A and B are chunks of the two strings.
- 1: Not end of comparison:
- A != B: branch to cleanup code to compute result.
- A == B: check for 0 byte, next block if not found.
- 2: End of the inline comparison:
- A != B: branch to cleanup code to compute result.
- A == B: check for 0 byte, call strcmp/strncmp
- 3: compared requested N bytes:
- A == B: branch to result 0.
- A != B: cleanup code to compute result. */
-
- unsigned HOST_WIDE_INT remain = bytes_to_compare - cmp_bytes;
-
- rtx dst_label;
- if (remain > 0 || equality_compare_rest)
- {
- /* Branch to cleanup code, otherwise fall through to do
- more compares. */
- if (!cleanup_label)
- cleanup_label = gen_label_rtx ();
- dst_label = cleanup_label;
- }
- else
- /* Branch to end and produce result of 0. */
- dst_label = final_move_label;
-
- rtx lab_ref = gen_rtx_LABEL_REF (VOIDmode, dst_label);
- rtx cond = gen_reg_rtx (CCmode);
-
- /* Always produce the 0 result, it is needed if
- cmpb finds a 0 byte in this chunk. */
- rtx tmp = gen_rtx_MINUS (word_mode, tmp_reg_src1, tmp_reg_src2);
- rs6000_emit_dot_insn (result_reg, tmp, 1, cond);
-
- rtx cmp_rtx;
- if (remain == 0 && !equality_compare_rest)
- cmp_rtx = gen_rtx_EQ (VOIDmode, cond, const0_rtx);
- else
- cmp_rtx = gen_rtx_NE (VOIDmode, cond, const0_rtx);
-
- rtx ifelse = gen_rtx_IF_THEN_ELSE (VOIDmode, cmp_rtx,
- lab_ref, pc_rtx);
- rtx j = emit_jump_insn (gen_rtx_SET (pc_rtx, ifelse));
- JUMP_LABEL (j) = dst_label;
- LABEL_NUSES (dst_label) += 1;
-
- if (remain > 0 || equality_compare_rest)
- {
- /* Generate a cmpb to test for a 0 byte and branch
- to final result if found. */
- rtx cmpb_zero = gen_reg_rtx (word_mode);
- rtx lab_ref_fin = gen_rtx_LABEL_REF (VOIDmode, final_move_label);
- rtx condz = gen_reg_rtx (CCmode);
- rtx zero_reg = gen_reg_rtx (word_mode);
- emit_move_insn (zero_reg, GEN_INT (0));
- do_cmpb3 (cmpb_zero, tmp_reg_src1, zero_reg);
-
- if (cmp_bytes < word_mode_size)
- {
- /* Don't want to look at zero bytes past end. */
- HOST_WIDE_INT mb =
- BITS_PER_UNIT * (word_mode_size - cmp_bytes);
- rtx mask = GEN_INT (HOST_WIDE_INT_M1U << mb);
- do_and3 (cmpb_zero, cmpb_zero, mask);
- }
-
- emit_move_insn (condz, gen_rtx_COMPARE (CCmode, cmpb_zero, zero_reg));
- rtx cmpnz_rtx = gen_rtx_NE (VOIDmode, condz, const0_rtx);
- rtx ifelse = gen_rtx_IF_THEN_ELSE (VOIDmode, cmpnz_rtx,
- lab_ref_fin, pc_rtx);
- rtx j2 = emit_jump_insn (gen_rtx_SET (pc_rtx, ifelse));
- JUMP_LABEL (j2) = final_move_label;
- LABEL_NUSES (final_move_label) += 1;
-
- }
-
- offset += cmp_bytes;
- bytes_to_compare -= cmp_bytes;
+ s1addr = gen_reg_rtx (Pmode);
+ s2addr = gen_reg_rtx (Pmode);
+ off_reg = gen_reg_rtx (Pmode);
+ vec_result = gen_reg_rtx (load_mode);
+ emit_move_insn (result_reg, GEN_INT (0));
+ expand_strncmp_vec_sequence (compare_length,
+ orig_src1, orig_src2,
+ s1addr, s2addr, off_reg,
+ tmp_reg_src1, tmp_reg_src2,
+ vec_result,
+ equality_compare_rest,
+ &cleanup_label, final_move_label);
}
-
+ else
+ expand_strncmp_gpr_sequence (compare_length, base_align,
+ orig_src1, orig_src2,
+ tmp_reg_src1, tmp_reg_src2,
+ result_reg,
+ equality_compare_rest,
+ &cleanup_label, final_move_label);
+
+ offset = compare_length;
+
if (equality_compare_rest)
{
/* Update pointers past what has been compared already. */
@@ -2141,7 +2505,12 @@ expand_strn_compare (rtx operands[], int no_length)
if (cleanup_label)
emit_label (cleanup_label);
- emit_final_str_compare_gpr (tmp_reg_src1, tmp_reg_src2, result_reg);
+ if (use_vec)
+ emit_final_str_compare_vec (tmp_reg_src1, tmp_reg_src2, result_reg,
+ s1addr, s2addr, orig_src1, orig_src2,
+ off_reg, vec_result);
+ else
+ emit_final_str_compare_gpr (tmp_reg_src1, tmp_reg_src2, result_reg);
emit_label (final_move_label);
emit_insn (gen_movsi (target,
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index cbe1868..79dd2f6 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -2300,7 +2300,6 @@ rs6000_debug_vector_unit (enum rs6000_vector v)
case VECTOR_ALTIVEC: ret = "altivec"; break;
case VECTOR_VSX: ret = "vsx"; break;
case VECTOR_P8_VECTOR: ret = "p8_vector"; break;
- case VECTOR_OTHER: ret = "other"; break;
default: ret = "unknown"; break;
}
@@ -5325,6 +5324,7 @@ rs6000_density_test (rs6000_cost_data *data)
struct loop *loop = data->loop_info;
basic_block *bbs = get_loop_body (loop);
int nbbs = loop->num_nodes;
+ loop_vec_info loop_vinfo = loop_vec_info_for_loop (data->loop_info);
int vec_cost = data->cost[vect_body], not_vec_cost = 0;
int i, density_pct;
@@ -5336,7 +5336,7 @@ rs6000_density_test (rs6000_cost_data *data)
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple *stmt = gsi_stmt (gsi);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (stmt);
if (!STMT_VINFO_RELEVANT_P (stmt_info)
&& !STMT_VINFO_IN_PATTERN_P (stmt_info))
@@ -7942,7 +7942,9 @@ toc_relative_expr_p (const_rtx op, bool strict, const_rtx *tocrel_base_ret,
*tocrel_offset_ret = tocrel_offset;
return (GET_CODE (tocrel_base) == UNSPEC
- && XINT (tocrel_base, 1) == UNSPEC_TOCREL);
+ && XINT (tocrel_base, 1) == UNSPEC_TOCREL
+ && REG_P (XVECEXP (tocrel_base, 0, 1))
+ && REGNO (XVECEXP (tocrel_base, 0, 1)) == TOC_REGISTER);
}
/* Return true if X is a constant pool address, and also for cmodel=medium
@@ -15068,6 +15070,12 @@ rs6000_builtin_valid_without_lhs (enum rs6000_builtins fn_code)
case ALTIVEC_BUILTIN_STVX_V4SF:
case ALTIVEC_BUILTIN_STVX_V2DI:
case ALTIVEC_BUILTIN_STVX_V2DF:
+ case VSX_BUILTIN_STXVW4X_V16QI:
+ case VSX_BUILTIN_STXVW4X_V8HI:
+ case VSX_BUILTIN_STXVW4X_V4SF:
+ case VSX_BUILTIN_STXVW4X_V4SI:
+ case VSX_BUILTIN_STXVD2X_V2DF:
+ case VSX_BUILTIN_STXVD2X_V2DI:
return true;
default:
return false;
@@ -15115,7 +15123,6 @@ fold_mergehl_helper (gimple_stmt_iterator *gsi, gimple *stmt, int use_high)
tree arg1 = gimple_call_arg (stmt, 1);
tree lhs = gimple_call_lhs (stmt);
tree lhs_type = TREE_TYPE (lhs);
- tree lhs_type_type = TREE_TYPE (lhs_type);
int n_elts = TYPE_VECTOR_SUBPARTS (lhs_type);
int midpoint = n_elts / 2;
int offset = 0;
@@ -15123,12 +15130,31 @@ fold_mergehl_helper (gimple_stmt_iterator *gsi, gimple *stmt, int use_high)
if (use_high == 1)
offset = midpoint;
- tree_vector_builder elts (lhs_type, VECTOR_CST_NELTS (arg0), 1);
+ /* The permute_type will match the lhs for integral types. For double and
+ float types, the permute type needs to map to the V2 or V4 type that
+ matches size. */
+ tree permute_type;
+ if (INTEGRAL_TYPE_P (TREE_TYPE (lhs_type)))
+ permute_type = lhs_type;
+ else
+ {
+ if (types_compatible_p (TREE_TYPE (lhs_type),
+ TREE_TYPE (V2DF_type_node)))
+ permute_type = V2DI_type_node;
+ else if (types_compatible_p (TREE_TYPE (lhs_type),
+ TREE_TYPE (V4SF_type_node)))
+ permute_type = V4SI_type_node;
+ else
+ gcc_unreachable ();
+ }
+ tree_vector_builder elts (permute_type, VECTOR_CST_NELTS (arg0), 1);
for (int i = 0; i < midpoint; i++)
{
- elts.safe_push (build_int_cst (lhs_type_type, offset + i));
- elts.safe_push (build_int_cst (lhs_type_type, offset + n_elts + i));
+ elts.safe_push (build_int_cst (TREE_TYPE (permute_type),
+ offset + i));
+ elts.safe_push (build_int_cst (TREE_TYPE (permute_type),
+ offset + n_elts + i));
}
tree permute = elts.build ();
@@ -15460,16 +15486,44 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
case ALTIVEC_BUILTIN_VSLH:
case ALTIVEC_BUILTIN_VSLW:
case P8V_BUILTIN_VSLD:
- arg0 = gimple_call_arg (stmt, 0);
- if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (arg0)))
- && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (TREE_TYPE (arg0))))
- return false;
- arg1 = gimple_call_arg (stmt, 1);
- lhs = gimple_call_lhs (stmt);
- g = gimple_build_assign (lhs, LSHIFT_EXPR, arg0, arg1);
- gimple_set_location (g, gimple_location (stmt));
- gsi_replace (gsi, g, true);
- return true;
+ {
+ location_t loc;
+ gimple_seq stmts = NULL;
+ arg0 = gimple_call_arg (stmt, 0);
+ tree arg0_type = TREE_TYPE (arg0);
+ if (INTEGRAL_TYPE_P (TREE_TYPE (arg0_type))
+ && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0_type)))
+ return false;
+ arg1 = gimple_call_arg (stmt, 1);
+ tree arg1_type = TREE_TYPE (arg1);
+ tree unsigned_arg1_type = unsigned_type_for (TREE_TYPE (arg1));
+ tree unsigned_element_type = unsigned_type_for (TREE_TYPE (arg1_type));
+ loc = gimple_location (stmt);
+ lhs = gimple_call_lhs (stmt);
+ /* Force arg1 into the range valid matching the arg0 type. */
+ /* Build a vector consisting of the max valid bit-size values. */
+ int n_elts = VECTOR_CST_NELTS (arg1);
+ int tree_size_in_bits = TREE_INT_CST_LOW (size_in_bytes (arg1_type))
+ * BITS_PER_UNIT;
+ tree element_size = build_int_cst (unsigned_element_type,
+ tree_size_in_bits / n_elts);
+ tree_vector_builder elts (unsigned_type_for (arg1_type), n_elts, 1);
+ for (int i = 0; i < n_elts; i++)
+ elts.safe_push (element_size);
+ tree modulo_tree = elts.build ();
+ /* Modulo the provided shift value against that vector. */
+ tree unsigned_arg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR,
+ unsigned_arg1_type, arg1);
+ tree new_arg1 = gimple_build (&stmts, loc, TRUNC_MOD_EXPR,
+ unsigned_arg1_type, unsigned_arg1,
+ modulo_tree);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ /* And finally, do the shift. */
+ g = gimple_build_assign (lhs, LSHIFT_EXPR, arg0, new_arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ }
/* Flavors of vector shift right. */
case ALTIVEC_BUILTIN_VSRB:
case ALTIVEC_BUILTIN_VSRH:
@@ -15577,6 +15631,77 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
return true;
}
+ /* unaligned Vector loads. */
+ case VSX_BUILTIN_LXVW4X_V16QI:
+ case VSX_BUILTIN_LXVW4X_V8HI:
+ case VSX_BUILTIN_LXVW4X_V4SF:
+ case VSX_BUILTIN_LXVW4X_V4SI:
+ case VSX_BUILTIN_LXVD2X_V2DF:
+ case VSX_BUILTIN_LXVD2X_V2DI:
+ {
+ arg0 = gimple_call_arg (stmt, 0); // offset
+ arg1 = gimple_call_arg (stmt, 1); // address
+ lhs = gimple_call_lhs (stmt);
+ location_t loc = gimple_location (stmt);
+ /* Since arg1 may be cast to a different type, just use ptr_type_node
+ here instead of trying to enforce TBAA on pointer types. */
+ tree arg1_type = ptr_type_node;
+ tree lhs_type = TREE_TYPE (lhs);
+ /* In GIMPLE the type of the MEM_REF specifies the alignment. The
+ required alignment (power) is 4 bytes regardless of data type. */
+ tree align_ltype = build_aligned_type (lhs_type, 4);
+ /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create
+ the tree using the value from arg0. The resulting type will match
+ the type of arg1. */
+ gimple_seq stmts = NULL;
+ tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg0);
+ tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR,
+ arg1_type, arg1, temp_offset);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ /* Use the build2 helper to set up the mem_ref. The MEM_REF could also
+ take an offset, but since we've already incorporated the offset
+ above, here we just pass in a zero. */
+ gimple *g;
+ g = gimple_build_assign (lhs, build2 (MEM_REF, align_ltype, temp_addr,
+ build_int_cst (arg1_type, 0)));
+ gimple_set_location (g, loc);
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+
+ /* unaligned Vector stores. */
+ case VSX_BUILTIN_STXVW4X_V16QI:
+ case VSX_BUILTIN_STXVW4X_V8HI:
+ case VSX_BUILTIN_STXVW4X_V4SF:
+ case VSX_BUILTIN_STXVW4X_V4SI:
+ case VSX_BUILTIN_STXVD2X_V2DF:
+ case VSX_BUILTIN_STXVD2X_V2DI:
+ {
+ arg0 = gimple_call_arg (stmt, 0); /* Value to be stored. */
+ arg1 = gimple_call_arg (stmt, 1); /* Offset. */
+ tree arg2 = gimple_call_arg (stmt, 2); /* Store-to address. */
+ location_t loc = gimple_location (stmt);
+ tree arg0_type = TREE_TYPE (arg0);
+ /* Use ptr_type_node (no TBAA) for the arg2_type. */
+ tree arg2_type = ptr_type_node;
+ /* In GIMPLE the type of the MEM_REF specifies the alignment. The
+ required alignment (power) is 4 bytes regardless of data type. */
+ tree align_stype = build_aligned_type (arg0_type, 4);
+ /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create
+ the tree using the value from arg1. */
+ gimple_seq stmts = NULL;
+ tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg1);
+ tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR,
+ arg2_type, arg2, temp_offset);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ gimple *g;
+ g = gimple_build_assign (build2 (MEM_REF, align_stype, temp_addr,
+ build_int_cst (arg2_type, 0)), arg0);
+ gimple_set_location (g, loc);
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+
/* Vector Fused multiply-add (fma). */
case ALTIVEC_BUILTIN_VMADDFP:
case VSX_BUILTIN_XVMADDDP:
@@ -15674,6 +15799,48 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
gimple_set_location (g, gimple_location (stmt));
gsi_replace (gsi, g, true);
return true;
+ }
+
+ /* Flavors of vec_splat. */
+ /* a = vec_splat (b, 0x3) becomes a = { b[3],b[3],b[3],...}; */
+ case ALTIVEC_BUILTIN_VSPLTB:
+ case ALTIVEC_BUILTIN_VSPLTH:
+ case ALTIVEC_BUILTIN_VSPLTW:
+ case VSX_BUILTIN_XXSPLTD_V2DI:
+ case VSX_BUILTIN_XXSPLTD_V2DF:
+ {
+ arg0 = gimple_call_arg (stmt, 0); /* input vector. */
+ arg1 = gimple_call_arg (stmt, 1); /* index into arg0. */
+ /* Only fold the vec_splat_*() if arg1 is both a constant value and
+ is a valid index into the arg0 vector. */
+ unsigned int n_elts = VECTOR_CST_NELTS (arg0);
+ if (TREE_CODE (arg1) != INTEGER_CST
+ || TREE_INT_CST_LOW (arg1) > (n_elts -1))
+ return false;
+ lhs = gimple_call_lhs (stmt);
+ tree lhs_type = TREE_TYPE (lhs);
+ tree arg0_type = TREE_TYPE (arg0);
+ tree splat;
+ if (TREE_CODE (arg0) == VECTOR_CST)
+ splat = VECTOR_CST_ELT (arg0, TREE_INT_CST_LOW (arg1));
+ else
+ {
+ /* Determine (in bits) the length and start location of the
+ splat value for a call to the tree_vec_extract helper. */
+ int splat_elem_size = TREE_INT_CST_LOW (size_in_bytes (arg0_type))
+ * BITS_PER_UNIT / n_elts;
+ int splat_start_bit = TREE_INT_CST_LOW (arg1) * splat_elem_size;
+ tree len = build_int_cst (bitsizetype, splat_elem_size);
+ tree start = build_int_cst (bitsizetype, splat_start_bit);
+ splat = tree_vec_extract (gsi, TREE_TYPE (lhs_type), arg0,
+ len, start);
+ }
+ /* And finally, build the new vector. */
+ tree splat_tree = build_vector_from_val (lhs_type, splat);
+ g = gimple_build_assign (lhs, splat_tree);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
}
/* vec_mergel (integrals). */
@@ -15682,6 +15849,8 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
case VSX_BUILTIN_XXMRGLW_4SI:
case ALTIVEC_BUILTIN_VMRGLB:
case VSX_BUILTIN_VEC_MERGEL_V2DI:
+ case VSX_BUILTIN_XXMRGLW_4SF:
+ case VSX_BUILTIN_VEC_MERGEL_V2DF:
fold_mergehl_helper (gsi, stmt, 1);
return true;
/* vec_mergeh (integrals). */
@@ -15690,8 +15859,94 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
case VSX_BUILTIN_XXMRGHW_4SI:
case ALTIVEC_BUILTIN_VMRGHB:
case VSX_BUILTIN_VEC_MERGEH_V2DI:
+ case VSX_BUILTIN_XXMRGHW_4SF:
+ case VSX_BUILTIN_VEC_MERGEH_V2DF:
fold_mergehl_helper (gsi, stmt, 0);
return true;
+
+ /* d = vec_pack (a, b) */
+ case P8V_BUILTIN_VPKUDUM:
+ case ALTIVEC_BUILTIN_VPKUHUM:
+ case ALTIVEC_BUILTIN_VPKUWUM:
+ {
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ gimple *g = gimple_build_assign (lhs, VEC_PACK_TRUNC_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+
+ /* d = vec_unpackh (a) */
+ /* Note that the UNPACK_{HI,LO}_EXPR used in the gimple_build_assign call
+ in this code is sensitive to endian-ness, and needs to be inverted to
+ handle both LE and BE targets. */
+ case ALTIVEC_BUILTIN_VUPKHSB:
+ case ALTIVEC_BUILTIN_VUPKHSH:
+ case P8V_BUILTIN_VUPKHSW:
+ {
+ arg0 = gimple_call_arg (stmt, 0);
+ lhs = gimple_call_lhs (stmt);
+ if (BYTES_BIG_ENDIAN)
+ g = gimple_build_assign (lhs, VEC_UNPACK_HI_EXPR, arg0);
+ else
+ g = gimple_build_assign (lhs, VEC_UNPACK_LO_EXPR, arg0);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+ /* d = vec_unpackl (a) */
+ case ALTIVEC_BUILTIN_VUPKLSB:
+ case ALTIVEC_BUILTIN_VUPKLSH:
+ case P8V_BUILTIN_VUPKLSW:
+ {
+ arg0 = gimple_call_arg (stmt, 0);
+ lhs = gimple_call_lhs (stmt);
+ if (BYTES_BIG_ENDIAN)
+ g = gimple_build_assign (lhs, VEC_UNPACK_LO_EXPR, arg0);
+ else
+ g = gimple_build_assign (lhs, VEC_UNPACK_HI_EXPR, arg0);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+ /* There is no gimple type corresponding with pixel, so just return. */
+ case ALTIVEC_BUILTIN_VUPKHPX:
+ case ALTIVEC_BUILTIN_VUPKLPX:
+ return false;
+
+ /* vec_perm. */
+ case ALTIVEC_BUILTIN_VPERM_16QI:
+ case ALTIVEC_BUILTIN_VPERM_8HI:
+ case ALTIVEC_BUILTIN_VPERM_4SI:
+ case ALTIVEC_BUILTIN_VPERM_2DI:
+ case ALTIVEC_BUILTIN_VPERM_4SF:
+ case ALTIVEC_BUILTIN_VPERM_2DF:
+ {
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ tree permute = gimple_call_arg (stmt, 2);
+ lhs = gimple_call_lhs (stmt);
+ location_t loc = gimple_location (stmt);
+ gimple_seq stmts = NULL;
+ // convert arg0 and arg1 to match the type of the permute
+ // for the VEC_PERM_EXPR operation.
+ tree permute_type = (TREE_TYPE (permute));
+ tree arg0_ptype = gimple_convert (&stmts, loc, permute_type, arg0);
+ tree arg1_ptype = gimple_convert (&stmts, loc, permute_type, arg1);
+ tree lhs_ptype = gimple_build (&stmts, loc, VEC_PERM_EXPR,
+ permute_type, arg0_ptype, arg1_ptype,
+ permute);
+ // Convert the result back to the desired lhs type upon completion.
+ tree temp = gimple_convert (&stmts, loc, TREE_TYPE (lhs), lhs_ptype);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ g = gimple_build_assign (lhs, temp);
+ gimple_set_location (g, loc);
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+
default:
if (TARGET_DEBUG_BUILTIN)
fprintf (stderr, "gimple builtin intrinsic not matched:%d %s %s\n",
@@ -15835,7 +16090,7 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
case MISC_BUILTIN_SPEC_BARRIER:
{
- emit_insn (gen_rs6000_speculation_barrier ());
+ emit_insn (gen_speculation_barrier ());
return NULL_RTX;
}
@@ -20167,6 +20422,9 @@ rs6000_output_function_entry (FILE *file, const char *fname)
/* Print an operand. Recognize special options, documented below. */
#if TARGET_ELF
+/* Access to .sdata2 through r2 (see -msdata=eabi in invoke.texi) is
+ only introduced by the linker, when applying the sda21
+ relocation. */
#define SMALL_DATA_RELOC ((rs6000_sdata == SDATA_EABI) ? "sda21" : "sdarel")
#define SMALL_DATA_REG ((rs6000_sdata == SDATA_EABI) ? 0 : 13)
#else
@@ -24073,6 +24331,12 @@ rs6000_function_ok_for_sibcall (tree decl, tree exp)
{
tree fntype;
+ /* The sibcall epilogue may clobber the static chain register.
+ ??? We could work harder and avoid that, but it's probably
+ not worth the hassle in practice. */
+ if (CALL_EXPR_STATIC_CHAIN (exp))
+ return false;
+
if (decl)
fntype = TREE_TYPE (decl);
else
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 56b8a30..4ce24d5 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -243,18 +243,8 @@
;; Is copying of this instruction disallowed?
(define_attr "cannot_copy" "no,yes" (const_string "no"))
-;; Length (in bytes).
-; '(pc)' in the following doesn't include the instruction itself; it is
-; calculated as if the instruction had zero size.
-(define_attr "length" ""
- (if_then_else (eq_attr "type" "branch")
- (if_then_else (and (ge (minus (match_dup 0) (pc))
- (const_int -32768))
- (lt (minus (match_dup 0) (pc))
- (const_int 32764)))
- (const_int 4)
- (const_int 8))
- (const_int 4)))
+;; Length of the instruction (in bytes).
+(define_attr "length" "" (const_int 4))
;; Processor type -- this attribute must exactly match the processor_type
;; enumeration in rs6000-opts.h.
@@ -998,7 +988,7 @@
"=r, r, wl, wu, wj, wK, wH, wr")
(sign_extend:EXTSI (match_operand:SI 1 "lwa_operand"
- "Y, r, Z, Z, r, wK, wH, ?wIwH")))]
+ "YZ, r, Z, Z, r, wK, wH, ?wIwH")))]
""
"@
lwa%U1%X1 %0,%1
@@ -2388,8 +2378,7 @@
(bswap:HSI (match_operand:HSI 1 "memory_operand" "Z"))))]
"TARGET_POWERPC64"
"l<wd>brx %0,%y1"
- [(set_attr "length" "4")
- (set_attr "type" "load")])
+ [(set_attr "type" "load")])
(define_insn "*bswaphi2_extendsi"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -2397,8 +2386,7 @@
(bswap:HI (match_operand:HI 1 "memory_operand" "Z"))))]
""
"lhbrx %0,%y1"
- [(set_attr "length" "4")
- (set_attr "type" "load")])
+ [(set_attr "type" "load")])
;; Separate the bswap patterns into load, store, and gpr<-gpr. This prevents
;; the register allocator from converting a gpr<-gpr swap into a store and then
@@ -5997,7 +5985,7 @@
(set (match_operand:DI 0 "gpc_reg_operand")
(unspec:DI [(match_dup 2)]
UNSPEC_FCTID))]
- "TARGET_HARD_FLOAT && TARGET_VSX"
+ "TARGET_HARD_FLOAT && TARGET_VSX && TARGET_FPRND"
{
operands[2] = gen_reg_rtx (<MODE>mode);
})
@@ -6090,8 +6078,7 @@
"@
fcfidu %0,%1
xscvuxddp %x0,%x1"
- [(set_attr "type" "fp")
- (set_attr "length" "4")])
+ [(set_attr "type" "fp")])
(define_insn_and_split "*floatunsdidf2_mem"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d,ws")
@@ -6706,8 +6693,7 @@
(match_operand 2 "" ""))))]
"TARGET_MACHO && ! TARGET_64BIT"
"lwz %0,lo16(%2)(%1)"
- [(set_attr "type" "load")
- (set_attr "length" "4")])
+ [(set_attr "type" "load")])
;; MR LA LWZ LFIWZX LXSIWZX
;; STW STFIWX STXSIWX LI LIS
@@ -7419,8 +7405,8 @@
fmr %0,%1
lxsd %0,%1
stxsd %1,%0
- lxsd%U1x %x0,%y1
- stxsd%U0x %x1,%y0
+ lxsdx %x0,%y1
+ stxsdx %x1,%y0
xxlor %x0,%x1,%x1
xxlxor %x0,%x0,%x0
#
@@ -7469,13 +7455,13 @@
[(set (match_operand:FMOVE64 0 "nonimmediate_operand"
"=m, d, d, <f64_p9>, wY,
<f64_av>, Z, <f64_vsx>, <f64_vsx>, !r,
- Y, r, !r, *c*l, !r,
+ YZ, r, !r, *c*l, !r,
*h, r, wg, r, <f64_dm>")
(match_operand:FMOVE64 1 "input_operand"
"d, m, d, wY, <f64_p9>,
Z, <f64_av>, <f64_vsx>, <zero_fp>, <zero_fp>,
- r, Y, r, r, h,
+ r, YZ, r, r, h,
0, wg, r, <f64_dm>, r"))]
"TARGET_POWERPC64 && TARGET_HARD_FLOAT
@@ -7487,8 +7473,8 @@
fmr %0,%1
lxsd %0,%1
stxsd %1,%0
- lxsd%U1x %x0,%y1
- stxsd%U0x %x1,%y0
+ lxsdx %x0,%y1
+ stxsdx %x1,%y0
xxlor %x0,%x1,%x1
xxlxor %x0,%x0,%x0
li %0,0
@@ -9417,8 +9403,7 @@
(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGD)))]
"HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
- "addis %0,%1,%2@got@tlsgd@ha"
- [(set_attr "length" "4")])
+ "addis %0,%1,%2@got@tlsgd@ha")
(define_insn "*tls_gd_low<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
@@ -9427,8 +9412,7 @@
(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGD)))]
"HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
- "addi %0,%1,%2@got@tlsgd@l"
- [(set_attr "length" "4")])
+ "addi %0,%1,%2@got@tlsgd@l")
(define_insn "*tls_gd_call_aix<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
@@ -9460,8 +9444,7 @@
}
return "bl %z1(%3@tlsgd)";
}
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn_and_split "tls_ld_aix<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
@@ -9553,8 +9536,7 @@
(match_operand:TLSmode 1 "gpc_reg_operand" "b")]
UNSPEC_TLSLD)))]
"HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
- "addis %0,%1,%&@got@tlsld@ha"
- [(set_attr "length" "4")])
+ "addis %0,%1,%&@got@tlsld@ha")
(define_insn "*tls_ld_low<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
@@ -9563,8 +9545,7 @@
(match_operand:TLSmode 2 "gpc_reg_operand" "b")]
UNSPEC_TLSLD)))]
"HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
- "addi %0,%1,%&@got@tlsld@l"
- [(set_attr "length" "4")])
+ "addi %0,%1,%&@got@tlsld@l")
(define_insn "*tls_ld_call_aix<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
@@ -9594,8 +9575,7 @@
}
return "bl %z1(%&@tlsld)";
}
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "tls_dtprel_<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
@@ -9650,8 +9630,7 @@
(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGOTDTPREL)))]
"HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
- "addis %0,%1,%2@got@dtprel@ha"
- [(set_attr "length" "4")])
+ "addis %0,%1,%2@got@dtprel@ha")
(define_insn "*tls_got_dtprel_low<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
@@ -9660,8 +9639,7 @@
(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGOTDTPREL)))]
"HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
- "l<TLSmode:tls_insn_suffix> %0,%2@got@dtprel@l(%1)"
- [(set_attr "length" "4")])
+ "l<TLSmode:tls_insn_suffix> %0,%2@got@dtprel@l(%1)")
(define_insn "tls_tprel_<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
@@ -9719,8 +9697,7 @@
(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGOTTPREL)))]
"HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
- "addis %0,%1,%2@got@tprel@ha"
- [(set_attr "length" "4")])
+ "addis %0,%1,%2@got@tprel@ha")
(define_insn "*tls_got_tprel_low<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
@@ -9729,8 +9706,7 @@
(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGOTTPREL)))]
"HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
- "l<TLSmode:tls_insn_suffix> %0,%2@got@tprel@l(%1)"
- [(set_attr "length" "4")])
+ "l<TLSmode:tls_insn_suffix> %0,%2@got@tprel@l(%1)")
(define_insn "tls_tls_<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
@@ -10038,8 +10014,7 @@
(unspec:SI [(const_int 0)] UNSPEC_TOC))]
"DEFAULT_ABI == ABI_V4 && flag_pic == 1 && TARGET_32BIT"
"bl _GLOBAL_OFFSET_TABLE_@local-4"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_expand "load_toc_v4_PIC_1"
[(parallel [(set (reg:SI LR_REGNO)
@@ -10057,7 +10032,6 @@
&& (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))"
"bcl 20,31,%0\n%0:"
[(set_attr "type" "branch")
- (set_attr "length" "4")
(set_attr "cannot_copy" "yes")])
(define_insn "load_toc_v4_PIC_1_476"
@@ -10075,7 +10049,6 @@
return templ;
}
[(set_attr "type" "branch")
- (set_attr "length" "4")
(set_attr "cannot_copy" "yes")])
(define_expand "load_toc_v4_PIC_1b"
@@ -10659,8 +10632,7 @@
(clobber (reg:P LR_REGNO))]
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
"bl %z0"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*call_value_local_aix<mode>"
[(set (match_operand 0 "" "")
@@ -10669,8 +10641,7 @@
(clobber (reg:P LR_REGNO))]
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
"bl %z1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
;; Call to AIX abi function which may be in another module.
;; Restore the TOC pointer (r2) after the call.
@@ -11053,8 +11024,7 @@
"@
b %z0
b%T0"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*sibcall_value_aix<mode>"
[(set (match_operand 0 "" "")
@@ -11065,8 +11035,7 @@
"@
b %z1
b%T1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_expand "sibcall_epilogue"
[(use (const_int 0))]
@@ -11117,8 +11086,7 @@
(set (attr "indexed")
(if_then_else (match_operand 0 "indexed_address_mem")
(const_string "yes")
- (const_string "no")))
- (set_attr "length" "4")])
+ (const_string "no")))])
(define_insn "probe_stack_range<P:mode>"
[(set (match_operand:P 0 "register_operand" "=&r")
@@ -11613,51 +11581,6 @@
operands[10] = GEN_INT (sextc);
})
-;; The following two insns don't exist as single insns, but if we provide
-;; them, we can swap an add and compare, which will enable us to overlap more
-;; of the required delay between a compare and branch. We generate code for
-;; them by splitting.
-
-(define_insn ""
- [(set (match_operand:CC 3 "cc_reg_operand" "=y")
- (compare:CC (match_operand:SI 1 "gpc_reg_operand" "r")
- (match_operand:SI 2 "short_cint_operand" "i")))
- (set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (plus:SI (match_dup 1) (match_operand:SI 4 "short_cint_operand" "i")))]
- ""
- "#"
- [(set_attr "length" "8")])
-
-(define_insn ""
- [(set (match_operand:CCUNS 3 "cc_reg_operand" "=y")
- (compare:CCUNS (match_operand:SI 1 "gpc_reg_operand" "r")
- (match_operand:SI 2 "u_short_cint_operand" "i")))
- (set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (plus:SI (match_dup 1) (match_operand:SI 4 "short_cint_operand" "i")))]
- ""
- "#"
- [(set_attr "length" "8")])
-
-(define_split
- [(set (match_operand:CC 3 "cc_reg_operand")
- (compare:CC (match_operand:SI 1 "gpc_reg_operand")
- (match_operand:SI 2 "short_cint_operand")))
- (set (match_operand:SI 0 "gpc_reg_operand")
- (plus:SI (match_dup 1) (match_operand:SI 4 "short_cint_operand")))]
- ""
- [(set (match_dup 3) (compare:CC (match_dup 1) (match_dup 2)))
- (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 4)))])
-
-(define_split
- [(set (match_operand:CCUNS 3 "cc_reg_operand")
- (compare:CCUNS (match_operand:SI 1 "gpc_reg_operand")
- (match_operand:SI 2 "u_short_cint_operand")))
- (set (match_operand:SI 0 "gpc_reg_operand")
- (plus:SI (match_dup 1) (match_operand:SI 4 "short_cint_operand")))]
- ""
- [(set (match_dup 3) (compare:CCUNS (match_dup 1) (match_dup 2)))
- (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 4)))])
-
;; Only need to compare second words if first words equal
(define_insn "*cmp<mode>_internal1"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
@@ -12331,11 +12254,10 @@
(const_string "12")
(const_string "16")))])
-;; Define both directions of branch and return. If we need a reload
-;; register, we'd rather use CR0 since it is much easier to copy a
-;; register CC value to there.
+;; Conditional branches.
+;; These either are a single bc insn, or a bc around a b.
-(define_insn ""
+(define_insn "*cbranch"
[(set (pc)
(if_then_else (match_operator 1 "branch_comparison_operator"
[(match_operand 2 "cc_reg_operand" "y")
@@ -12346,9 +12268,17 @@
{
return output_cbranch (operands[1], "%l0", 0, insn);
}
- [(set_attr "type" "branch")])
-
-(define_insn ""
+ [(set_attr "type" "branch")
+ (set (attr "length")
+ (if_then_else (and (ge (minus (match_dup 0) (pc))
+ (const_int -32768))
+ (lt (minus (match_dup 0) (pc))
+ (const_int 32764)))
+ (const_int 4)
+ (const_int 8)))])
+
+;; Conditional return.
+(define_insn "*creturn"
[(set (pc)
(if_then_else (match_operator 0 "branch_comparison_operator"
[(match_operand 1 "cc_reg_operand" "y")
@@ -12359,8 +12289,7 @@
{
return output_cbranch (operands[0], NULL, 0, insn);
}
- [(set_attr "type" "jmpreg")
- (set_attr "length" "4")])
+ [(set_attr "type" "jmpreg")])
;; Logic on condition register values.
@@ -12641,7 +12570,7 @@
return "ori 2,2,0";
})
-(define_insn "rs6000_speculation_barrier"
+(define_insn "speculation_barrier"
[(unspec_volatile:BLK [(const_int 0)] UNSPECV_SPEC_BARRIER)]
""
"ori 31,31,0")
@@ -12716,7 +12645,17 @@
return "<bd_neg> $+8\;b %l0";
}
[(set_attr "type" "branch")
- (set_attr "length" "*,16,20,20")])
+ (set (attr "length")
+ (cond [(eq (symbol_ref "which_alternative") (const_int 0))
+ (if_then_else (and (ge (minus (match_dup 0) (pc))
+ (const_int -32768))
+ (lt (minus (match_dup 0) (pc))
+ (const_int 32764)))
+ (const_int 4)
+ (const_int 8))
+ (eq (symbol_ref "which_alternative") (const_int 1))
+ (const_int 16)]
+ (const_int 20)))])
;; Now the splitter if we could not allocate the CTR register
(define_split
@@ -12795,7 +12734,17 @@
}
}
[(set_attr "type" "branch")
- (set_attr "length" "*,16,20,20")])
+ (set (attr "length")
+ (cond [(eq (symbol_ref "which_alternative") (const_int 0))
+ (if_then_else (and (ge (minus (match_dup 0) (pc))
+ (const_int -32768))
+ (lt (minus (match_dup 0) (pc))
+ (const_int 32764)))
+ (const_int 4)
+ (const_int 8))
+ (eq (symbol_ref "which_alternative") (const_int 1))
+ (const_int 16)]
+ (const_int 20)))])
;; Now the splitter if we could not allocate the CTR register
(define_split
@@ -12968,8 +12917,7 @@
(match_operand:P 3 "gpc_reg_operand" "r"))])]
""
"bl %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*save_gpregs_<mode>_r12"
[(match_parallel 0 "any_parallel_operand"
@@ -12980,8 +12928,7 @@
(match_operand:P 3 "gpc_reg_operand" "r"))])]
""
"bl %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*save_gpregs_<mode>_r1"
[(match_parallel 0 "any_parallel_operand"
@@ -12992,8 +12939,7 @@
(match_operand:P 3 "gpc_reg_operand" "r"))])]
""
"bl %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*save_fpregs_<mode>_r11"
[(match_parallel 0 "any_parallel_operand"
@@ -13004,8 +12950,7 @@
(match_operand:DF 3 "gpc_reg_operand" "d"))])]
""
"bl %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*save_fpregs_<mode>_r12"
[(match_parallel 0 "any_parallel_operand"
@@ -13016,8 +12961,7 @@
(match_operand:DF 3 "gpc_reg_operand" "d"))])]
""
"bl %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*save_fpregs_<mode>_r1"
[(match_parallel 0 "any_parallel_operand"
@@ -13028,8 +12972,7 @@
(match_operand:DF 3 "gpc_reg_operand" "d"))])]
""
"bl %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
; This is to explain that changes to the stack pointer should
; not be moved over loads from or stores to stack memory.
@@ -13119,8 +13062,7 @@
(set_attr "indexed" "yes")
(set_attr "cell_micro" "always")])
-; FIXME: This would probably be somewhat simpler if the Cygnus sibcall
-; stuff was in GCC. Oh, and "any_parallel_operand" is a bit flexible...
+; FIXME: "any_parallel_operand" is a bit flexible...
; The following comment applies to:
; save_gpregs_*
@@ -13146,8 +13088,7 @@
(match_operand:P 3 "memory_operand" "m"))])]
""
"bl %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*restore_gpregs_<mode>_r12"
[(match_parallel 0 "any_parallel_operand"
@@ -13158,8 +13099,7 @@
(match_operand:P 3 "memory_operand" "m"))])]
""
"bl %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*restore_gpregs_<mode>_r1"
[(match_parallel 0 "any_parallel_operand"
@@ -13170,8 +13110,7 @@
(match_operand:P 3 "memory_operand" "m"))])]
""
"bl %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*return_and_restore_gpregs_<mode>_r11"
[(match_parallel 0 "any_parallel_operand"
@@ -13183,8 +13122,7 @@
(match_operand:P 3 "memory_operand" "m"))])]
""
"b %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*return_and_restore_gpregs_<mode>_r12"
[(match_parallel 0 "any_parallel_operand"
@@ -13196,8 +13134,7 @@
(match_operand:P 3 "memory_operand" "m"))])]
""
"b %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*return_and_restore_gpregs_<mode>_r1"
[(match_parallel 0 "any_parallel_operand"
@@ -13209,8 +13146,7 @@
(match_operand:P 3 "memory_operand" "m"))])]
""
"b %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*return_and_restore_fpregs_<mode>_r11"
[(match_parallel 0 "any_parallel_operand"
@@ -13222,8 +13158,7 @@
(match_operand:DF 3 "memory_operand" "m"))])]
""
"b %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*return_and_restore_fpregs_<mode>_r12"
[(match_parallel 0 "any_parallel_operand"
@@ -13235,8 +13170,7 @@
(match_operand:DF 3 "memory_operand" "m"))])]
""
"b %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*return_and_restore_fpregs_<mode>_r1"
[(match_parallel 0 "any_parallel_operand"
@@ -13248,8 +13182,7 @@
(match_operand:DF 3 "memory_operand" "m"))])]
""
"b %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*return_and_restore_fpregs_aix_<mode>_r11"
[(match_parallel 0 "any_parallel_operand"
@@ -13260,8 +13193,7 @@
(match_operand:DF 3 "memory_operand" "m"))])]
""
"b %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
(define_insn "*return_and_restore_fpregs_aix_<mode>_r1"
[(match_parallel 0 "any_parallel_operand"
@@ -13272,8 +13204,7 @@
(match_operand:DF 3 "memory_operand" "m"))])]
""
"b %1"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ [(set_attr "type" "branch")])
; This is used in compiling the unwind routines.
(define_expand "eh_return"
@@ -13868,8 +13799,7 @@
UNSPEC_ADDG6S))]
"TARGET_POPCNTD"
"addg6s %0,%1,%2"
- [(set_attr "type" "integer")
- (set_attr "length" "4")])
+ [(set_attr "type" "integer")])
(define_insn "cdtbcd"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -13877,8 +13807,7 @@
UNSPEC_CDTBCD))]
"TARGET_POPCNTD"
"cdtbcd %0,%1"
- [(set_attr "type" "integer")
- (set_attr "length" "4")])
+ [(set_attr "type" "integer")])
(define_insn "cbcdtd"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -13886,8 +13815,7 @@
UNSPEC_CBCDTD))]
"TARGET_POPCNTD"
"cbcdtd %0,%1"
- [(set_attr "type" "integer")
- (set_attr "length" "4")])
+ [(set_attr "type" "integer")])
(define_int_iterator UNSPEC_DIV_EXTEND [UNSPEC_DIVE
UNSPEC_DIVEU])
@@ -13944,8 +13872,7 @@
operands[3] = gen_rtx_REG (<FP128_64>mode, fp_regno);
}
- [(set_attr "type" "fp,fpstore,mffgpr,mftgpr,store")
- (set_attr "length" "4")])
+ [(set_attr "type" "fp,fpstore,mffgpr,mftgpr,store")])
(define_insn_and_split "unpack<mode>_nodm"
[(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=d,m")
@@ -13968,8 +13895,7 @@
operands[3] = gen_rtx_REG (<FP128_64>mode, fp_regno);
}
- [(set_attr "type" "fp,fpstore")
- (set_attr "length" "4")])
+ [(set_attr "type" "fp,fpstore")])
(define_insn_and_split "pack<mode>"
[(set (match_operand:FMOVE128 0 "register_operand" "=&d")
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index 25a4883..fc147b0 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -177,7 +177,7 @@ mno-string
Target RejectNegative Undocumented Ignore
mstring
-Target RejectNegative Undocumented Warn(%<-mstring%> is deprecated)
+Target RejectNegative Undocumented Deprecated
msoft-float
Target Report RejectNegative Mask(SOFT_FLOAT) Var(rs6000_isa_flags)
@@ -334,21 +334,13 @@ Target Report Var(rs6000_block_compare_inline_loop_limit) Init(-1) RejectNegativ
Max number of bytes to compare with loops.
mstring-compare-inline-limit=
-Target Report Var(rs6000_string_compare_inline_limit) Init(8) RejectNegative Joined UInteger Save
-Max number of pairs of load insns for compare.
+Target Report Var(rs6000_string_compare_inline_limit) Init(64) RejectNegative Joined UInteger Save
+Max number of bytes to compare.
misel
Target Report Mask(ISEL) Var(rs6000_isa_flags)
Generate isel instructions.
-misel=no
-Target RejectNegative Alias(misel) NegativeAlias Warn(%<-misel=no%> is deprecated; use %<-mno-isel%> instead)
-Deprecated option. Use -mno-isel instead.
-
-misel=yes
-Target RejectNegative Alias(misel) Warn(%<-misel=yes%> is deprecated; use %<-misel%> instead)
-Deprecated option. Use -misel instead.
-
mdebug=
Target RejectNegative Joined
-mdebug= Enable debug output.
@@ -484,7 +476,7 @@ Target Report Mask(CRYPTO) Var(rs6000_isa_flags)
Use ISA 2.07 Category:Vector.AES and Category:Vector.SHA2 instructions.
mdirect-move
-Target Undocumented Mask(DIRECT_MOVE) Var(rs6000_isa_flags) Ignore Warn(%qs is deprecated)
+Target Undocumented Mask(DIRECT_MOVE) Var(rs6000_isa_flags) Deprecated
mhtm
Target Report Mask(HTM) Var(rs6000_isa_flags)
diff --git a/gcc/config/rs6000/sync.md b/gcc/config/rs6000/sync.md
index 74bc407..ee98049 100644
--- a/gcc/config/rs6000/sync.md
+++ b/gcc/config/rs6000/sync.md
@@ -132,8 +132,7 @@
"TARGET_SYNC_TI
&& !reg_mentioned_p (operands[0], operands[1])"
"lq %0,%1"
- [(set_attr "type" "load")
- (set_attr "length" "4")])
+ [(set_attr "type" "load")])
(define_expand "atomic_load<mode>"
[(set (match_operand:AINT 0 "register_operand") ;; output
@@ -196,8 +195,7 @@
[(match_operand:PTI 1 "quad_int_reg_operand" "r")] UNSPEC_LSQ))]
"TARGET_SYNC_TI"
"stq %1,%0"
- [(set_attr "type" "store")
- (set_attr "length" "4")])
+ [(set_attr "type" "store")])
(define_expand "atomic_store<mode>"
[(set (match_operand:AINT 0 "memory_operand") ;; memory
diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
index de2fa78..e296be9 100644
--- a/gcc/config/rs6000/vsx.md
+++ b/gcc/config/rs6000/vsx.md
@@ -1412,7 +1412,7 @@
}
})
-(define_insn "*vsx_ld_elemrev_v16qi_internal"
+(define_insn "vsx_ld_elemrev_v16qi_internal"
[(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
(vec_select:V16QI
(match_operand:V16QI 1 "memory_operand" "Z")
@@ -3265,10 +3265,9 @@
"VECTOR_MEM_VSX_P (<MODE>mode)"
"@
stfd%U0%X0 %1,%0
- stxsd%U0x %x1,%y0
+ stxsdx %x1,%y0
stxsd %1,%0"
- [(set_attr "type" "fpstore")
- (set_attr "length" "4")])
+ [(set_attr "type" "fpstore")])
;; Variable V2DI/V2DF extract shift
(define_insn "vsx_vslo_<mode>"
@@ -5052,6 +5051,22 @@
"vcmpnezb %0,%1,%2"
[(set_attr "type" "vecsimple")])
+;; Vector Compare Not Equal or Zero Byte predicate or record-form
+(define_insn "vcmpnezb_p"
+ [(set (reg:CC CR6_REGNO)
+ (unspec:CC
+ [(match_operand:V16QI 1 "altivec_register_operand" "v")
+ (match_operand:V16QI 2 "altivec_register_operand" "v")]
+ UNSPEC_VCMPNEZB))
+ (set (match_operand:V16QI 0 "altivec_register_operand" "=v")
+ (unspec:V16QI
+ [(match_dup 1)
+ (match_dup 2)]
+ UNSPEC_VCMPNEZB))]
+ "TARGET_P9_VECTOR"
+ "vcmpnezb. %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
;; Vector Compare Not Equal Half Word (specified/not+eq:)
(define_insn "vcmpneh"
[(set (match_operand:V8HI 0 "altivec_register_operand" "=v")
diff --git a/gcc/config/rs6000/xmmintrin.h b/gcc/config/rs6000/xmmintrin.h
index 43d03ea..11ecbd8 100644
--- a/gcc/config/rs6000/xmmintrin.h
+++ b/gcc/config/rs6000/xmmintrin.h
@@ -57,6 +57,9 @@
#ifndef _XMMINTRIN_H_INCLUDED
#define _XMMINTRIN_H_INCLUDED
+/* Define four value permute mask */
+#define _MM_SHUFFLE(w,x,y,z) (((w) << 6) | ((x) << 4) | ((y) << 2) | (z))
+
#include <altivec.h>
/* Avoid collisions between altivec.h and strict adherence to C++ and
diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c
index c2669ed..5f5cc51 100644
--- a/gcc/config/rx/rx.c
+++ b/gcc/config/rx/rx.c
@@ -3796,6 +3796,9 @@ rx_modes_tieable_p (machine_mode mode1, machine_mode mode2)
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS rx_rtx_costs
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-rx.h"
diff --git a/gcc/config/s390/2064.md b/gcc/config/s390/2064.md
index 9c9d62b..4a73446 100644
--- a/gcc/config/s390/2064.md
+++ b/gcc/config/s390/2064.md
@@ -39,63 +39,61 @@
;; |
;; wr
-;; This scheduler description is also used for the g5 and g6.
-
(define_automaton "z_ipu")
(define_cpu_unit "z_e1" "z_ipu")
(define_cpu_unit "z_wr" "z_ipu")
(define_insn_reservation "z_la" 1
- (and (eq_attr "cpu" "z900,g5,g6")
+ (and (eq_attr "cpu" "z900")
(eq_attr "type" "la"))
"z_e1,z_wr")
(define_insn_reservation "z_larl" 1
- (and (eq_attr "cpu" "z900,g5,g6")
+ (and (eq_attr "cpu" "z900")
(eq_attr "type" "larl"))
"z_e1,z_wr")
(define_insn_reservation "z_load" 1
- (and (eq_attr "cpu" "z900,g5,g6")
+ (and (eq_attr "cpu" "z900")
(eq_attr "type" "load"))
"z_e1,z_wr")
(define_insn_reservation "z_store" 1
- (and (eq_attr "cpu" "z900,g5,g6")
+ (and (eq_attr "cpu" "z900")
(eq_attr "type" "store"))
"z_e1,z_wr")
(define_insn_reservation "z_sem" 2
- (and (eq_attr "cpu" "z900,g5,g6")
+ (and (eq_attr "cpu" "z900")
(eq_attr "type" "sem"))
"z_e1*2,z_wr")
(define_insn_reservation "z_call" 5
- (and (eq_attr "cpu" "z900,g5,g6")
+ (and (eq_attr "cpu" "z900")
(eq_attr "type" "jsr"))
"z_e1*5,z_wr")
(define_insn_reservation "z_mul" 5
- (and (eq_attr "cpu" "g5,g6,z900")
+ (and (eq_attr "cpu" "z900")
(eq_attr "type" "imulsi,imulhi"))
"z_e1*5,z_wr")
(define_insn_reservation "z_inf" 10
- (and (eq_attr "cpu" "g5,g6,z900")
+ (and (eq_attr "cpu" "z900")
(eq_attr "type" "idiv,imuldi"))
"z_e1*10,z_wr")
;; For everything else we check the atype flag.
(define_insn_reservation "z_int" 1
- (and (eq_attr "cpu" "z900,g5,g6")
+ (and (eq_attr "cpu" "z900")
(and (not (eq_attr "type" "la,larl,load,store,jsr"))
(eq_attr "atype" "reg")))
"z_e1,z_wr")
(define_insn_reservation "z_agen" 1
- (and (eq_attr "cpu" "z900,g5,g6")
+ (and (eq_attr "cpu" "z900")
(and (not (eq_attr "type" "la,larl,load,store,jsr"))
(eq_attr "atype" "agen")))
"z_e1,z_wr")
diff --git a/gcc/config/s390/constraints.md b/gcc/config/s390/constraints.md
index b18622d..b8ba851 100644
--- a/gcc/config/s390/constraints.md
+++ b/gcc/config/s390/constraints.md
@@ -51,7 +51,7 @@
;; M -- Constant integer with a value of 0x7fffffff.
;; N -- Multiple letter constraint followed by 4 parameter letters.
;; 0..9,x: number of the part counting from most to least significant
-;; H,Q: mode of the part
+;; S,H,Q: mode of the part
;; D,S,H: mode of the containing operand
;; 0,F: value of the other parts (F - all bits set)
;; --
@@ -204,7 +204,7 @@
;; N -- Multiple letter constraint followed by 4 parameter letters.
;; 0..9,x: number of the part counting from most to least significant
-;; H,Q: mode of the part
+;; S,H,Q: mode of the part
;; D,S,H: mode of the containing operand
;; 0,F: value of the other parts (F = all bits set)
;;
@@ -226,6 +226,18 @@
(match_test "s390_N_constraint_str (\"xQS0\", ival)")))
+(define_constraint "NxHD0"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"xHD0\", ival)")))
+
+
+(define_constraint "NxSD0"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"xSD0\", ival)")))
+
+
(define_constraint "NxQD0"
"@internal"
(and (match_code "const_int")
diff --git a/gcc/config/s390/driver-native.c b/gcc/config/s390/driver-native.c
index 3793f8a..4b2dd6e 100644
--- a/gcc/config/s390/driver-native.c
+++ b/gcc/config/s390/driver-native.c
@@ -86,8 +86,6 @@ s390_host_detect_local_cpu (int argc, const char **argv)
machine_id = strtol (p, NULL, 16);
switch (machine_id)
{
- /* g5 and g6 default to z900 */
- case 0x9672:
case 0x2064:
case 0x2066:
cpu = "z900";
diff --git a/gcc/config/s390/linux.h b/gcc/config/s390/linux.h
index 525c17c..480030a 100644
--- a/gcc/config/s390/linux.h
+++ b/gcc/config/s390/linux.h
@@ -55,7 +55,6 @@ along with GCC; see the file COPYING3. If not see
#undef ASM_SPEC
#define ASM_SPEC \
"%{m31&m64}%{mesa&mzarch}%{march=z*}" \
- "%{march=arch3:-march=g5}" \
"%{march=arch5:-march=z900}" \
"%{march=arch6:-march=z990}" \
"%{march=arch7:-march=z9-ec}" \
diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md
index a5b1fcb..98a824e 100644
--- a/gcc/config/s390/predicates.md
+++ b/gcc/config/s390/predicates.md
@@ -534,3 +534,15 @@
unsigned HOST_WIDE_INT val = INTVAL (op);
return val <= 128 && val % 8 == 0;
})
+
+;; Certain operations (e.g. CS) cannot access SYMBOL_REF directly, it needs to
+;; be loaded into some register first. In theory, if we put a SYMBOL_REF into
+;; a corresponding insn anyway, reload will generate a load for it, but, when
+;; coupled with constant propagation, this will lead to an inefficient code
+;; (see PR 80080).
+
+(define_predicate "nonsym_memory_operand"
+ (match_code "mem")
+{
+ return memory_operand (op, mode) && !contains_symbol_ref_p (op);
+})
diff --git a/gcc/config/s390/s390-c.c b/gcc/config/s390/s390-c.c
index 4a72d49..286b8c3 100644
--- a/gcc/config/s390/s390-c.c
+++ b/gcc/config/s390/s390-c.c
@@ -233,7 +233,7 @@ s390_macro_to_expand (cpp_reader *pfile, const cpp_token *tok)
rid_code = (enum rid)(ident->rid_code);
- if (ident->type == NT_MACRO)
+ if (cpp_macro_p (ident))
{
/* Now actually fetch the tokens we "peeked" before and do a
lookahead for the next. */
@@ -335,15 +335,8 @@ s390_cpu_cpp_builtins_internal (cpp_reader *pfile,
"__bool");
{
char macro_def[64];
- int arch_level;
gcc_assert (s390_arch != PROCESSOR_NATIVE);
- arch_level = (int)s390_arch + 3;
- if (s390_arch >= PROCESSOR_2094_Z9_EC)
- /* Z9_EC has the same level as Z9_109. */
- arch_level--;
- /* Review when a new arch is added and increase the value. */
- char dummy[(PROCESSOR_max > 12) ? -1 : 1] __attribute__((unused));
- sprintf (macro_def, "__ARCH__=%d", arch_level);
+ sprintf (macro_def, "__ARCH__=%d", processor_table[s390_arch].arch_level);
cpp_undef (pfile, "__ARCH__");
cpp_define (pfile, macro_def);
}
diff --git a/gcc/config/s390/s390-opts.h b/gcc/config/s390/s390-opts.h
index aaecca7..3c06432 100644
--- a/gcc/config/s390/s390-opts.h
+++ b/gcc/config/s390/s390-opts.h
@@ -20,16 +20,14 @@ along with GCC; see the file COPYING3. If not see
#ifndef S390_OPTS_H
#define S390_OPTS_H
-/* Which processor to generate code or schedule for. The cpu attribute
+/* Which processor to generate code or schedule for. The `cpu' attribute
defines a list that mirrors this list, so changes to s390.md must be
- made at the same time. The enumeration must also be kept in snyc with
- processor_table in s390.c (the enumeration values are used as indices into
- the table). */
+ made at the same time. The enumeration must also be kept in sync with
+ `processor_table' and `processor_flags_table' in s390.c (the enumeration
+ values are used as indices into these tables). */
enum processor_type
{
- PROCESSOR_9672_G5,
- PROCESSOR_9672_G6,
PROCESSOR_2064_Z900,
PROCESSOR_2084_Z990,
PROCESSOR_2094_Z9_109,
diff --git a/gcc/config/s390/s390-passes.def b/gcc/config/s390/s390-passes.def
new file mode 100644
index 0000000..6d88d01
--- /dev/null
+++ b/gcc/config/s390/s390-passes.def
@@ -0,0 +1,20 @@
+/* Description of target passes for S/390.
+ Copyright (C) 2018 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/>. */
+
+ INSERT_PASS_BEFORE (pass_thread_prologue_and_epilogue, 1, pass_s390_early_mach);
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index 46f0743..45fce6c 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -165,3 +165,9 @@ extern void s390_register_target_pragmas (void);
/* Routines for s390-c.c */
extern bool s390_const_operand_ok (tree, int, int, tree);
+
+/* Pass management. */
+namespace gcc { class context; }
+class rtl_opt_pass;
+
+extern rtl_opt_pass *make_pass_s390_early_mach (gcc::context *ctxt);
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index a579e9d..71039fe 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -326,29 +326,18 @@ struct processor_costs zEC12_cost =
COSTS_N_INSNS (160), /* DSGR cracked */
};
-static struct
-{
- /* The preferred name to be used in user visible output. */
- const char *const name;
- /* CPU name as it should be passed to Binutils via .machine */
- const char *const binutils_name;
- const enum processor_type processor;
- const struct processor_costs *cost;
-}
-const processor_table[] =
-{
- { "g5", "g5", PROCESSOR_9672_G5, &z900_cost },
- { "g6", "g6", PROCESSOR_9672_G6, &z900_cost },
- { "z900", "z900", PROCESSOR_2064_Z900, &z900_cost },
- { "z990", "z990", PROCESSOR_2084_Z990, &z990_cost },
- { "z9-109", "z9-109", PROCESSOR_2094_Z9_109, &z9_109_cost },
- { "z9-ec", "z9-ec", PROCESSOR_2094_Z9_EC, &z9_109_cost },
- { "z10", "z10", PROCESSOR_2097_Z10, &z10_cost },
- { "z196", "z196", PROCESSOR_2817_Z196, &z196_cost },
- { "zEC12", "zEC12", PROCESSOR_2827_ZEC12, &zEC12_cost },
- { "z13", "z13", PROCESSOR_2964_Z13, &zEC12_cost },
- { "z14", "arch12", PROCESSOR_3906_Z14, &zEC12_cost },
- { "native", "", PROCESSOR_NATIVE, NULL }
+const struct s390_processor processor_table[] =
+{
+ { "z900", "z900", PROCESSOR_2064_Z900, &z900_cost, 5 },
+ { "z990", "z990", PROCESSOR_2084_Z990, &z990_cost, 6 },
+ { "z9-109", "z9-109", PROCESSOR_2094_Z9_109, &z9_109_cost, 7 },
+ { "z9-ec", "z9-ec", PROCESSOR_2094_Z9_EC, &z9_109_cost, 7 },
+ { "z10", "z10", PROCESSOR_2097_Z10, &z10_cost, 8 },
+ { "z196", "z196", PROCESSOR_2817_Z196, &z196_cost, 9 },
+ { "zEC12", "zEC12", PROCESSOR_2827_ZEC12, &zEC12_cost, 10 },
+ { "z13", "z13", PROCESSOR_2964_Z13, &zEC12_cost, 11 },
+ { "z14", "arch12", PROCESSOR_3906_Z14, &zEC12_cost, 12 },
+ { "native", "", PROCESSOR_NATIVE, NULL, 0 }
};
extern int reload_completed;
@@ -390,6 +379,11 @@ static unsigned vfu_longrunning[NUM_SIDES];
base and index are registers of the class ADDR_REGS,
displacement is an unsigned 12-bit immediate constant. */
+/* The max number of insns of backend generated memset/memcpy/memcmp
+ loops. This value is used in the unroll adjust hook to detect such
+ loops. Current max is 9 coming from the memcmp loop. */
+#define BLOCK_MEM_OPS_LOOP_INSNS 9
+
struct s390_address
{
rtx base;
@@ -426,11 +420,11 @@ struct s390_address
#define CONST_OK_FOR_K(x) \
CONST_OK_FOR_CONSTRAINT_P((x), 'K', "K")
#define CONST_OK_FOR_Os(x) \
- CONST_OK_FOR_CONSTRAINT_P((x), 'O', "Os")
+ CONST_OK_FOR_CONSTRAINT_P((x), 'O', "Os")
#define CONST_OK_FOR_Op(x) \
- CONST_OK_FOR_CONSTRAINT_P((x), 'O', "Op")
+ CONST_OK_FOR_CONSTRAINT_P((x), 'O', "Op")
#define CONST_OK_FOR_On(x) \
- CONST_OK_FOR_CONSTRAINT_P((x), 'O', "On")
+ CONST_OK_FOR_CONSTRAINT_P((x), 'O', "On")
#define REGNO_PAIR_OK(REGNO, MODE) \
(s390_hard_regno_nregs ((REGNO), (MODE)) == 1 || !((REGNO) & 1))
@@ -925,7 +919,7 @@ s390_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
/* Record the vector mode used for an element selector. This assumes:
1. There is no builtin with two different vector modes and an element selector
- 2. The element selector comes after the vector type it is referring to.
+ 2. The element selector comes after the vector type it is referring to.
This currently the true for all the builtins but FIXME we
should better check for that. */
if (VECTOR_MODE_P (insn_op->mode))
@@ -988,7 +982,7 @@ s390_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
break;
case 1:
if (nonvoid)
- pat = GEN_FCN (icode) (target, op[0]);
+ pat = GEN_FCN (icode) (target, op[0]);
else
pat = GEN_FCN (icode) (op[0]);
break;
@@ -1338,7 +1332,7 @@ s390_cc_modes_compatible (machine_mode m1, machine_mode m2)
case E_CCZmode:
if (m2 == CCUmode || m2 == CCTmode || m2 == CCZ1mode
|| m2 == CCSmode || m2 == CCSRmode || m2 == CCURmode)
- return m2;
+ return m2;
return VOIDmode;
case E_CCSmode:
@@ -1398,20 +1392,20 @@ s390_match_ccmode_set (rtx set, machine_mode req_mode)
case E_CCVFHmode:
case E_CCVFHEmode:
if (req_mode != set_mode)
- return 0;
+ return 0;
break;
case E_CCZmode:
if (req_mode != CCSmode && req_mode != CCUmode && req_mode != CCTmode
&& req_mode != CCSRmode && req_mode != CCURmode
&& req_mode != CCZ1mode)
- return 0;
+ return 0;
break;
case E_CCAPmode:
case E_CCANmode:
if (req_mode != CCAmode)
- return 0;
+ return 0;
break;
default:
@@ -1440,12 +1434,12 @@ s390_match_ccmode (rtx_insn *insn, machine_mode req_mode)
if (GET_CODE (PATTERN (insn)) == PARALLEL)
for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
- {
- rtx set = XVECEXP (PATTERN (insn), 0, i);
- if (GET_CODE (set) == SET)
- if (!s390_match_ccmode_set (set, req_mode))
- return false;
- }
+ {
+ rtx set = XVECEXP (PATTERN (insn), 0, i);
+ if (GET_CODE (set) == SET)
+ if (!s390_match_ccmode_set (set, req_mode))
+ return false;
+ }
return true;
}
@@ -1485,7 +1479,7 @@ s390_tm_ccmode (rtx op1, rtx op2, bool mixed)
bit1 = exact_log2 (INTVAL (op2));
bit0 = exact_log2 (INTVAL (op1) ^ INTVAL (op2));
if (bit0 != -1 && bit1 != -1)
- return bit0 > bit1 ? CCT1mode : CCT2mode;
+ return bit0 > bit1 ? CCT1mode : CCT2mode;
}
return VOIDmode;
@@ -1522,7 +1516,7 @@ s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1)
{
/* Relax CCTmode to CCZmode to allow fall-back to AND
if that turns out to be beneficial. */
- return ccmode == CCTmode ? CCZmode : ccmode;
+ return ccmode == CCTmode ? CCZmode : ccmode;
}
}
@@ -1549,11 +1543,11 @@ s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1)
&& GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)
return CCAPmode;
- /* If constants are involved in an add instruction it is possible to use
- the resulting cc for comparisons with zero. Knowing the sign of the
+ /* If constants are involved in an add instruction it is possible to use
+ the resulting cc for comparisons with zero. Knowing the sign of the
constant the overflow behavior gets predictable. e.g.:
- int a, b; if ((b = a + c) > 0)
- with c as a constant value: c < 0 -> CCAN and c >= 0 -> CCAP */
+ int a, b; if ((b = a + c) > 0)
+ with c as a constant value: c < 0 -> CCAN and c >= 0 -> CCAP */
if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 1)) == CONST_INT
&& (CONST_OK_FOR_K (INTVAL (XEXP (op0, 1)))
|| (CONST_OK_FOR_CONSTRAINT_P (INTVAL (XEXP (op0, 1)), 'O', "Os")
@@ -1658,8 +1652,8 @@ s390_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
&& (GET_MODE_SIZE (GET_MODE (inner))
>= GET_MODE_SIZE (GET_MODE (SUBREG_REG (inner))))
&& ((INTVAL (mask)
- & GET_MODE_MASK (GET_MODE (inner))
- & ~GET_MODE_MASK (GET_MODE (SUBREG_REG (inner))))
+ & GET_MODE_MASK (GET_MODE (inner))
+ & ~GET_MODE_MASK (GET_MODE (SUBREG_REG (inner))))
== 0))
inner = SUBREG_REG (inner);
@@ -1744,8 +1738,8 @@ s390_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
{
/* For CCRAWmode put the required cc mask into the second
operand. */
- if (GET_MODE (XVECEXP (*op0, 0, 0)) == CCRAWmode
- && INTVAL (*op1) >= 0 && INTVAL (*op1) <= 3)
+ if (GET_MODE (XVECEXP (*op0, 0, 0)) == CCRAWmode
+ && INTVAL (*op1) >= 0 && INTVAL (*op1) <= 3)
*op1 = gen_rtx_CONST_INT (VOIDmode, 1 << (3 - INTVAL (*op1)));
*op0 = XVECEXP (*op0, 0, 0);
*code = new_code;
@@ -1762,7 +1756,7 @@ s390_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
&& *op1 == const0_rtx)
{
if ((*code == EQ && GET_CODE (*op0) == NE)
- || (*code == NE && GET_CODE (*op0) == EQ))
+ || (*code == NE && GET_CODE (*op0) == EQ))
*code = EQ;
else
*code = NE;
@@ -1831,6 +1825,21 @@ s390_emit_compare (enum rtx_code code, rtx op0, rtx op1)
return gen_rtx_fmt_ee (code, VOIDmode, cc, const0_rtx);
}
+/* If MEM is not a legitimate compare-and-swap memory operand, return a new
+ MEM, whose address is a pseudo containing the original MEM's address. */
+
+static rtx
+s390_legitimize_cs_operand (rtx mem)
+{
+ rtx tmp;
+
+ if (!contains_symbol_ref_p (mem))
+ return mem;
+ tmp = gen_reg_rtx (Pmode);
+ emit_move_insn (tmp, copy_rtx (XEXP (mem, 0)));
+ return change_address (mem, VOIDmode, tmp);
+}
+
/* Emit a SImode compare and swap instruction setting MEM to NEW_RTX if OLD
matches CMP.
Return the correct condition RTL to be placed in the IF_THEN_ELSE of the
@@ -1842,6 +1851,7 @@ s390_emit_compare_and_swap (enum rtx_code code, rtx old, rtx mem,
{
rtx cc;
+ mem = s390_legitimize_cs_operand (mem);
cc = gen_rtx_REG (ccmode, CC_REGNUM);
switch (GET_MODE (mem))
{
@@ -1905,65 +1915,65 @@ s390_branch_condition_mask (rtx code)
case E_CCZmode:
case E_CCZ1mode:
switch (GET_CODE (code))
- {
- case EQ: return CC0;
+ {
+ case EQ: return CC0;
case NE: return CC1 | CC2 | CC3;
default: return -1;
- }
+ }
break;
case E_CCT1mode:
switch (GET_CODE (code))
- {
- case EQ: return CC1;
+ {
+ case EQ: return CC1;
case NE: return CC0 | CC2 | CC3;
default: return -1;
- }
+ }
break;
case E_CCT2mode:
switch (GET_CODE (code))
- {
- case EQ: return CC2;
+ {
+ case EQ: return CC2;
case NE: return CC0 | CC1 | CC3;
default: return -1;
- }
+ }
break;
case E_CCT3mode:
switch (GET_CODE (code))
- {
- case EQ: return CC3;
+ {
+ case EQ: return CC3;
case NE: return CC0 | CC1 | CC2;
default: return -1;
- }
+ }
break;
case E_CCLmode:
switch (GET_CODE (code))
- {
- case EQ: return CC0 | CC2;
+ {
+ case EQ: return CC0 | CC2;
case NE: return CC1 | CC3;
default: return -1;
- }
+ }
break;
case E_CCL1mode:
switch (GET_CODE (code))
- {
+ {
case LTU: return CC2 | CC3; /* carry */
case GEU: return CC0 | CC1; /* no carry */
default: return -1;
- }
+ }
break;
case E_CCL2mode:
switch (GET_CODE (code))
- {
+ {
case GTU: return CC0 | CC1; /* borrow */
case LEU: return CC2 | CC3; /* no borrow */
default: return -1;
- }
+ }
break;
case E_CCL3mode:
@@ -1980,96 +1990,96 @@ s390_branch_condition_mask (rtx code)
case E_CCUmode:
switch (GET_CODE (code))
- {
- case EQ: return CC0;
- case NE: return CC1 | CC2 | CC3;
- case LTU: return CC1;
- case GTU: return CC2;
- case LEU: return CC0 | CC1;
- case GEU: return CC0 | CC2;
+ {
+ case EQ: return CC0;
+ case NE: return CC1 | CC2 | CC3;
+ case LTU: return CC1;
+ case GTU: return CC2;
+ case LEU: return CC0 | CC1;
+ case GEU: return CC0 | CC2;
default: return -1;
- }
+ }
break;
case E_CCURmode:
switch (GET_CODE (code))
- {
- case EQ: return CC0;
- case NE: return CC2 | CC1 | CC3;
- case LTU: return CC2;
- case GTU: return CC1;
- case LEU: return CC0 | CC2;
- case GEU: return CC0 | CC1;
+ {
+ case EQ: return CC0;
+ case NE: return CC2 | CC1 | CC3;
+ case LTU: return CC2;
+ case GTU: return CC1;
+ case LEU: return CC0 | CC2;
+ case GEU: return CC0 | CC1;
default: return -1;
- }
+ }
break;
case E_CCAPmode:
switch (GET_CODE (code))
- {
- case EQ: return CC0;
- case NE: return CC1 | CC2 | CC3;
- case LT: return CC1 | CC3;
- case GT: return CC2;
- case LE: return CC0 | CC1 | CC3;
- case GE: return CC0 | CC2;
+ {
+ case EQ: return CC0;
+ case NE: return CC1 | CC2 | CC3;
+ case LT: return CC1 | CC3;
+ case GT: return CC2;
+ case LE: return CC0 | CC1 | CC3;
+ case GE: return CC0 | CC2;
default: return -1;
- }
+ }
break;
case E_CCANmode:
switch (GET_CODE (code))
- {
- case EQ: return CC0;
- case NE: return CC1 | CC2 | CC3;
- case LT: return CC1;
- case GT: return CC2 | CC3;
- case LE: return CC0 | CC1;
- case GE: return CC0 | CC2 | CC3;
+ {
+ case EQ: return CC0;
+ case NE: return CC1 | CC2 | CC3;
+ case LT: return CC1;
+ case GT: return CC2 | CC3;
+ case LE: return CC0 | CC1;
+ case GE: return CC0 | CC2 | CC3;
default: return -1;
- }
+ }
break;
case E_CCSmode:
switch (GET_CODE (code))
- {
- case EQ: return CC0;
- case NE: return CC1 | CC2 | CC3;
- case LT: return CC1;
- case GT: return CC2;
- case LE: return CC0 | CC1;
- case GE: return CC0 | CC2;
+ {
+ case EQ: return CC0;
+ case NE: return CC1 | CC2 | CC3;
+ case LT: return CC1;
+ case GT: return CC2;
+ case LE: return CC0 | CC1;
+ case GE: return CC0 | CC2;
case UNORDERED: return CC3;
case ORDERED: return CC0 | CC1 | CC2;
case UNEQ: return CC0 | CC3;
- case UNLT: return CC1 | CC3;
- case UNGT: return CC2 | CC3;
- case UNLE: return CC0 | CC1 | CC3;
- case UNGE: return CC0 | CC2 | CC3;
+ case UNLT: return CC1 | CC3;
+ case UNGT: return CC2 | CC3;
+ case UNLE: return CC0 | CC1 | CC3;
+ case UNGE: return CC0 | CC2 | CC3;
case LTGT: return CC1 | CC2;
default: return -1;
- }
+ }
break;
case E_CCSRmode:
switch (GET_CODE (code))
- {
- case EQ: return CC0;
- case NE: return CC2 | CC1 | CC3;
- case LT: return CC2;
- case GT: return CC1;
- case LE: return CC0 | CC2;
- case GE: return CC0 | CC1;
+ {
+ case EQ: return CC0;
+ case NE: return CC2 | CC1 | CC3;
+ case LT: return CC2;
+ case GT: return CC1;
+ case LE: return CC0 | CC2;
+ case GE: return CC0 | CC1;
case UNORDERED: return CC3;
case ORDERED: return CC0 | CC2 | CC1;
case UNEQ: return CC0 | CC3;
- case UNLT: return CC2 | CC3;
- case UNGT: return CC1 | CC3;
- case UNLE: return CC0 | CC2 | CC3;
- case UNGE: return CC0 | CC1 | CC3;
+ case UNLT: return CC2 | CC3;
+ case UNGT: return CC1 | CC3;
+ case UNLE: return CC0 | CC2 | CC3;
+ case UNGE: return CC0 | CC1 | CC3;
case LTGT: return CC2 | CC1;
default: return -1;
- }
+ }
break;
/* Vector comparison modes. */
@@ -2521,7 +2531,7 @@ s390_split_ok_p (rtx dst, rtx src, machine_mode mode, int first_subword)
{
rtx subreg = operand_subword (dst, first_subword, 0, mode);
if (reg_overlap_mentioned_p (subreg, src))
- return false;
+ return false;
}
return true;
@@ -2621,7 +2631,7 @@ s390_expand_logical_operator (enum rtx_code code, machine_mode mode,
else if (REG_P (dst))
dst = gen_rtx_SUBREG (wmode, dst, 0);
else
- dst = gen_reg_rtx (wmode);
+ dst = gen_reg_rtx (wmode);
if (GET_CODE (src1) == SUBREG
&& (tem = simplify_subreg (wmode, src1, mode, 0)) != 0)
@@ -2743,7 +2753,7 @@ s390_short_displacement (rtx disp)
if (GET_CODE (disp) == CONST
&& GET_CODE (XEXP (disp, 0)) == UNSPEC
&& (XINT (XEXP (disp, 0), 1) == UNSPEC_GOT
- || XINT (XEXP (disp, 0), 1) == UNSPEC_GOTNTPOFF))
+ || XINT (XEXP (disp, 0), 1) == UNSPEC_GOTNTPOFF))
return false;
/* All other symbolic constants are literal pool references,
@@ -2754,6 +2764,58 @@ s390_short_displacement (rtx disp)
return false;
}
+/* Attempts to split `ref', which should be UNSPEC_LTREF, into (base + `disp').
+ If successful, also determines the
+ following characteristics of `ref': `is_ptr' - whether it can be an
+ LA argument, `is_base_ptr' - whether the resulting base is a well-known
+ base register (stack/frame pointer, etc), `is_pool_ptr` - whether it is
+ considered a literal pool pointer for purposes of avoiding two different
+ literal pool pointers per insn during or after reload (`B' constraint). */
+static bool
+s390_decompose_constant_pool_ref (rtx *ref, rtx *disp, bool *is_ptr,
+ bool *is_base_ptr, bool *is_pool_ptr)
+{
+ if (!*ref)
+ return true;
+
+ if (GET_CODE (*ref) == UNSPEC)
+ switch (XINT (*ref, 1))
+ {
+ case UNSPEC_LTREF:
+ if (!*disp)
+ *disp = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (1, XVECEXP (*ref, 0, 0)),
+ UNSPEC_LTREL_OFFSET);
+ else
+ return false;
+
+ *ref = XVECEXP (*ref, 0, 1);
+ break;
+
+ default:
+ return false;
+ }
+
+ if (!REG_P (*ref) || GET_MODE (*ref) != Pmode)
+ return false;
+
+ if (REGNO (*ref) == STACK_POINTER_REGNUM
+ || REGNO (*ref) == FRAME_POINTER_REGNUM
+ || ((reload_completed || reload_in_progress)
+ && frame_pointer_needed
+ && REGNO (*ref) == HARD_FRAME_POINTER_REGNUM)
+ || REGNO (*ref) == ARG_POINTER_REGNUM
+ || (flag_pic
+ && REGNO (*ref) == PIC_OFFSET_TABLE_REGNUM))
+ *is_ptr = *is_base_ptr = true;
+
+ if ((reload_completed || reload_in_progress)
+ && *ref == cfun->machine->base_reg)
+ *is_ptr = *is_base_ptr = *is_pool_ptr = true;
+
+ return true;
+}
+
/* Decompose a RTL expression ADDR for a memory address into
its components, returned in OUT.
@@ -2865,96 +2927,14 @@ s390_decompose_address (rtx addr, struct s390_address *out)
}
/* Validate base register. */
- if (base)
- {
- if (GET_CODE (base) == UNSPEC)
- switch (XINT (base, 1))
- {
- case UNSPEC_LTREF:
- if (!disp)
- disp = gen_rtx_UNSPEC (Pmode,
- gen_rtvec (1, XVECEXP (base, 0, 0)),
- UNSPEC_LTREL_OFFSET);
- else
- return false;
-
- base = XVECEXP (base, 0, 1);
- break;
-
- case UNSPEC_LTREL_BASE:
- if (XVECLEN (base, 0) == 1)
- base = fake_pool_base, literal_pool = true;
- else
- base = XVECEXP (base, 0, 1);
- break;
-
- default:
- return false;
- }
-
- if (!REG_P (base) || GET_MODE (base) != Pmode)
- return false;
-
- if (REGNO (base) == STACK_POINTER_REGNUM
- || REGNO (base) == FRAME_POINTER_REGNUM
- || ((reload_completed || reload_in_progress)
- && frame_pointer_needed
- && REGNO (base) == HARD_FRAME_POINTER_REGNUM)
- || REGNO (base) == ARG_POINTER_REGNUM
- || (flag_pic
- && REGNO (base) == PIC_OFFSET_TABLE_REGNUM))
- pointer = base_ptr = true;
-
- if ((reload_completed || reload_in_progress)
- && base == cfun->machine->base_reg)
- pointer = base_ptr = literal_pool = true;
- }
+ if (!s390_decompose_constant_pool_ref (&base, &disp, &pointer, &base_ptr,
+ &literal_pool))
+ return false;
/* Validate index register. */
- if (indx)
- {
- if (GET_CODE (indx) == UNSPEC)
- switch (XINT (indx, 1))
- {
- case UNSPEC_LTREF:
- if (!disp)
- disp = gen_rtx_UNSPEC (Pmode,
- gen_rtvec (1, XVECEXP (indx, 0, 0)),
- UNSPEC_LTREL_OFFSET);
- else
- return false;
-
- indx = XVECEXP (indx, 0, 1);
- break;
-
- case UNSPEC_LTREL_BASE:
- if (XVECLEN (indx, 0) == 1)
- indx = fake_pool_base, literal_pool = true;
- else
- indx = XVECEXP (indx, 0, 1);
- break;
-
- default:
- return false;
- }
-
- if (!REG_P (indx) || GET_MODE (indx) != Pmode)
- return false;
-
- if (REGNO (indx) == STACK_POINTER_REGNUM
- || REGNO (indx) == FRAME_POINTER_REGNUM
- || ((reload_completed || reload_in_progress)
- && frame_pointer_needed
- && REGNO (indx) == HARD_FRAME_POINTER_REGNUM)
- || REGNO (indx) == ARG_POINTER_REGNUM
- || (flag_pic
- && REGNO (indx) == PIC_OFFSET_TABLE_REGNUM))
- pointer = indx_ptr = true;
-
- if ((reload_completed || reload_in_progress)
- && indx == cfun->machine->base_reg)
- pointer = indx_ptr = literal_pool = true;
- }
+ if (!s390_decompose_constant_pool_ref (&indx, &disp, &pointer, &indx_ptr,
+ &literal_pool))
+ return false;
/* Prefer to use pointer as base, not index. */
if (base && indx && !base_ptr
@@ -2997,14 +2977,14 @@ s390_decompose_address (rtx addr, struct s390_address *out)
pointer = true;
/* In the small-PIC case, the linker converts @GOT
- and @GOTNTPOFF offsets to possible displacements. */
+ and @GOTNTPOFF offsets to possible displacements. */
if (GET_CODE (disp) == UNSPEC
- && (XINT (disp, 1) == UNSPEC_GOT
+ && (XINT (disp, 1) == UNSPEC_GOT
|| XINT (disp, 1) == UNSPEC_GOTNTPOFF)
&& flag_pic == 1)
- {
+ {
;
- }
+ }
/* Accept pool label offsets. */
else if (GET_CODE (disp) == UNSPEC
@@ -3014,7 +2994,7 @@ s390_decompose_address (rtx addr, struct s390_address *out)
/* Accept literal pool references. */
else if (GET_CODE (disp) == UNSPEC
&& XINT (disp, 1) == UNSPEC_LTREL_OFFSET)
- {
+ {
/* In case CSE pulled a non literal pool reference out of
the pool we have to reject the address. This is
especially important when loading the GOT pointer on non
@@ -3034,9 +3014,9 @@ s390_decompose_address (rtx addr, struct s390_address *out)
if (offset >= GET_MODE_SIZE (get_pool_mode (sym)))
return false;
- orig_disp = plus_constant (Pmode, orig_disp, offset);
+ orig_disp = plus_constant (Pmode, orig_disp, offset);
}
- }
+ }
else
return false;
@@ -3153,7 +3133,7 @@ s390_loadrelative_operand_p (rtx addr, rtx *symref, HOST_WIDE_INT *addend)
if ((GET_CODE (addr) == SYMBOL_REF && !CONSTANT_POOL_ADDRESS_P (addr))
|| (GET_CODE (addr) == UNSPEC
&& (XINT (addr, 1) == UNSPEC_GOTENT
- || (TARGET_CPU_ZARCH && XINT (addr, 1) == UNSPEC_PLT))))
+ || XINT (addr, 1) == UNSPEC_PLT)))
{
if (symref)
*symref = addr;
@@ -3409,7 +3389,7 @@ s390_float_const_zero_p (rtx value)
static int
s390_register_move_cost (machine_mode mode,
- reg_class_t from, reg_class_t to)
+ reg_class_t from, reg_class_t to)
{
/* On s390, copy between fprs and gprs is expensive. */
@@ -3597,8 +3577,7 @@ s390_rtx_costs (rtx x, machine_mode mode, int outer_code,
/* mulsidi case: mr, m */
*total = s390_cost->m;
else if (GET_CODE (left) == ZERO_EXTEND
- && GET_CODE (right) == ZERO_EXTEND
- && TARGET_CPU_ZARCH)
+ && GET_CODE (right) == ZERO_EXTEND)
/* umulsidi case: ml, mlr */
*total = s390_cost->ml;
else
@@ -3643,14 +3622,14 @@ s390_rtx_costs (rtx x, machine_mode mode, int outer_code,
case UDIV:
case UMOD:
- if (mode == TImode) /* 128 bit division */
+ if (mode == TImode) /* 128 bit division */
*total = s390_cost->dlgr;
else if (mode == DImode)
{
rtx right = XEXP (x, 1);
if (GET_CODE (right) == ZERO_EXTEND) /* 64 by 32 bit division */
*total = s390_cost->dlr;
- else /* 64 by 64 bit division */
+ else /* 64 by 64 bit division */
*total = s390_cost->dlgr;
}
else if (mode == SImode) /* 32 bit division */
@@ -3667,7 +3646,7 @@ s390_rtx_costs (rtx x, machine_mode mode, int outer_code,
*total = s390_cost->dsgfr;
else
*total = s390_cost->dr;
- else /* 64 by 64 bit division */
+ else /* 64 by 64 bit division */
*total = s390_cost->dsgr;
}
else if (mode == SImode) /* 32 bit division */
@@ -3906,7 +3885,7 @@ s390_legitimate_constant_p (machine_mode mode, rtx op)
return 1;
/* Accept immediate LARL operands. */
- if (TARGET_CPU_ZARCH && larl_operand (op, mode))
+ if (larl_operand (op, mode))
return 1;
/* Thread-local symbols are never legal constants. This is
@@ -3948,7 +3927,7 @@ s390_cannot_force_const_mem (machine_mode mode, rtx x)
case SYMBOL_REF:
/* 'Naked' TLS symbol references are never OK,
- non-TLS symbols are OK iff we are non-PIC. */
+ non-TLS symbols are OK iff we are non-PIC. */
if (tls_symbolic_operand (x))
return true;
else
@@ -3980,8 +3959,6 @@ s390_cannot_force_const_mem (machine_mode mode, rtx x)
/* If the literal pool shares the code section, be put
execute template placeholders into the pool as well. */
case UNSPEC_INSN:
- return TARGET_CPU_ZARCH;
-
default:
return true;
}
@@ -4027,8 +4004,7 @@ legitimate_reload_constant_p (rtx op)
return true;
/* Accept larl operands. */
- if (TARGET_CPU_ZARCH
- && larl_operand (op, VOIDmode))
+ if (larl_operand (op, VOIDmode))
return true;
/* Accept floating-point zero operands that fit into a single GPR. */
@@ -4127,7 +4103,7 @@ s390_preferred_reload_class (rtx op, reg_class_t rclass)
case CONST:
/* Symrefs cannot be pushed into the literal pool with -fPIC
so we *MUST NOT* return NO_REGS for these cases
- (s390_cannot_force_const_mem will return true).
+ (s390_cannot_force_const_mem will return true).
On the other hand we MUST return NO_REGS for symrefs with
invalid addend which might have been pushed to the literal
@@ -4135,8 +4111,7 @@ s390_preferred_reload_class (rtx op, reg_class_t rclass)
handled via secondary reload but this does not happen if
they are used as literal pool slot replacement in reload
inheritance (see emit_input_reload_insns). */
- if (TARGET_CPU_ZARCH
- && GET_CODE (XEXP (op, 0)) == PLUS
+ if (GET_CODE (XEXP (op, 0)) == PLUS
&& GET_CODE (XEXP (XEXP(op, 0), 0)) == SYMBOL_REF
&& GET_CODE (XEXP (XEXP(op, 0), 1)) == CONST_INT)
{
@@ -4149,7 +4124,7 @@ s390_preferred_reload_class (rtx op, reg_class_t rclass)
case LABEL_REF:
case SYMBOL_REF:
if (!legitimate_reload_constant_p (op))
- return NO_REGS;
+ return NO_REGS;
/* fallthrough */
case PLUS:
/* load address will be used. */
@@ -4190,7 +4165,7 @@ s390_check_symref_alignment (rtx addr, HOST_WIDE_INT alignment)
if (GET_CODE (symref) == SYMBOL_REF)
{
/* We have load-relative instructions for 2-byte, 4-byte, and
- 8-byte alignment so allow only these. */
+ 8-byte alignment so allow only these. */
switch (alignment)
{
case 8: return !SYMBOL_FLAG_NOTALIGN8_P (symref);
@@ -4350,10 +4325,10 @@ s390_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
case E_##M##mode: \
if (TARGET_64BIT) \
sri->icode = in_p ? CODE_FOR_reload##m##di_toreg_z10 : \
- CODE_FOR_reload##m##di_tomem_z10; \
+ CODE_FOR_reload##m##di_tomem_z10; \
else \
- sri->icode = in_p ? CODE_FOR_reload##m##si_toreg_z10 : \
- CODE_FOR_reload##m##si_tomem_z10; \
+ sri->icode = in_p ? CODE_FOR_reload##m##si_toreg_z10 : \
+ CODE_FOR_reload##m##si_tomem_z10; \
break;
switch (GET_MODE (x))
@@ -4519,7 +4494,7 @@ s390_expand_plus_operand (rtx target, rtx src,
|| (ad.indx && !REGNO_OK_FOR_INDEX_P (REGNO (ad.indx))))
{
/* Otherwise, one of the operands cannot be an address register;
- we reload its value into the scratch register. */
+ we reload its value into the scratch register. */
if (true_regnum (sum1) < 1 || true_regnum (sum1) > 15)
{
emit_move_insn (scratch, sum1);
@@ -4532,9 +4507,9 @@ s390_expand_plus_operand (rtx target, rtx src,
}
/* According to the way these invalid addresses are generated
- in reload.c, it should never happen (at least on s390) that
- *neither* of the PLUS components, after find_replacements
- was applied, is an address register. */
+ in reload.c, it should never happen (at least on s390) that
+ *neither* of the PLUS components, after find_replacements
+ was applied, is an address register. */
if (sum1 == scratch && sum2 == scratch)
{
debug_rtx (src);
@@ -4716,7 +4691,7 @@ legitimize_pic_address (rtx orig, rtx reg)
|| (SYMBOL_REF_P (addr) && s390_rel_address_ok_p (addr))
|| (GET_CODE (addr) == UNSPEC &&
(XINT (addr, 1) == UNSPEC_GOTENT
- || (TARGET_CPU_ZARCH && XINT (addr, 1) == UNSPEC_PLT))))
+ || XINT (addr, 1) == UNSPEC_PLT)))
&& GET_CODE (addend) == CONST_INT)
{
/* This can be locally addressed. */
@@ -4725,8 +4700,7 @@ legitimize_pic_address (rtx orig, rtx reg)
rtx const_addr = (GET_CODE (addr) == UNSPEC ?
gen_rtx_CONST (Pmode, addr) : addr);
- if (TARGET_CPU_ZARCH
- && larl_operand (const_addr, VOIDmode)
+ if (larl_operand (const_addr, VOIDmode)
&& INTVAL (addend) < HOST_WIDE_INT_1 << 31
&& INTVAL (addend) >= -(HOST_WIDE_INT_1 << 31))
{
@@ -4798,7 +4772,7 @@ legitimize_pic_address (rtx orig, rtx reg)
that case. So no need to do it here. */
if (reg == 0)
- reg = gen_reg_rtx (Pmode);
+ reg = gen_reg_rtx (Pmode);
if (TARGET_Z10)
{
@@ -4812,70 +4786,42 @@ legitimize_pic_address (rtx orig, rtx reg)
new_rtx = reg;
}
else if (flag_pic == 1)
- {
- /* Assume GOT offset is a valid displacement operand (< 4k
- or < 512k with z990). This is handled the same way in
- both 31- and 64-bit code (@GOT).
- lg <target>, sym@GOT(r12) */
+ {
+ /* Assume GOT offset is a valid displacement operand (< 4k
+ or < 512k with z990). This is handled the same way in
+ both 31- and 64-bit code (@GOT).
+ lg <target>, sym@GOT(r12) */
if (reload_in_progress || reload_completed)
df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT);
- new_rtx = gen_rtx_CONST (Pmode, new_rtx);
- new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new_rtx);
- new_rtx = gen_const_mem (Pmode, new_rtx);
- emit_move_insn (reg, new_rtx);
- new_rtx = reg;
- }
- else if (TARGET_CPU_ZARCH)
- {
- /* If the GOT offset might be >= 4k, we determine the position
- of the GOT entry via a PC-relative LARL (@GOTENT).
+ new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT);
+ new_rtx = gen_rtx_CONST (Pmode, new_rtx);
+ new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new_rtx);
+ new_rtx = gen_const_mem (Pmode, new_rtx);
+ emit_move_insn (reg, new_rtx);
+ new_rtx = reg;
+ }
+ else
+ {
+ /* If the GOT offset might be >= 4k, we determine the position
+ of the GOT entry via a PC-relative LARL (@GOTENT).
larl temp, sym@GOTENT
- lg <target>, 0(temp) */
+ lg <target>, 0(temp) */
- rtx temp = reg ? reg : gen_reg_rtx (Pmode);
+ rtx temp = reg ? reg : gen_reg_rtx (Pmode);
gcc_assert (REGNO (temp) >= FIRST_PSEUDO_REGISTER
|| REGNO_REG_CLASS (REGNO (temp)) == ADDR_REGS);
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTENT);
- new_rtx = gen_rtx_CONST (Pmode, new_rtx);
+ new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTENT);
+ new_rtx = gen_rtx_CONST (Pmode, new_rtx);
emit_move_insn (temp, new_rtx);
-
new_rtx = gen_const_mem (Pmode, temp);
- emit_move_insn (reg, new_rtx);
-
- new_rtx = reg;
- }
- else
- {
- /* If the GOT offset might be >= 4k, we have to load it
- from the literal pool (@GOT).
-
- lg temp, lit-litbase(r13)
- lg <target>, 0(temp)
- lit: .long sym@GOT */
-
- rtx temp = reg ? reg : gen_reg_rtx (Pmode);
-
- gcc_assert (REGNO (temp) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS (REGNO (temp)) == ADDR_REGS);
-
- if (reload_in_progress || reload_completed)
- df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-
- addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT);
- addr = gen_rtx_CONST (Pmode, addr);
- addr = force_const_mem (Pmode, addr);
- emit_move_insn (temp, addr);
+ emit_move_insn (reg, new_rtx);
- new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
- new_rtx = gen_const_mem (Pmode, new_rtx);
- emit_move_insn (reg, new_rtx);
- new_rtx = reg;
- }
+ new_rtx = reg;
+ }
}
else if (GET_CODE (addr) == UNSPEC && GET_CODE (addend) == CONST_INT)
{
@@ -4904,36 +4850,10 @@ legitimize_pic_address (rtx orig, rtx reg)
gcc_unreachable ();
break;
- /* @PLT is OK as is on 64-bit, must be converted to
- GOT-relative @PLTOFF on 31-bit. */
+ /* For @PLT larl is used. This is handled like local
+ symbol refs. */
case UNSPEC_PLT:
- if (!TARGET_CPU_ZARCH)
- {
- rtx temp = reg? reg : gen_reg_rtx (Pmode);
-
- if (reload_in_progress || reload_completed)
- df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-
- addr = XVECEXP (addr, 0, 0);
- addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
- UNSPEC_PLTOFF);
- if (addend != const0_rtx)
- addr = gen_rtx_PLUS (Pmode, addr, addend);
- addr = gen_rtx_CONST (Pmode, addr);
- addr = force_const_mem (Pmode, addr);
- emit_move_insn (temp, addr);
-
- new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
- if (reg != 0)
- {
- s390_load_address (reg, new_rtx);
- new_rtx = reg;
- }
- }
- else
- /* On 64 bit larl can be used. This case is handled like
- local symbol refs. */
- gcc_unreachable ();
+ gcc_unreachable ();
break;
/* Everything else cannot happen. */
@@ -5090,7 +5010,7 @@ legitimize_tls_address (rtx addr, rtx reg)
temp = gen_reg_rtx (Pmode);
emit_move_insn (temp, new_rtx);
}
- else if (TARGET_CPU_ZARCH)
+ else
{
/* If the GOT offset might be >= 4k, we determine the position
of the GOT entry via a PC-relative LARL. */
@@ -5104,44 +5024,6 @@ legitimize_tls_address (rtx addr, rtx reg)
temp = gen_reg_rtx (Pmode);
emit_move_insn (temp, new_rtx);
}
- else if (flag_pic)
- {
- /* If the GOT offset might be >= 4k, we have to load it
- from the literal pool. */
-
- if (reload_in_progress || reload_completed)
- df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTNTPOFF);
- new_rtx = gen_rtx_CONST (Pmode, new_rtx);
- new_rtx = force_const_mem (Pmode, new_rtx);
- temp = gen_reg_rtx (Pmode);
- emit_move_insn (temp, new_rtx);
-
- new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
- new_rtx = gen_const_mem (Pmode, new_rtx);
-
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, new_rtx, addr), UNSPEC_TLS_LOAD);
- temp = gen_reg_rtx (Pmode);
- emit_insn (gen_rtx_SET (temp, new_rtx));
- }
- else
- {
- /* In position-dependent code, load the absolute address of
- the GOT entry from the literal pool. */
-
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_INDNTPOFF);
- new_rtx = gen_rtx_CONST (Pmode, new_rtx);
- new_rtx = force_const_mem (Pmode, new_rtx);
- temp = gen_reg_rtx (Pmode);
- emit_move_insn (temp, new_rtx);
-
- new_rtx = temp;
- new_rtx = gen_const_mem (Pmode, new_rtx);
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, new_rtx, addr), UNSPEC_TLS_LOAD);
- temp = gen_reg_rtx (Pmode);
- emit_insn (gen_rtx_SET (temp, new_rtx));
- }
new_rtx = gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), temp);
if (reg != 0)
@@ -5155,7 +5037,7 @@ legitimize_tls_address (rtx addr, rtx reg)
new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_NTPOFF);
new_rtx = gen_rtx_CONST (Pmode, new_rtx);
new_rtx = force_const_mem (Pmode, new_rtx);
- temp = gen_reg_rtx (Pmode);
+ temp = gen_reg_rtx (Pmode);
emit_move_insn (temp, new_rtx);
new_rtx = gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), temp);
@@ -5175,7 +5057,6 @@ legitimize_tls_address (rtx addr, rtx reg)
switch (XINT (XEXP (addr, 0), 1))
{
case UNSPEC_INDNTPOFF:
- gcc_assert (TARGET_CPU_ZARCH);
new_rtx = addr;
break;
@@ -5254,9 +5135,9 @@ s390_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
else if (flag_pic)
{
if (SYMBOLIC_CONST (x)
- || (GET_CODE (x) == PLUS
- && (SYMBOLIC_CONST (XEXP (x, 0))
- || SYMBOLIC_CONST (XEXP (x, 1)))))
+ || (GET_CODE (x) == PLUS
+ && (SYMBOLIC_CONST (XEXP (x, 0))
+ || SYMBOLIC_CONST (XEXP (x, 1)))))
x = legitimize_pic_address (x, 0);
if (s390_legitimate_address_p (mode, x, FALSE))
@@ -5413,7 +5294,7 @@ s390_expand_movmem (rtx dst, rtx src, rtx len)
mode = GET_MODE (len);
if (mode == VOIDmode)
- mode = Pmode;
+ mode = Pmode;
dst_addr = gen_reg_rtx (Pmode);
src_addr = gen_reg_rtx (Pmode);
@@ -5432,12 +5313,12 @@ s390_expand_movmem (rtx dst, rtx src, rtx len)
temp = expand_binop (mode, add_optab, count, constm1_rtx, count, 1,
OPTAB_DIRECT);
if (temp != count)
- emit_move_insn (count, temp);
+ emit_move_insn (count, temp);
temp = expand_binop (mode, lshr_optab, count, GEN_INT (8), blocks, 1,
OPTAB_DIRECT);
if (temp != blocks)
- emit_move_insn (blocks, temp);
+ emit_move_insn (blocks, temp);
emit_cmp_and_jump_insns (blocks, const0_rtx,
EQ, NULL_RTX, mode, 1, loop_end_label);
@@ -5471,7 +5352,7 @@ s390_expand_movmem (rtx dst, rtx src, rtx len)
temp = expand_binop (mode, add_optab, blocks, constm1_rtx, blocks, 1,
OPTAB_DIRECT);
if (temp != blocks)
- emit_move_insn (blocks, temp);
+ emit_move_insn (blocks, temp);
emit_cmp_and_jump_insns (blocks, const0_rtx,
EQ, NULL_RTX, mode, 1, loop_end_label);
@@ -5499,12 +5380,15 @@ s390_expand_setmem (rtx dst, rtx len, rtx val)
/* Expand setmem/clrmem for a constant length operand without a
loop if it will be shorter that way.
- With a constant length and without pfd argument a
- clrmem loop is 32 bytes -> 5.3 * xc
- setmem loop is 36 bytes -> 3.6 * (mvi/stc + mvc) */
+ clrmem loop (with PFD) is 30 bytes -> 5 * xc
+ clrmem loop (without PFD) is 24 bytes -> 4 * xc
+ setmem loop (with PFD) is 38 bytes -> ~4 * (mvi/stc + mvc)
+ setmem loop (without PFD) is 32 bytes -> ~4 * (mvi/stc + mvc) */
if (GET_CODE (len) == CONST_INT
- && ((INTVAL (len) <= 256 * 5 && val == const0_rtx)
- || INTVAL (len) <= 257 * 3)
+ && ((val == const0_rtx
+ && (INTVAL (len) <= 256 * 4
+ || (INTVAL (len) <= 256 * 5 && TARGET_SETMEM_PFD(val,len))))
+ || (val != const0_rtx && INTVAL (len) <= 257 * 4))
&& (!TARGET_MVCLE || INTVAL (len) <= 256))
{
HOST_WIDE_INT o, l;
@@ -5618,12 +5502,11 @@ s390_expand_setmem (rtx dst, rtx len, rtx val)
emit_label (loop_start_label);
- if (TARGET_Z10
- && (GET_CODE (len) != CONST_INT || INTVAL (len) > 1024))
+ if (TARGET_SETMEM_PFD (val, len))
{
- /* Issue a write prefetch for the +4 cache line. */
- rtx prefetch = gen_prefetch (gen_rtx_PLUS (Pmode, dst_addr,
- GEN_INT (1024)),
+ /* Issue a write prefetch. */
+ rtx distance = GEN_INT (TARGET_SETMEM_PREFETCH_DISTANCE);
+ rtx prefetch = gen_prefetch (gen_rtx_PLUS (Pmode, dst_addr, distance),
const1_rtx, const0_rtx);
emit_insn (prefetch);
PREFETCH_SCHEDULE_BARRIER_P (prefetch) = true;
@@ -5691,12 +5574,12 @@ s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len)
if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256)
{
if (INTVAL (len) > 0)
- {
- emit_insn (gen_cmpmem_short (op0, op1, GEN_INT (INTVAL (len) - 1)));
- emit_insn (gen_cmpint (target, ccreg));
- }
+ {
+ emit_insn (gen_cmpmem_short (op0, op1, GEN_INT (INTVAL (len) - 1)));
+ emit_insn (gen_cmpint (target, ccreg));
+ }
else
- emit_move_insn (target, const0_rtx);
+ emit_move_insn (target, const0_rtx);
}
else if (TARGET_MVCLE)
{
@@ -5713,7 +5596,7 @@ s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len)
mode = GET_MODE (len);
if (mode == VOIDmode)
- mode = Pmode;
+ mode = Pmode;
addr0 = gen_reg_rtx (Pmode);
addr1 = gen_reg_rtx (Pmode);
@@ -5732,12 +5615,12 @@ s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len)
temp = expand_binop (mode, add_optab, count, constm1_rtx, count, 1,
OPTAB_DIRECT);
if (temp != count)
- emit_move_insn (count, temp);
+ emit_move_insn (count, temp);
temp = expand_binop (mode, lshr_optab, count, GEN_INT (8), blocks, 1,
OPTAB_DIRECT);
if (temp != blocks)
- emit_move_insn (blocks, temp);
+ emit_move_insn (blocks, temp);
emit_cmp_and_jump_insns (blocks, const0_rtx,
EQ, NULL_RTX, mode, 1, loop_end_label);
@@ -5777,7 +5660,7 @@ s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len)
temp = expand_binop (mode, add_optab, blocks, constm1_rtx, blocks, 1,
OPTAB_DIRECT);
if (temp != blocks)
- emit_move_insn (blocks, temp);
+ emit_move_insn (blocks, temp);
emit_cmp_and_jump_insns (blocks, const0_rtx,
EQ, NULL_RTX, mode, 1, loop_end_label);
@@ -5913,7 +5796,7 @@ s390_expand_vec_strlen (rtx target, rtx string, rtx alignment)
highest_index_to_load_reg, str_idx_reg));
add_reg_br_prob_note (s390_emit_jump (is_aligned_label, cond),
- profile_probability::very_unlikely ());
+ profile_probability::very_unlikely ());
expand_binop (Pmode, add_optab, str_idx_reg,
GEN_INT (-16), str_idx_reg, 1, OPTAB_DIRECT);
@@ -6147,7 +6030,7 @@ s390_expand_addcc (enum rtx_code cmp_code, rtx cmp_op0, rtx cmp_op1,
p = rtvec_alloc (2);
RTVEC_ELT (p, 0) =
- gen_rtx_SET (dst, op_res);
+ gen_rtx_SET (dst, op_res);
RTVEC_ELT (p, 1) =
gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
@@ -6214,7 +6097,7 @@ s390_expand_addcc (enum rtx_code cmp_code, rtx cmp_op0, rtx cmp_op1,
const0_rtx));
p = rtvec_alloc (2);
RTVEC_ELT (p, 0) =
- gen_rtx_SET (dst, op_res);
+ gen_rtx_SET (dst, op_res);
RTVEC_ELT (p, 1) =
gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
@@ -7045,8 +6928,8 @@ s390_expand_cs_tdsi (machine_mode mode, rtx btarget, rtx vtarget, rtx mem,
emit_insn (gen_rtx_SET (cc, gen_rtx_COMPARE (CCZmode, output, cmp)));
}
s390_emit_jump (skip_cs_label, gen_rtx_NE (VOIDmode, cc, const0_rtx));
- add_reg_br_prob_note (get_last_insn (),
- profile_probability::very_unlikely ());
+ add_reg_br_prob_note (get_last_insn (),
+ profile_probability::very_unlikely ());
/* If the jump is not taken, OUTPUT is the expected value. */
cmp = output;
/* Reload newval to a register manually, *after* the compare and jump
@@ -7313,12 +7196,12 @@ s390_delegitimize_address (rtx orig_x)
/* Extract the symbol ref from:
(plus:SI (reg:SI 12 %r12)
- (const:SI (unspec:SI [(symbol_ref/f:SI ("*.LC0"))]
- UNSPEC_GOTOFF/PLTOFF)))
+ (const:SI (unspec:SI [(symbol_ref/f:SI ("*.LC0"))]
+ UNSPEC_GOTOFF/PLTOFF)))
and
(plus:SI (reg:SI 12 %r12)
- (const:SI (plus:SI (unspec:SI [(symbol_ref:SI ("L"))]
- UNSPEC_GOTOFF/PLTOFF)
+ (const:SI (plus:SI (unspec:SI [(symbol_ref:SI ("L"))]
+ UNSPEC_GOTOFF/PLTOFF)
(const_int 4 [0x4])))) */
if (GET_CODE (x) == PLUS
&& REG_P (XEXP (x, 0))
@@ -7363,7 +7246,7 @@ s390_delegitimize_address (rtx orig_x)
{
/* Extract the symbol ref from:
(mem:QI (const:DI (unspec:DI [(symbol_ref:DI ("foo"))]
- UNSPEC_PLT/GOTENT))) */
+ UNSPEC_PLT/GOTENT))) */
y = XEXP (x, 0);
if (GET_CODE (y) == UNSPEC
@@ -7678,7 +7561,7 @@ print_operand_address (FILE *file, rtx addr)
if (ad.base && ad.indx)
fprintf (file, "(%s,%s)", reg_names[REGNO (ad.indx)],
- reg_names[REGNO (ad.base)]);
+ reg_names[REGNO (ad.base)]);
else if (ad.base)
fprintf (file, "(%s)", reg_names[REGNO (ad.base)]);
}
@@ -7712,7 +7595,7 @@ print_operand_address (FILE *file, rtx addr)
'o': print integer X as if it's an unsigned 32bit word.
's': "start" of contiguous bitmask X in either DImode or vector inner mode.
't': CONST_INT: "start" of contiguous bitmask X in SImode.
- CONST_VECTOR: Generate a bitmask for vgbm instruction.
+ CONST_VECTOR: Generate a bitmask for vgbm instruction.
'x': print integer X as if it's an unsigned halfword.
'v': print register number as vector register (v1 instead of f1).
*/
@@ -7770,7 +7653,7 @@ print_operand (FILE *file, rtx x, int code)
case 'O':
{
- struct s390_address ad;
+ struct s390_address ad;
int ret;
ret = s390_decompose_address (MEM_P (x) ? XEXP (x, 0) : x, &ad);
@@ -7783,16 +7666,16 @@ print_operand (FILE *file, rtx x, int code)
return;
}
- if (ad.disp)
- output_addr_const (file, ad.disp);
- else
- fprintf (file, "0");
+ if (ad.disp)
+ output_addr_const (file, ad.disp);
+ else
+ fprintf (file, "0");
}
return;
case 'R':
{
- struct s390_address ad;
+ struct s390_address ad;
int ret;
ret = s390_decompose_address (MEM_P (x) ? XEXP (x, 0) : x, &ad);
@@ -7805,10 +7688,10 @@ print_operand (FILE *file, rtx x, int code)
return;
}
- if (ad.base)
- fprintf (file, "%s", reg_names[REGNO (ad.base)]);
- else
- fprintf (file, "0");
+ if (ad.base)
+ fprintf (file, "%s", reg_names[REGNO (ad.base)]);
+ else
+ fprintf (file, "0");
}
return;
@@ -7954,13 +7837,13 @@ print_operand (FILE *file, rtx x, int code)
case CONST_WIDE_INT:
if (code == 'b')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC,
CONST_WIDE_INT_ELT (x, 0) & 0xff);
else if (code == 'x')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC,
CONST_WIDE_INT_ELT (x, 0) & 0xffff);
else if (code == 'h')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC,
((CONST_WIDE_INT_ELT (x, 0) & 0xffff) ^ 0x8000) - 0x8000);
else
{
@@ -8163,7 +8046,7 @@ s390_adjust_priority (rtx_insn *insn, int priority)
priority = priority << 1;
break;
default:
- break;
+ break;
}
return priority;
}
@@ -8183,8 +8066,6 @@ s390_issue_rate (void)
return 3;
case PROCESSOR_2097_Z10:
return 2;
- case PROCESSOR_9672_G5:
- case PROCESSOR_9672_G6:
case PROCESSOR_2064_Z900:
/* Starting with EC12 we use the sched_reorder hook to take care
of instruction dispatch constraints. The algorithm only
@@ -8282,120 +8163,21 @@ annotate_constant_pool_refs (rtx *x)
}
}
- /* Annotate LTREL_BASE as well. */
- if (GET_CODE (*x) == UNSPEC
- && XINT (*x, 1) == UNSPEC_LTREL_BASE)
- {
- rtx base = cfun->machine->base_reg;
- *x = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, XVECEXP (*x, 0, 0), base),
- UNSPEC_LTREL_BASE);
- return;
- }
-
fmt = GET_RTX_FORMAT (GET_CODE (*x));
for (i = GET_RTX_LENGTH (GET_CODE (*x)) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
- {
- annotate_constant_pool_refs (&XEXP (*x, i));
- }
- else if (fmt[i] == 'E')
- {
- for (j = 0; j < XVECLEN (*x, i); j++)
- annotate_constant_pool_refs (&XVECEXP (*x, i, j));
- }
- }
-}
-
-/* Split all branches that exceed the maximum distance.
- Returns true if this created a new literal pool entry. */
-
-static int
-s390_split_branches (void)
-{
- rtx temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
- int new_literal = 0, ret;
- rtx_insn *insn;
- rtx pat, target;
- rtx *label;
-
- /* We need correct insn addresses. */
-
- shorten_branches (get_insns ());
-
- /* Find all branches that exceed 64KB, and split them. */
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- if (! JUMP_P (insn) || tablejump_p (insn, NULL, NULL))
- continue;
-
- pat = PATTERN (insn);
- if (GET_CODE (pat) == PARALLEL)
- pat = XVECEXP (pat, 0, 0);
- if (GET_CODE (pat) != SET || SET_DEST (pat) != pc_rtx)
- continue;
-
- if (GET_CODE (SET_SRC (pat)) == LABEL_REF)
- {
- label = &SET_SRC (pat);
- }
- else if (GET_CODE (SET_SRC (pat)) == IF_THEN_ELSE)
- {
- if (GET_CODE (XEXP (SET_SRC (pat), 1)) == LABEL_REF)
- label = &XEXP (SET_SRC (pat), 1);
- else if (GET_CODE (XEXP (SET_SRC (pat), 2)) == LABEL_REF)
- label = &XEXP (SET_SRC (pat), 2);
- else
- continue;
- }
- else
- continue;
-
- if (get_attr_length (insn) <= 4)
- continue;
-
- /* We are going to use the return register as scratch register,
- make sure it will be saved/restored by the prologue/epilogue. */
- cfun_frame_layout.save_return_addr_p = 1;
-
- if (!flag_pic)
{
- new_literal = 1;
- rtx mem = force_const_mem (Pmode, *label);
- rtx_insn *set_insn = emit_insn_before (gen_rtx_SET (temp_reg, mem),
- insn);
- INSN_ADDRESSES_NEW (set_insn, -1);
- annotate_constant_pool_refs (&PATTERN (set_insn));
-
- target = temp_reg;
+ annotate_constant_pool_refs (&XEXP (*x, i));
}
- else
+ else if (fmt[i] == 'E')
{
- new_literal = 1;
- target = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, *label),
- UNSPEC_LTREL_OFFSET);
- target = gen_rtx_CONST (Pmode, target);
- target = force_const_mem (Pmode, target);
- rtx_insn *set_insn = emit_insn_before (gen_rtx_SET (temp_reg, target),
- insn);
- INSN_ADDRESSES_NEW (set_insn, -1);
- annotate_constant_pool_refs (&PATTERN (set_insn));
-
- target = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, XEXP (target, 0),
- cfun->machine->base_reg),
- UNSPEC_LTREL_BASE);
- target = gen_rtx_PLUS (Pmode, temp_reg, target);
+ for (j = 0; j < XVECLEN (*x, i); j++)
+ annotate_constant_pool_refs (&XVECEXP (*x, i, j));
}
-
- ret = validate_change (insn, label, target, 0);
- gcc_assert (ret);
}
-
- return new_literal;
}
-
/* Find an annotated literal pool symbol referenced in RTX X,
and store it at REF. Will abort if X contains references to
more than one such pool symbol; multiple references to the same
@@ -8410,23 +8192,19 @@ find_constant_pool_ref (rtx x, rtx *ref)
int i, j;
const char *fmt;
- /* Ignore LTREL_BASE references. */
- if (GET_CODE (x) == UNSPEC
- && XINT (x, 1) == UNSPEC_LTREL_BASE)
- return;
/* Likewise POOL_ENTRY insns. */
if (GET_CODE (x) == UNSPEC_VOLATILE
&& XINT (x, 1) == UNSPECV_POOL_ENTRY)
return;
gcc_assert (GET_CODE (x) != SYMBOL_REF
- || !CONSTANT_POOL_ADDRESS_P (x));
+ || !CONSTANT_POOL_ADDRESS_P (x));
if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_LTREF)
{
rtx sym = XVECEXP (x, 0, 0);
gcc_assert (GET_CODE (sym) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (sym));
+ && CONSTANT_POOL_ADDRESS_P (sym));
if (*ref == NULL_RTX)
*ref = sym;
@@ -8440,14 +8218,14 @@ find_constant_pool_ref (rtx x, rtx *ref)
for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
- {
- find_constant_pool_ref (XEXP (x, i), ref);
- }
+ {
+ find_constant_pool_ref (XEXP (x, i), ref);
+ }
else if (fmt[i] == 'E')
- {
- for (j = 0; j < XVECLEN (x, i); j++)
- find_constant_pool_ref (XVECEXP (x, i, j), ref);
- }
+ {
+ for (j = 0; j < XVECLEN (x, i); j++)
+ find_constant_pool_ref (XVECEXP (x, i, j), ref);
+ }
}
}
@@ -8485,84 +8263,17 @@ replace_constant_pool_ref (rtx *x, rtx ref, rtx offset)
for (i = GET_RTX_LENGTH (GET_CODE (*x)) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
- {
- replace_constant_pool_ref (&XEXP (*x, i), ref, offset);
- }
- else if (fmt[i] == 'E')
- {
- for (j = 0; j < XVECLEN (*x, i); j++)
- replace_constant_pool_ref (&XVECEXP (*x, i, j), ref, offset);
- }
- }
-}
-
-/* Check whether X contains an UNSPEC_LTREL_BASE.
- Return its constant pool symbol if found, NULL_RTX otherwise. */
-
-static rtx
-find_ltrel_base (rtx x)
-{
- int i, j;
- const char *fmt;
-
- if (GET_CODE (x) == UNSPEC
- && XINT (x, 1) == UNSPEC_LTREL_BASE)
- return XVECEXP (x, 0, 0);
-
- fmt = GET_RTX_FORMAT (GET_CODE (x));
- for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- {
- rtx fnd = find_ltrel_base (XEXP (x, i));
- if (fnd)
- return fnd;
- }
- else if (fmt[i] == 'E')
- {
- for (j = 0; j < XVECLEN (x, i); j++)
- {
- rtx fnd = find_ltrel_base (XVECEXP (x, i, j));
- if (fnd)
- return fnd;
- }
- }
- }
-
- return NULL_RTX;
-}
-
-/* Replace any occurrence of UNSPEC_LTREL_BASE in X with its base. */
-
-static void
-replace_ltrel_base (rtx *x)
-{
- int i, j;
- const char *fmt;
-
- if (GET_CODE (*x) == UNSPEC
- && XINT (*x, 1) == UNSPEC_LTREL_BASE)
- {
- *x = XVECEXP (*x, 0, 1);
- return;
- }
-
- fmt = GET_RTX_FORMAT (GET_CODE (*x));
- for (i = GET_RTX_LENGTH (GET_CODE (*x)) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- {
- replace_ltrel_base (&XEXP (*x, i));
- }
+ {
+ replace_constant_pool_ref (&XEXP (*x, i), ref, offset);
+ }
else if (fmt[i] == 'E')
- {
- for (j = 0; j < XVECLEN (*x, i); j++)
- replace_ltrel_base (&XVECEXP (*x, i, j));
- }
+ {
+ for (j = 0; j < XVECLEN (*x, i); j++)
+ replace_constant_pool_ref (&XVECEXP (*x, i, j), ref, offset);
+ }
}
}
-
/* We keep a list of constants which we have to add to internal
constant tables in the middle of large functions. */
@@ -8778,28 +8489,6 @@ s390_execute_label (rtx insn)
return NULL_RTX;
}
-/* Add execute target for INSN to the constant pool POOL. */
-
-static void
-s390_add_execute (struct constant_pool *pool, rtx insn)
-{
- struct constant *c;
-
- for (c = pool->execute; c != NULL; c = c->next)
- if (INSN_UID (insn) == INSN_UID (c->value))
- break;
-
- if (c == NULL)
- {
- c = (struct constant *) xmalloc (sizeof *c);
- c->value = insn;
- c->label = gen_label_rtx ();
- c->next = pool->execute;
- pool->execute = c;
- pool->size += 6;
- }
-}
-
/* Find execute target for INSN in the constant pool POOL.
Return an RTX describing the distance from the start of
the pool to the location of the execute target. */
@@ -8865,17 +8554,11 @@ s390_dump_pool (struct constant_pool *pool, bool remote_label)
int i;
/* Switch to rodata section. */
- if (TARGET_CPU_ZARCH)
- {
- insn = emit_insn_after (gen_pool_section_start (), insn);
- INSN_ADDRESSES_NEW (insn, -1);
- }
+ insn = emit_insn_after (gen_pool_section_start (), insn);
+ INSN_ADDRESSES_NEW (insn, -1);
/* Ensure minimum pool alignment. */
- if (TARGET_CPU_ZARCH)
- insn = emit_insn_after (gen_pool_align (GEN_INT (8)), insn);
- else
- insn = emit_insn_after (gen_pool_align (GEN_INT (4)), insn);
+ insn = emit_insn_after (gen_pool_align (GEN_INT (8)), insn);
INSN_ADDRESSES_NEW (insn, -1);
/* Emit pool base label. */
@@ -8923,11 +8606,8 @@ s390_dump_pool (struct constant_pool *pool, bool remote_label)
}
/* Switch back to previous section. */
- if (TARGET_CPU_ZARCH)
- {
- insn = emit_insn_after (gen_pool_section_end (), insn);
- INSN_ADDRESSES_NEW (insn, -1);
- }
+ insn = emit_insn_after (gen_pool_section_end (), insn);
+ INSN_ADDRESSES_NEW (insn, -1);
insn = emit_barrier_after (insn);
INSN_ADDRESSES_NEW (insn, -1);
@@ -8991,11 +8671,7 @@ s390_mainpool_start (void)
pool->pool_insn = insn;
}
- if (!TARGET_CPU_ZARCH && s390_execute_label (insn))
- {
- s390_add_execute (pool, insn);
- }
- else if (NONJUMP_INSN_P (insn) || CALL_P (insn))
+ if (NONJUMP_INSN_P (insn) || CALL_P (insn))
{
rtx pool_ref = NULL_RTX;
find_constant_pool_ref (PATTERN (insn), &pool_ref);
@@ -9047,6 +8723,8 @@ static void
s390_mainpool_finish (struct constant_pool *pool)
{
rtx base_reg = cfun->machine->base_reg;
+ rtx set;
+ rtx_insn *insn;
/* If the pool is empty, we're done. */
if (pool->size == 0)
@@ -9063,95 +8741,39 @@ s390_mainpool_finish (struct constant_pool *pool)
/* We need correct insn addresses. */
shorten_branches (get_insns ());
- /* On zSeries, we use a LARL to load the pool register. The pool is
+ /* Use a LARL to load the pool register. The pool is
located in the .rodata section, so we emit it after the function. */
- if (TARGET_CPU_ZARCH)
- {
- rtx set = gen_main_base_64 (base_reg, pool->label);
- rtx_insn *insn = emit_insn_after (set, pool->pool_insn);
- INSN_ADDRESSES_NEW (insn, -1);
- remove_insn (pool->pool_insn);
-
- insn = get_last_insn ();
- pool->pool_insn = emit_insn_after (gen_pool (const0_rtx), insn);
- INSN_ADDRESSES_NEW (pool->pool_insn, -1);
-
- s390_dump_pool (pool, 0);
- }
-
- /* On S/390, if the total size of the function's code plus literal pool
- does not exceed 4096 bytes, we use BASR to set up a function base
- pointer, and emit the literal pool at the end of the function. */
- else if (INSN_ADDRESSES (INSN_UID (pool->emit_pool_after))
- + pool->size + 8 /* alignment slop */ < 4096)
- {
- rtx set = gen_main_base_31_small (base_reg, pool->label);
- rtx_insn *insn = emit_insn_after (set, pool->pool_insn);
- INSN_ADDRESSES_NEW (insn, -1);
- remove_insn (pool->pool_insn);
-
- insn = emit_label_after (pool->label, insn);
- INSN_ADDRESSES_NEW (insn, -1);
-
- /* emit_pool_after will be set by s390_mainpool_start to the
- last insn of the section where the literal pool should be
- emitted. */
- insn = pool->emit_pool_after;
-
- pool->pool_insn = emit_insn_after (gen_pool (const0_rtx), insn);
- INSN_ADDRESSES_NEW (pool->pool_insn, -1);
-
- s390_dump_pool (pool, 1);
- }
-
- /* Otherwise, we emit an inline literal pool and use BASR to branch
- over it, setting up the pool register at the same time. */
- else
- {
- rtx_code_label *pool_end = gen_label_rtx ();
-
- rtx pat = gen_main_base_31_large (base_reg, pool->label, pool_end);
- rtx_insn *insn = emit_jump_insn_after (pat, pool->pool_insn);
- JUMP_LABEL (insn) = pool_end;
- INSN_ADDRESSES_NEW (insn, -1);
- remove_insn (pool->pool_insn);
-
- insn = emit_label_after (pool->label, insn);
- INSN_ADDRESSES_NEW (insn, -1);
-
- pool->pool_insn = emit_insn_after (gen_pool (const0_rtx), insn);
- INSN_ADDRESSES_NEW (pool->pool_insn, -1);
-
- insn = emit_label_after (pool_end, pool->pool_insn);
- INSN_ADDRESSES_NEW (insn, -1);
+ set = gen_main_base_64 (base_reg, pool->label);
+ insn = emit_insn_after (set, pool->pool_insn);
+ INSN_ADDRESSES_NEW (insn, -1);
+ remove_insn (pool->pool_insn);
- s390_dump_pool (pool, 1);
- }
+ insn = get_last_insn ();
+ pool->pool_insn = emit_insn_after (gen_pool (const0_rtx), insn);
+ INSN_ADDRESSES_NEW (pool->pool_insn, -1);
+ s390_dump_pool (pool, 0);
/* Replace all literal pool references. */
for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
- if (INSN_P (insn))
- replace_ltrel_base (&PATTERN (insn));
-
if (NONJUMP_INSN_P (insn) || CALL_P (insn))
- {
- rtx addr, pool_ref = NULL_RTX;
- find_constant_pool_ref (PATTERN (insn), &pool_ref);
- if (pool_ref)
- {
+ {
+ rtx addr, pool_ref = NULL_RTX;
+ find_constant_pool_ref (PATTERN (insn), &pool_ref);
+ if (pool_ref)
+ {
if (s390_execute_label (insn))
addr = s390_find_execute (pool, insn);
else
addr = s390_find_constant (pool, get_pool_constant (pool_ref),
get_pool_mode (pool_ref));
- replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
- INSN_CODE (insn) = -1;
- }
- }
+ replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
+ INSN_CODE (insn) = -1;
+ }
+ }
}
@@ -9159,18 +8781,6 @@ s390_mainpool_finish (struct constant_pool *pool)
s390_free_pool (pool);
}
-/* POOL holds the main literal pool as collected by s390_mainpool_start.
- We have decided we cannot use this pool, so revert all changes
- to the current function that were done by s390_mainpool_start. */
-static void
-s390_mainpool_cancel (struct constant_pool *pool)
-{
- /* We didn't actually change the instruction stream, so simply
- free the pool memory. */
- s390_free_pool (pool);
-}
-
-
/* Chunkify the literal pool. */
#define S390_POOL_CHUNK_MIN 0xc00
@@ -9180,15 +8790,9 @@ static struct constant_pool *
s390_chunkify_start (void)
{
struct constant_pool *curr_pool = NULL, *pool_list = NULL;
- int extra_size = 0;
bitmap far_labels;
- rtx pending_ltrel = NULL_RTX;
rtx_insn *insn;
- rtx (*gen_reload_base) (rtx, rtx) =
- TARGET_CPU_ZARCH? gen_reload_base_64 : gen_reload_base_31;
-
-
/* We need correct insn addresses. */
shorten_branches (get_insns ());
@@ -9197,28 +8801,7 @@ s390_chunkify_start (void)
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
- bool section_switch_p = false;
-
- /* Check for pending LTREL_BASE. */
- if (INSN_P (insn))
- {
- rtx ltrel_base = find_ltrel_base (PATTERN (insn));
- if (ltrel_base)
- {
- gcc_assert (ltrel_base == pending_ltrel);
- pending_ltrel = NULL_RTX;
- }
- }
-
- if (!TARGET_CPU_ZARCH && s390_execute_label (insn))
- {
- if (!curr_pool)
- curr_pool = s390_start_pool (&pool_list, insn);
-
- s390_add_execute (curr_pool, insn);
- s390_add_pool_insn (curr_pool, insn);
- }
- else if (NONJUMP_INSN_P (insn) || CALL_P (insn))
+ if (NONJUMP_INSN_P (insn) || CALL_P (insn))
{
rtx pool_ref = NULL_RTX;
find_constant_pool_ref (PATTERN (insn), &pool_ref);
@@ -9232,16 +8815,6 @@ s390_chunkify_start (void)
s390_add_constant (curr_pool, constant, mode);
s390_add_pool_insn (curr_pool, insn);
-
- /* Don't split the pool chunk between a LTREL_OFFSET load
- and the corresponding LTREL_BASE. */
- if (GET_CODE (constant) == CONST
- && GET_CODE (XEXP (constant, 0)) == UNSPEC
- && XINT (XEXP (constant, 0), 1) == UNSPEC_LTREL_OFFSET)
- {
- gcc_assert (!pending_ltrel);
- pending_ltrel = pool_ref;
- }
}
}
@@ -9249,127 +8822,25 @@ s390_chunkify_start (void)
{
if (curr_pool)
s390_add_pool_insn (curr_pool, insn);
- /* An LTREL_BASE must follow within the same basic block. */
- gcc_assert (!pending_ltrel);
}
- if (NOTE_P (insn))
- switch (NOTE_KIND (insn))
- {
- case NOTE_INSN_SWITCH_TEXT_SECTIONS:
- section_switch_p = true;
- break;
- case NOTE_INSN_VAR_LOCATION:
- continue;
- default:
- break;
- }
+ if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
+ continue;
if (!curr_pool
|| INSN_ADDRESSES_SIZE () <= (size_t) INSN_UID (insn)
- || INSN_ADDRESSES (INSN_UID (insn)) == -1)
+ || INSN_ADDRESSES (INSN_UID (insn)) == -1)
continue;
- if (TARGET_CPU_ZARCH)
- {
- if (curr_pool->size < S390_POOL_CHUNK_MAX)
- continue;
-
- s390_end_pool (curr_pool, NULL);
- curr_pool = NULL;
- }
- else
- {
- int chunk_size = INSN_ADDRESSES (INSN_UID (insn))
- - INSN_ADDRESSES (INSN_UID (curr_pool->first_insn))
- + extra_size;
-
- /* We will later have to insert base register reload insns.
- Those will have an effect on code size, which we need to
- consider here. This calculation makes rather pessimistic
- worst-case assumptions. */
- if (LABEL_P (insn))
- extra_size += 6;
-
- if (chunk_size < S390_POOL_CHUNK_MIN
- && curr_pool->size < S390_POOL_CHUNK_MIN
- && !section_switch_p)
- continue;
-
- /* Pool chunks can only be inserted after BARRIERs ... */
- if (BARRIER_P (insn))
- {
- s390_end_pool (curr_pool, insn);
- curr_pool = NULL;
- extra_size = 0;
- }
-
- /* ... so if we don't find one in time, create one. */
- else if (chunk_size > S390_POOL_CHUNK_MAX
- || curr_pool->size > S390_POOL_CHUNK_MAX
- || section_switch_p)
- {
- rtx_insn *label, *jump, *barrier, *next, *prev;
-
- if (!section_switch_p)
- {
- /* We can insert the barrier only after a 'real' insn. */
- if (! NONJUMP_INSN_P (insn) && ! CALL_P (insn))
- continue;
- if (get_attr_length (insn) == 0)
- continue;
- /* Don't separate LTREL_BASE from the corresponding
- LTREL_OFFSET load. */
- if (pending_ltrel)
- continue;
- next = insn;
- do
- {
- insn = next;
- next = NEXT_INSN (insn);
- }
- while (next
- && NOTE_P (next)
- && NOTE_KIND (next) == NOTE_INSN_VAR_LOCATION);
- }
- else
- {
- gcc_assert (!pending_ltrel);
-
- /* The old pool has to end before the section switch
- note in order to make it part of the current
- section. */
- insn = PREV_INSN (insn);
- }
+ if (curr_pool->size < S390_POOL_CHUNK_MAX)
+ continue;
- label = gen_label_rtx ();
- prev = insn;
- if (prev && NOTE_P (prev))
- prev = prev_nonnote_insn (prev);
- if (prev)
- jump = emit_jump_insn_after_setloc (gen_jump (label), insn,
- INSN_LOCATION (prev));
- else
- jump = emit_jump_insn_after_noloc (gen_jump (label), insn);
- barrier = emit_barrier_after (jump);
- insn = emit_label_after (label, barrier);
- JUMP_LABEL (jump) = label;
- LABEL_NUSES (label) = 1;
-
- INSN_ADDRESSES_NEW (jump, -1);
- INSN_ADDRESSES_NEW (barrier, -1);
- INSN_ADDRESSES_NEW (insn, -1);
-
- s390_end_pool (curr_pool, barrier);
- curr_pool = NULL;
- extra_size = 0;
- }
- }
+ s390_end_pool (curr_pool, NULL);
+ curr_pool = NULL;
}
if (curr_pool)
s390_end_pool (curr_pool, NULL);
- gcc_assert (!pending_ltrel);
/* Find all labels that are branched into
from an insn belonging to a different chunk. */
@@ -9435,8 +8906,8 @@ s390_chunkify_start (void)
for (curr_pool = pool_list; curr_pool; curr_pool = curr_pool->next)
{
- rtx new_insn = gen_reload_base (cfun->machine->base_reg,
- curr_pool->label);
+ rtx new_insn = gen_reload_base_64 (cfun->machine->base_reg,
+ curr_pool->label);
rtx_insn *insn = curr_pool->first_insn;
INSN_ADDRESSES_NEW (emit_insn_before (new_insn, insn), -1);
}
@@ -9445,13 +8916,13 @@ s390_chunkify_start (void)
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
if (LABEL_P (insn)
- && bitmap_bit_p (far_labels, CODE_LABEL_NUMBER (insn)))
+ && bitmap_bit_p (far_labels, CODE_LABEL_NUMBER (insn)))
{
struct constant_pool *pool = s390_find_pool (pool_list, insn);
if (pool)
{
- rtx new_insn = gen_reload_base (cfun->machine->base_reg,
- pool->label);
+ rtx new_insn = gen_reload_base_64 (cfun->machine->base_reg,
+ pool->label);
INSN_ADDRESSES_NEW (emit_insn_after (new_insn, insn), -1);
}
}
@@ -9483,19 +8954,16 @@ s390_chunkify_finish (struct constant_pool *pool_list)
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
- if (INSN_P (insn))
- replace_ltrel_base (&PATTERN (insn));
-
curr_pool = s390_find_pool (pool_list, insn);
if (!curr_pool)
continue;
if (NONJUMP_INSN_P (insn) || CALL_P (insn))
- {
- rtx addr, pool_ref = NULL_RTX;
- find_constant_pool_ref (PATTERN (insn), &pool_ref);
- if (pool_ref)
- {
+ {
+ rtx addr, pool_ref = NULL_RTX;
+ find_constant_pool_ref (PATTERN (insn), &pool_ref);
+ if (pool_ref)
+ {
if (s390_execute_label (insn))
addr = s390_find_execute (curr_pool, insn);
else
@@ -9503,10 +8971,10 @@ s390_chunkify_finish (struct constant_pool *pool_list)
get_pool_constant (pool_ref),
get_pool_mode (pool_ref));
- replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
- INSN_CODE (insn) = -1;
- }
- }
+ replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
+ INSN_CODE (insn) = -1;
+ }
+ }
}
/* Dump out all literal pools. */
@@ -9524,66 +8992,6 @@ s390_chunkify_finish (struct constant_pool *pool_list)
}
}
-/* POOL_LIST is a chunk list as prepared by s390_chunkify_start.
- We have decided we cannot use this list, so revert all changes
- to the current function that were done by s390_chunkify_start. */
-
-static void
-s390_chunkify_cancel (struct constant_pool *pool_list)
-{
- struct constant_pool *curr_pool = NULL;
- rtx_insn *insn;
-
- /* Remove all pool placeholder insns. */
-
- for (curr_pool = pool_list; curr_pool; curr_pool = curr_pool->next)
- {
- /* Did we insert an extra barrier? Remove it. */
- rtx_insn *barrier = PREV_INSN (curr_pool->pool_insn);
- rtx_insn *jump = barrier? PREV_INSN (barrier) : NULL;
- rtx_insn *label = NEXT_INSN (curr_pool->pool_insn);
-
- if (jump && JUMP_P (jump)
- && barrier && BARRIER_P (barrier)
- && label && LABEL_P (label)
- && GET_CODE (PATTERN (jump)) == SET
- && SET_DEST (PATTERN (jump)) == pc_rtx
- && GET_CODE (SET_SRC (PATTERN (jump))) == LABEL_REF
- && XEXP (SET_SRC (PATTERN (jump)), 0) == label)
- {
- remove_insn (jump);
- remove_insn (barrier);
- remove_insn (label);
- }
-
- remove_insn (curr_pool->pool_insn);
- }
-
- /* Remove all base register reload insns. */
-
- for (insn = get_insns (); insn; )
- {
- rtx_insn *next_insn = NEXT_INSN (insn);
-
- if (NONJUMP_INSN_P (insn)
- && GET_CODE (PATTERN (insn)) == SET
- && GET_CODE (SET_SRC (PATTERN (insn))) == UNSPEC
- && XINT (SET_SRC (PATTERN (insn)), 1) == UNSPEC_RELOAD_BASE)
- remove_insn (insn);
-
- insn = next_insn;
- }
-
- /* Free pool list. */
-
- while (pool_list)
- {
- struct constant_pool *next = pool_list->next;
- s390_free_pool (pool_list);
- pool_list = next;
- }
-}
-
/* Output the constant pool entry EXP in mode MODE with alignment ALIGN. */
void
@@ -9646,16 +9054,7 @@ s390_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED)
value of RETURN_REGNUM is actually saved. */
if (count == 0)
- {
- /* On non-z architectures branch splitting could overwrite r14. */
- if (TARGET_CPU_ZARCH)
- return get_hard_reg_initial_val (Pmode, RETURN_REGNUM);
- else
- {
- cfun_frame_layout.save_return_addr_p = true;
- return gen_rtx_MEM (Pmode, return_address_pointer_rtx);
- }
- }
+ return get_hard_reg_initial_val (Pmode, RETURN_REGNUM);
if (TARGET_PACKED_STACK)
offset = -2 * UNITS_PER_LONG;
@@ -10074,7 +9473,6 @@ s390_register_info ()
clobbered_regs[RETURN_REGNUM]
|= (!crtl->is_leaf
|| TARGET_TPF_PROFILING
- || cfun->machine->split_branches_pending_p
|| cfun_frame_layout.save_return_addr_p
|| crtl->calls_eh_return);
@@ -10113,7 +9511,6 @@ s390_optimize_register_info ()
int i;
gcc_assert (epilogue_completed);
- gcc_assert (!cfun->machine->split_branches_pending_p);
s390_regs_ever_clobbered (clobbered_regs);
@@ -10281,20 +9678,12 @@ s390_init_frame_layout (void)
if (reload_completed)
return;
- /* On S/390 machines, we may need to perform branch splitting, which
- will require both base and return address register. We have no
- choice but to assume we're going to need them until right at the
- end of the machine dependent reorg phase. */
- if (!TARGET_CPU_ZARCH)
- cfun->machine->split_branches_pending_p = true;
-
do
{
frame_size = cfun_frame_layout.frame_size;
/* Try to predict whether we'll need the base register. */
- base_used = cfun->machine->split_branches_pending_p
- || crtl->uses_const_pool
+ base_used = crtl->uses_const_pool
|| (!DISP_IN_RANGE (frame_size)
&& !CONST_OK_FOR_K (frame_size));
@@ -10746,7 +10135,7 @@ s390_lra_p (void)
static bool
s390_can_eliminate (const int from, const int to)
{
- /* On zSeries machines, we have not marked the base register as fixed.
+ /* We have not marked the base register as fixed.
Instead, we have an elimination rule BASE_REGNUM -> BASE_REGNUM.
If a function requires the base register, we say here that this
elimination cannot be performed. This will cause reload to free
@@ -10756,13 +10145,8 @@ s390_can_eliminate (const int from, const int to)
to allocate the base register for any other purpose. */
if (from == BASE_REGNUM && to == BASE_REGNUM)
{
- if (TARGET_CPU_ZARCH)
- {
- s390_init_frame_layout ();
- return cfun->machine->base_reg == NULL_RTX;
- }
-
- return false;
+ s390_init_frame_layout ();
+ return cfun->machine->base_reg == NULL_RTX;
}
/* Everything else must point into the stack frame. */
@@ -10906,9 +10290,9 @@ save_gprs (rtx base, int offset, int first, int last)
if (first == last)
{
if (TARGET_64BIT)
- insn = gen_movdi (addr, gen_rtx_REG (Pmode, first));
+ insn = gen_movdi (addr, gen_rtx_REG (Pmode, first));
else
- insn = gen_movsi (addr, gen_rtx_REG (Pmode, first));
+ insn = gen_movsi (addr, gen_rtx_REG (Pmode, first));
if (!global_not_special_regno_p (first))
RTX_FRAME_RELATED_P (insn) = 1;
@@ -11019,9 +10403,9 @@ restore_gprs (rtx base, int offset, int first, int last)
if (first == last)
{
if (TARGET_64BIT)
- insn = gen_movdi (gen_rtx_REG (Pmode, first), addr);
+ insn = gen_movdi (gen_rtx_REG (Pmode, first), addr);
else
- insn = gen_movsi (gen_rtx_REG (Pmode, first), addr);
+ insn = gen_movsi (gen_rtx_REG (Pmode, first), addr);
RTX_FRAME_RELATED_P (insn) = 1;
return insn;
@@ -11049,27 +10433,7 @@ s390_load_got (void)
start_sequence ();
- if (TARGET_CPU_ZARCH)
- {
- emit_move_insn (got_rtx, s390_got_symbol ());
- }
- else
- {
- rtx offset;
-
- offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, s390_got_symbol ()),
- UNSPEC_LTREL_OFFSET);
- offset = gen_rtx_CONST (Pmode, offset);
- offset = force_const_mem (Pmode, 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, got_rtx, offset);
-
- emit_move_insn (got_rtx, offset);
- }
+ emit_move_insn (got_rtx, s390_got_symbol ());
insns = get_insns ();
end_sequence ();
@@ -11208,6 +10572,12 @@ pass_s390_early_mach::execute (function *fun)
} // anon namespace
+rtl_opt_pass *
+make_pass_s390_early_mach (gcc::context *ctxt)
+{
+ return new pass_s390_early_mach (ctxt);
+}
+
/* Calculate TARGET = REG + OFFSET as s390_emit_prologue would do it.
- push too big immediates to the literal pool and annotate the refs
- emit frame related notes for stack pointer changes. */
@@ -11577,7 +10947,7 @@ s390_emit_prologue (void)
t, const0_rtx, const0_rtx));
}
}
- }
+ }
if (s390_warn_framesize > 0
&& cfun_frame_layout.frame_size >= s390_warn_framesize)
@@ -11712,7 +11082,7 @@ s390_emit_prologue (void)
void
s390_emit_epilogue (bool sibcall)
{
- rtx frame_pointer, return_reg, cfa_restores = NULL_RTX;
+ rtx frame_pointer, return_reg = NULL_RTX, cfa_restores = NULL_RTX;
int area_bottom, area_top, offset = 0;
int next_offset;
int i;
@@ -11725,7 +11095,7 @@ s390_emit_epilogue (bool sibcall)
algorithms located at the branch target. */
/* Emit a blockage here so that all code
- lies between the profiling mechanisms. */
+ lies between the profiling mechanisms. */
emit_insn (gen_blockage ());
emit_insn (gen_epilogue_tpf ());
@@ -11746,7 +11116,7 @@ s390_emit_epilogue (bool sibcall)
/* Nothing to restore. */
}
else if (DISP_IN_RANGE (cfun_frame_layout.frame_size + area_bottom)
- && DISP_IN_RANGE (cfun_frame_layout.frame_size + area_top - 1))
+ && DISP_IN_RANGE (cfun_frame_layout.frame_size + area_top - 1))
{
/* Area is in range. */
offset = cfun_frame_layout.frame_size;
@@ -11821,10 +11191,6 @@ s390_emit_epilogue (bool sibcall)
}
- /* Return register. */
-
- return_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
-
/* Restore call saved gprs. */
if (cfun_frame_layout.first_restore_gpr != -1)
@@ -11914,7 +11280,19 @@ s390_emit_epilogue (bool sibcall)
s390_restore_gprs_from_fprs ();
if (! sibcall)
- emit_jump_insn (gen_return_use (return_reg));
+ {
+ if (!return_reg && !s390_can_use_return_insn ())
+ /* We planned to emit (return), be we are not allowed to. */
+ return_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
+
+ if (return_reg)
+ /* Emit (return) and (use). */
+ emit_jump_insn (gen_return_use (return_reg));
+ else
+ /* The fact that RETURN_REGNUM is used is already reflected by
+ EPILOGUE_USES. Emit plain (return). */
+ emit_jump_insn (gen_return ());
+ }
}
/* Implement TARGET_SET_UP_BY_PROLOGUE. */
@@ -11961,11 +11339,6 @@ s390_expand_split_stack_prologue (void)
rtx tmp;
gcc_assert (flag_split_stack && reload_completed);
- if (!TARGET_CPU_ZARCH)
- {
- sorry ("CPUs older than z900 are not supported for -fsplit-stack");
- return;
- }
r1 = gen_rtx_REG (Pmode, 1);
@@ -12049,8 +11422,8 @@ s390_expand_split_stack_prologue (void)
LABEL_NUSES (call_done)++;
/* Mark the jump as very unlikely to be taken. */
- add_reg_br_prob_note (insn,
- profile_probability::very_unlikely ());
+ add_reg_br_prob_note (insn,
+ profile_probability::very_unlikely ());
if (cfun->machine->split_stack_varargs_pointer != NULL_RTX)
{
@@ -12318,7 +11691,7 @@ s390_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED,
if (type)
{
if (AGGREGATE_TYPE_P (type) && exact_log2 (size) < 0)
- return true;
+ return true;
if (TREE_CODE (type) == COMPLEX_TYPE
|| TREE_CODE (type) == VECTOR_TYPE)
@@ -12491,9 +11864,9 @@ s390_return_in_memory (const_tree type, const_tree fundecl ATTRIBUTE_UNUSED)
static machine_mode
s390_promote_function_mode (const_tree type, machine_mode mode,
- int *punsignedp,
- const_tree fntype ATTRIBUTE_UNUSED,
- int for_return ATTRIBUTE_UNUSED)
+ int *punsignedp,
+ const_tree fntype ATTRIBUTE_UNUSED,
+ int for_return ATTRIBUTE_UNUSED)
{
if (INTEGRAL_MODE_P (mode)
&& GET_MODE_SIZE (mode) < UNITS_PER_LONG)
@@ -12588,12 +11961,12 @@ s390_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
On S/390, va_list is an array type equivalent to
typedef struct __va_list_tag
- {
- long __gpr;
- long __fpr;
- void *__overflow_arg_area;
- void *__reg_save_area;
- } va_list[1];
+ {
+ long __gpr;
+ long __fpr;
+ void *__overflow_arg_area;
+ void *__reg_save_area;
+ } va_list[1];
where __gpr and __fpr hold the number of general purpose
or floating point arguments used up to now, respectively,
@@ -12697,14 +12070,14 @@ s390_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
if (cfun->va_list_fpr_size)
{
t = build2 (MODIFY_EXPR, TREE_TYPE (fpr), fpr,
- build_int_cst (NULL_TREE, n_fpr));
+ build_int_cst (NULL_TREE, n_fpr));
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
if (flag_split_stack
&& (lookup_attribute ("no_split_stack", DECL_ATTRIBUTES (cfun->decl))
- == NULL)
+ == NULL)
&& cfun->machine->split_stack_varargs_pointer == NULL_RTX)
{
rtx reg;
@@ -12732,9 +12105,9 @@ s390_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
|| TARGET_VX_ABI)
{
if (cfun->machine->split_stack_varargs_pointer == NULL_RTX)
- t = make_tree (TREE_TYPE (ovf), virtual_incoming_args_rtx);
+ t = make_tree (TREE_TYPE (ovf), virtual_incoming_args_rtx);
else
- t = make_tree (TREE_TYPE (ovf), cfun->machine->split_stack_varargs_pointer);
+ t = make_tree (TREE_TYPE (ovf), cfun->machine->split_stack_varargs_pointer);
off = INTVAL (crtl->args.arg_offset_rtx);
off = off < 0 ? 0 : off;
@@ -12770,7 +12143,7 @@ s390_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
if (integral value) {
if (size <= 4 && args.gpr < 5 ||
- size > 4 && args.gpr < 4 )
+ size > 4 && args.gpr < 4 )
ret = args.reg_save_area[args.gpr+8]
else
ret = *args.overflow_arg_area++;
@@ -12906,13 +12279,13 @@ s390_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
{
/*
if (reg > ((typeof (reg))max_reg))
- goto lab_false;
+ goto lab_false;
- addr = sav + sav_ofs + reg * save_scale;
+ addr = sav + sav_ofs + reg * save_scale;
goto lab_over;
- lab_false:
+ lab_false:
*/
lab_false = create_artificial_label (UNKNOWN_LOCATION);
@@ -12986,11 +12359,11 @@ s390_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
expanders.
DEST - Register location where CC will be stored.
TDB - Pointer to a 256 byte area where to store the transaction.
- diagnostic block. NULL if TDB is not needed.
+ diagnostic block. NULL if TDB is not needed.
RETRY - Retry count value. If non-NULL a retry loop for CC2
- is emitted
+ is emitted
CLOBBER_FPRS_P - If true clobbers for all FPRs are emitted as part
- of the tbegin instruction pattern. */
+ of the tbegin instruction pattern. */
void
s390_expand_tbegin (rtx dest, rtx tdb, rtx retry, bool clobber_fprs_p)
@@ -13130,21 +12503,21 @@ output_asm_nops (const char *user, int hw)
asm_fprintf (asm_out_file, "\t# NOPs for %s (%d halfwords)\n", user, hw);
while (hw > 0)
{
- if (TARGET_CPU_ZARCH && hw >= 3)
- {
- output_asm_insn ("brcl\t0,0", NULL);
- hw -= 3;
- }
+ if (hw >= 3)
+ {
+ output_asm_insn ("brcl\t0,0", NULL);
+ hw -= 3;
+ }
else if (hw >= 2)
- {
- output_asm_insn ("bc\t0,0", NULL);
- hw -= 2;
- }
+ {
+ output_asm_insn ("bc\t0,0", NULL);
+ hw -= 2;
+ }
else
- {
- output_asm_insn ("bcr\t0,0", NULL);
- hw -= 1;
- }
+ {
+ output_asm_insn ("bcr\t0,0", NULL);
+ hw -= 1;
+ }
}
}
@@ -13183,102 +12556,46 @@ s390_function_profiler (FILE *file, int labelno)
if (flag_fentry)
{
if (flag_nop_mcount)
- output_asm_nops ("-mnop-mcount", /* brasl */ 3);
+ output_asm_nops ("-mnop-mcount", /* brasl */ 3);
else if (cfun->static_chain_decl)
- warning (OPT_Wcannot_profile, "nested functions cannot be profiled "
- "with -mfentry on s390");
+ warning (OPT_Wcannot_profile, "nested functions cannot be profiled "
+ "with -mfentry on s390");
else
- output_asm_insn ("brasl\t0,%4", op);
+ output_asm_insn ("brasl\t0,%4", op);
}
else if (TARGET_64BIT)
{
if (flag_nop_mcount)
- output_asm_nops ("-mnop-mcount", /* stg */ 3 + /* larl */ 3 +
- /* brasl */ 3 + /* lg */ 3);
- else
- {
- output_asm_insn ("stg\t%0,%1", op);
- if (flag_dwarf2_cfi_asm)
- output_asm_insn (".cfi_rel_offset\t%0,%7", op);
- output_asm_insn ("larl\t%2,%3", op);
- output_asm_insn ("brasl\t%0,%4", op);
- output_asm_insn ("lg\t%0,%1", op);
- if (flag_dwarf2_cfi_asm)
- output_asm_insn (".cfi_restore\t%0", op);
- }
- }
- else if (TARGET_CPU_ZARCH)
- {
- if (flag_nop_mcount)
- output_asm_nops ("-mnop-mcount", /* st */ 2 + /* larl */ 3 +
- /* brasl */ 3 + /* l */ 2);
- else
- {
- output_asm_insn ("st\t%0,%1", op);
- if (flag_dwarf2_cfi_asm)
- output_asm_insn (".cfi_rel_offset\t%0,%7", op);
- output_asm_insn ("larl\t%2,%3", op);
- output_asm_insn ("brasl\t%0,%4", op);
- output_asm_insn ("l\t%0,%1", op);
- if (flag_dwarf2_cfi_asm)
- output_asm_insn (".cfi_restore\t%0", op);
- }
- }
- else if (!flag_pic)
- {
- op[6] = gen_label_rtx ();
-
- if (flag_nop_mcount)
- output_asm_nops ("-mnop-mcount", /* st */ 2 + /* bras */ 2 +
- /* .long */ 2 + /* .long */ 2 + /* l */ 2 +
- /* l */ 2 + /* basr */ 1 + /* l */ 2);
+ output_asm_nops ("-mnop-mcount", /* stg */ 3 + /* larl */ 3 +
+ /* brasl */ 3 + /* lg */ 3);
else
- {
- output_asm_insn ("st\t%0,%1", op);
- if (flag_dwarf2_cfi_asm)
- output_asm_insn (".cfi_rel_offset\t%0,%7", op);
- output_asm_insn ("bras\t%2,%l6", op);
- output_asm_insn (".long\t%4", op);
- output_asm_insn (".long\t%3", op);
- targetm.asm_out.internal_label (file, "L",
- CODE_LABEL_NUMBER (op[6]));
- output_asm_insn ("l\t%0,0(%2)", op);
- output_asm_insn ("l\t%2,4(%2)", op);
- output_asm_insn ("basr\t%0,%0", op);
- output_asm_insn ("l\t%0,%1", op);
- if (flag_dwarf2_cfi_asm)
- output_asm_insn (".cfi_restore\t%0", op);
- }
+ {
+ output_asm_insn ("stg\t%0,%1", op);
+ if (flag_dwarf2_cfi_asm)
+ output_asm_insn (".cfi_rel_offset\t%0,%7", op);
+ output_asm_insn ("larl\t%2,%3", op);
+ output_asm_insn ("brasl\t%0,%4", op);
+ output_asm_insn ("lg\t%0,%1", op);
+ if (flag_dwarf2_cfi_asm)
+ output_asm_insn (".cfi_restore\t%0", op);
+ }
}
else
{
- op[5] = gen_label_rtx ();
- op[6] = gen_label_rtx ();
-
if (flag_nop_mcount)
- output_asm_nops ("-mnop-mcount", /* st */ 2 + /* bras */ 2 +
- /* .long */ 2 + /* .long */ 2 + /* lr */ 1 +
- /* a */ 2 + /* a */ 2 + /* basr */ 1 + /* l */ 2);
+ output_asm_nops ("-mnop-mcount", /* st */ 2 + /* larl */ 3 +
+ /* brasl */ 3 + /* l */ 2);
else
- {
- output_asm_insn ("st\t%0,%1", op);
- if (flag_dwarf2_cfi_asm)
- output_asm_insn (".cfi_rel_offset\t%0,%7", op);
- output_asm_insn ("bras\t%2,%l6", op);
- targetm.asm_out.internal_label (file, "L",
- CODE_LABEL_NUMBER (op[5]));
- output_asm_insn (".long\t%4-%l5", op);
- output_asm_insn (".long\t%3-%l5", op);
- targetm.asm_out.internal_label (file, "L",
- CODE_LABEL_NUMBER (op[6]));
- output_asm_insn ("lr\t%0,%2", op);
- output_asm_insn ("a\t%0,0(%2)", op);
- output_asm_insn ("a\t%2,4(%2)", op);
- output_asm_insn ("basr\t%0,%0", op);
- output_asm_insn ("l\t%0,%1", op);
- if (flag_dwarf2_cfi_asm)
- output_asm_insn (".cfi_restore\t%0", op);
- }
+ {
+ output_asm_insn ("st\t%0,%1", op);
+ if (flag_dwarf2_cfi_asm)
+ output_asm_insn (".cfi_rel_offset\t%0,%7", op);
+ output_asm_insn ("larl\t%2,%3", op);
+ output_asm_insn ("brasl\t%0,%4", op);
+ output_asm_insn ("l\t%0,%1", op);
+ if (flag_dwarf2_cfi_asm)
+ output_asm_insn (".cfi_restore\t%0", op);
+ }
}
if (flag_record_mcount)
@@ -13401,8 +12718,8 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
output_asm_insn ("lay\t%1,%2(%1)", op);
else if (CONST_OK_FOR_K (delta))
output_asm_insn ("aghi\t%1,%2", op);
- else if (CONST_OK_FOR_Os (delta))
- output_asm_insn ("agfi\t%1,%2", op);
+ else if (CONST_OK_FOR_Os (delta))
+ output_asm_insn ("agfi\t%1,%2", op);
else
{
op[6] = gen_label_rtx ();
@@ -13424,12 +12741,12 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
output_asm_insn ("ag\t%4,0(%1)", op);
output_asm_insn ("ag\t%1,0(%4)", op);
}
- else if (CONST_OK_FOR_Os (vcall_offset))
- {
- output_asm_insn ("lgfi\t%4,%3", op);
- output_asm_insn ("ag\t%4,0(%1)", op);
- output_asm_insn ("ag\t%1,0(%4)", op);
- }
+ else if (CONST_OK_FOR_Os (vcall_offset))
+ {
+ output_asm_insn ("lgfi\t%4,%3", op);
+ output_asm_insn ("ag\t%4,0(%1)", op);
+ output_asm_insn ("ag\t%1,0(%4)", op);
+ }
else
{
op[7] = gen_label_rtx ();
@@ -13467,10 +12784,10 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
/* Setup base pointer if required. */
if (!vcall_offset
|| (!DISP_IN_RANGE (delta)
- && !CONST_OK_FOR_K (delta)
+ && !CONST_OK_FOR_K (delta)
&& !CONST_OK_FOR_Os (delta))
|| (!DISP_IN_RANGE (delta)
- && !CONST_OK_FOR_K (vcall_offset)
+ && !CONST_OK_FOR_K (vcall_offset)
&& !CONST_OK_FOR_Os (vcall_offset)))
{
op[5] = gen_label_rtx ();
@@ -13489,7 +12806,7 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
else if (CONST_OK_FOR_K (delta))
output_asm_insn ("ahi\t%1,%2", op);
else if (CONST_OK_FOR_Os (delta))
- output_asm_insn ("afi\t%1,%2", op);
+ output_asm_insn ("afi\t%1,%2", op);
else
{
op[6] = gen_label_rtx ();
@@ -13499,7 +12816,7 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
/* Perform vcall adjustment. */
if (vcall_offset)
- {
+ {
if (CONST_OK_FOR_J (vcall_offset))
{
output_asm_insn ("l\t%4,0(%1)", op);
@@ -13517,11 +12834,11 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
output_asm_insn ("a\t%1,0(%4)", op);
}
else if (CONST_OK_FOR_Os (vcall_offset))
- {
- output_asm_insn ("iilf\t%4,%3", op);
- output_asm_insn ("a\t%4,0(%1)", op);
- output_asm_insn ("a\t%1,0(%4)", op);
- }
+ {
+ output_asm_insn ("iilf\t%4,%3", op);
+ output_asm_insn ("a\t%4,0(%1)", op);
+ output_asm_insn ("a\t%1,0(%4)", op);
+ }
else
{
op[7] = gen_label_rtx ();
@@ -13746,10 +13063,10 @@ s390_call_saved_register_used (tree call_expr)
named. This only has an impact on vector argument register
usage none of which is call-saved. */
if (pass_by_reference (&cum_v, mode, type, true))
- {
- mode = Pmode;
- type = build_pointer_type (type);
- }
+ {
+ mode = Pmode;
+ type = build_pointer_type (type);
+ }
parm_rtx = s390_function_arg (cum, mode, type, true);
@@ -13759,10 +13076,10 @@ s390_call_saved_register_used (tree call_expr)
continue;
if (REG_P (parm_rtx))
- {
+ {
for (reg = 0; reg < REG_NREGS (parm_rtx); reg++)
if (!call_used_regs[reg + REGNO (parm_rtx)])
- return true;
+ return true;
}
if (GET_CODE (parm_rtx) == PARALLEL)
@@ -13834,8 +13151,8 @@ s390_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
TLS_CALL the location of the thread-local symbol
RESULT_REG the register where the result of the call should be stored
RETADDR_REG the register where the return address should be stored
- If this parameter is NULL_RTX the call is considered
- to be a sibling call. */
+ If this parameter is NULL_RTX the call is considered
+ to be a sibling call. */
rtx_insn *
s390_emit_call (rtx addr_location, rtx tls_call, rtx result_reg,
@@ -13855,9 +13172,9 @@ s390_emit_call (rtx addr_location, rtx tls_call, rtx result_reg,
if (GET_CODE (addr_location) == SYMBOL_REF)
{
/* When calling a global routine in PIC mode, we must
- replace the symbol itself with the PLT stub. */
+ replace the symbol itself with the PLT stub. */
if (flag_pic && !SYMBOL_REF_LOCAL_P (addr_location))
- {
+ {
if (TARGET_64BIT || retaddr_reg != NULL_RTX)
{
addr_location = gen_rtx_UNSPEC (Pmode,
@@ -13877,16 +13194,6 @@ s390_emit_call (rtx addr_location, rtx tls_call, rtx result_reg,
optimization is illegal for S/390 so we turn the direct
call into a indirect call again. */
addr_location = force_reg (Pmode, addr_location);
- }
-
- /* Unless we can use the bras(l) insn, force the
- routine address into a register. */
- if (!TARGET_SMALL_EXEC && !TARGET_CPU_ZARCH)
- {
- if (flag_pic)
- addr_location = legitimize_pic_address (addr_location, 0);
- else
- addr_location = force_reg (Pmode, addr_location);
}
}
@@ -13977,13 +13284,10 @@ s390_conditional_register_usage (void)
fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
}
- if (TARGET_CPU_ZARCH)
- {
- fixed_regs[BASE_REGNUM] = 0;
- call_used_regs[BASE_REGNUM] = 0;
- fixed_regs[RETURN_REGNUM] = 0;
- call_used_regs[RETURN_REGNUM] = 0;
- }
+ fixed_regs[BASE_REGNUM] = 0;
+ call_used_regs[BASE_REGNUM] = 0;
+ fixed_regs[RETURN_REGNUM] = 0;
+ call_used_regs[RETURN_REGNUM] = 0;
if (TARGET_64BIT)
{
for (i = FPR8_REGNUM; i <= FPR15_REGNUM; i++)
@@ -14027,7 +13331,7 @@ s390_emit_tpf_eh_return (rtx target)
emit_move_insn (reg, target);
emit_move_insn (orig_ra, get_hard_reg_initial_val (Pmode, RETURN_REGNUM));
insn = s390_emit_call (s390_tpf_eh_return_symbol, NULL_RTX, reg,
- gen_rtx_REG (Pmode, RETURN_REGNUM));
+ gen_rtx_REG (Pmode, RETURN_REGNUM));
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), reg);
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), orig_ra);
@@ -14049,14 +13353,10 @@ s390_optimize_prologue (void)
can do, so no point in walking the insn list. */
if (cfun_frame_layout.first_save_gpr <= BASE_REGNUM
- && cfun_frame_layout.last_save_gpr >= BASE_REGNUM
- && (TARGET_CPU_ZARCH
- || (cfun_frame_layout.first_save_gpr <= RETURN_REGNUM
- && cfun_frame_layout.last_save_gpr >= RETURN_REGNUM)))
+ && cfun_frame_layout.last_save_gpr >= BASE_REGNUM)
return;
/* Search for prologue/epilogue insns and replace them. */
-
for (insn = get_insns (); insn; insn = next_insn)
{
int first, last, off;
@@ -14632,7 +13932,8 @@ s390_adjust_loops ()
static void
s390_reorg (void)
{
- bool pool_overflow = false;
+ struct constant_pool *pool;
+ rtx_insn *insn;
int hw_before, hw_after;
if (s390_tune == PROCESSOR_2964_Z13)
@@ -14643,109 +13944,54 @@ s390_reorg (void)
split_all_insns_noflow ();
/* Install the main literal pool and the associated base
- register load insns.
-
- In addition, there are two problematic situations we need
- to correct:
-
- - the literal pool might be > 4096 bytes in size, so that
- some of its elements cannot be directly accessed
-
- - a branch target might be > 64K away from the branch, so that
- it is not possible to use a PC-relative instruction.
+ register load insns. The literal pool might be > 4096 bytes in
+ size, so that some of its elements cannot be directly accessed.
- To fix those, we split the single literal pool into multiple
+ To fix this, we split the single literal pool into multiple
pool chunks, reloading the pool base register at various
points throughout the function to ensure it always points to
- the pool chunk the following code expects, and / or replace
- PC-relative branches by absolute branches.
-
- However, the two problems are interdependent: splitting the
- literal pool can move a branch further away from its target,
- causing the 64K limit to overflow, and on the other hand,
- replacing a PC-relative branch by an absolute branch means
- we need to put the branch target address into the literal
- pool, possibly causing it to overflow.
-
- So, we loop trying to fix up both problems until we manage
- to satisfy both conditions at the same time. Note that the
- loop is guaranteed to terminate as every pass of the loop
- strictly decreases the total number of PC-relative branches
- in the function. (This is not completely true as there
- might be branch-over-pool insns introduced by chunkify_start.
- Those never need to be split however.) */
-
- for (;;)
- {
- struct constant_pool *pool = NULL;
-
- /* Collect the literal pool. */
- if (!pool_overflow)
- {
- pool = s390_mainpool_start ();
- if (!pool)
- pool_overflow = true;
- }
-
- /* If literal pool overflowed, start to chunkify it. */
- if (pool_overflow)
- pool = s390_chunkify_start ();
-
- /* Split out-of-range branches. If this has created new
- literal pool entries, cancel current chunk list and
- recompute it. zSeries machines have large branch
- instructions, so we never need to split a branch. */
- if (!TARGET_CPU_ZARCH && s390_split_branches ())
- {
- if (pool_overflow)
- s390_chunkify_cancel (pool);
- else
- s390_mainpool_cancel (pool);
+ the pool chunk the following code expects. */
- continue;
- }
-
- /* If we made it up to here, both conditions are satisfied.
- Finish up literal pool related changes. */
- if (pool_overflow)
- s390_chunkify_finish (pool);
- else
- s390_mainpool_finish (pool);
-
- /* We're done splitting branches. */
- cfun->machine->split_branches_pending_p = false;
- break;
+ /* Collect the literal pool. */
+ pool = s390_mainpool_start ();
+ if (pool)
+ {
+ /* Finish up literal pool related changes. */
+ s390_mainpool_finish (pool);
+ }
+ else
+ {
+ /* If literal pool overflowed, chunkify it. */
+ pool = s390_chunkify_start ();
+ s390_chunkify_finish (pool);
}
/* Generate out-of-pool execute target insns. */
- if (TARGET_CPU_ZARCH)
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
- rtx_insn *insn, *target;
rtx label;
+ rtx_insn *target;
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- label = s390_execute_label (insn);
- if (!label)
- continue;
+ label = s390_execute_label (insn);
+ if (!label)
+ continue;
- gcc_assert (label != const0_rtx);
+ gcc_assert (label != const0_rtx);
- target = emit_label (XEXP (label, 0));
- INSN_ADDRESSES_NEW (target, -1);
+ target = emit_label (XEXP (label, 0));
+ INSN_ADDRESSES_NEW (target, -1);
- if (JUMP_P (insn))
- {
- target = emit_jump_insn (s390_execute_target (insn));
- /* This is important in order to keep a table jump
- pointing at the jump table label. Only this makes it
- being recognized as table jump. */
- JUMP_LABEL (target) = JUMP_LABEL (insn);
- }
- else
- target = emit_insn (s390_execute_target (insn));
- INSN_ADDRESSES_NEW (target, -1);
+ if (JUMP_P (insn))
+ {
+ target = emit_jump_insn (s390_execute_target (insn));
+ /* This is important in order to keep a table jump
+ pointing at the jump table label. Only this makes it
+ being recognized as table jump. */
+ JUMP_LABEL (target) = JUMP_LABEL (insn);
}
+ else
+ target = emit_insn (s390_execute_target (insn));
+ INSN_ADDRESSES_NEW (target, -1);
}
/* Try to optimize prologue and epilogue further. */
@@ -14802,7 +14048,7 @@ s390_reorg (void)
/* Output a series of NOPs before the first active insn. */
while (insn && hw_after > 0)
{
- if (hw_after >= 3 && TARGET_CPU_ZARCH)
+ if (hw_after >= 3)
{
emit_insn_before (gen_nop_6_byte (), insn);
hw_after -= 3;
@@ -15383,9 +14629,29 @@ s390_loop_unroll_adjust (unsigned nunroll, struct loop *loop)
for (i = 0; i < loop->num_nodes; i++)
FOR_BB_INSNS (bbs[i], insn)
if (INSN_P (insn) && INSN_CODE (insn) != -1)
- FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
- if (MEM_P (*iter))
- mem_count += 1;
+ {
+ rtx set;
+
+ /* The runtime of small loops with memory block operations
+ will be determined by the memory operation. Doing
+ unrolling doesn't help here. Measurements to confirm
+ this where only done on recent CPU levels. So better do
+ not change anything for older CPUs. */
+ if (s390_tune >= PROCESSOR_2964_Z13
+ && loop->ninsns <= BLOCK_MEM_OPS_LOOP_INSNS
+ && ((set = single_set (insn)) != NULL_RTX)
+ && ((GET_MODE (SET_DEST (set)) == BLKmode
+ && (GET_MODE (SET_SRC (set)) == BLKmode
+ || SET_SRC (set) == const0_rtx))
+ || (GET_CODE (SET_SRC (set)) == COMPARE
+ && GET_MODE (XEXP (SET_SRC (set), 0)) == BLKmode
+ && GET_MODE (XEXP (SET_SRC (set), 1)) == BLKmode)))
+ return 1;
+
+ FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
+ if (MEM_P (*iter))
+ mem_count += 1;
+ }
free (bbs);
/* Prevent division by zero, and we do not need to adjust nunroll in this case. */
@@ -15430,27 +14696,9 @@ s390_override_options_after_change (void)
}
static void
-s390_option_override_internal (bool main_args_p,
- struct gcc_options *opts,
+s390_option_override_internal (struct gcc_options *opts,
const struct gcc_options *opts_set)
{
- const char *prefix;
- const char *suffix;
-
- /* Set up prefix/suffix so the error messages refer to either the command
- line argument, or the attribute(target). */
- if (main_args_p)
- {
- prefix = "-m";
- suffix = "";
- }
- else
- {
- prefix = "option(\"";
- suffix = "\")";
- }
-
-
/* Architecture mode defaults according to ABI. */
if (!(opts_set->x_target_flags & MASK_ZARCH))
{
@@ -15463,24 +14711,12 @@ s390_option_override_internal (bool main_args_p,
/* Set the march default in case it hasn't been specified on cmdline. */
if (!opts_set->x_s390_arch)
opts->x_s390_arch = PROCESSOR_2064_Z900;
- else if (opts->x_s390_arch == PROCESSOR_9672_G5
- || opts->x_s390_arch == PROCESSOR_9672_G6)
- warning (OPT_Wdeprecated, "%sarch=%s%s is deprecated and will be removed "
- "in future releases; use at least %sarch=z900%s",
- prefix, opts->x_s390_arch == PROCESSOR_9672_G5 ? "g5" : "g6",
- suffix, prefix, suffix);
opts->x_s390_arch_flags = processor_flags_table[(int) opts->x_s390_arch];
/* Determine processor to tune for. */
if (!opts_set->x_s390_tune)
opts->x_s390_tune = opts->x_s390_arch;
- else if (opts->x_s390_tune == PROCESSOR_9672_G5
- || opts->x_s390_tune == PROCESSOR_9672_G6)
- warning (OPT_Wdeprecated, "%stune=%s%s is deprecated and will be removed "
- "in future releases; use at least %stune=z900%s",
- prefix, opts->x_s390_tune == PROCESSOR_9672_G5 ? "g5" : "g6",
- suffix, prefix, suffix);
opts->x_s390_tune_flags = processor_flags_table[opts->x_s390_tune];
@@ -15488,9 +14724,6 @@ s390_option_override_internal (bool main_args_p,
if (opts->x_s390_arch == PROCESSOR_NATIVE
|| opts->x_s390_tune == PROCESSOR_NATIVE)
gcc_unreachable ();
- if (TARGET_ZARCH_P (opts->x_target_flags) && !TARGET_CPU_ZARCH_P (opts))
- error ("z/Architecture mode not supported on %s",
- processor_table[(int)opts->x_s390_arch].name);
if (TARGET_64BIT && !TARGET_ZARCH_P (opts->x_target_flags))
error ("64-bit ABI not supported in ESA/390 mode");
@@ -15519,17 +14752,6 @@ s390_option_override_internal (bool main_args_p,
opts->x_s390_function_return_mem = opts->x_s390_function_return;
}
- if (!TARGET_CPU_ZARCH)
- {
- if (opts->x_s390_indirect_branch_call != indirect_branch_keep
- || opts->x_s390_indirect_branch_jump != indirect_branch_keep)
- error ("-mindirect-branch* options require -march=z900 or higher");
- if (opts->x_s390_function_return_reg != indirect_branch_keep
- || opts->x_s390_function_return_mem != indirect_branch_keep)
- error ("-mfunction-return* options require -march=z900 or higher");
- }
-
-
/* Enable hardware transactions if available and not explicitly
disabled by user. E.g. with -m31 -march=zEC12 -mzarch */
if (!TARGET_OPT_HTM_P (opts_set->x_target_flags))
@@ -15613,6 +14835,17 @@ s390_option_override_internal (bool main_args_p,
else if (opts->x_s390_stack_guard)
error ("-mstack-guard implies use of -mstack-size");
+ /* Our implementation of the stack probe requires the probe interval
+ to be used as displacement in an address operand. The maximum
+ probe interval currently is 64k. This would exceed short
+ displacements. Trim that value down to 4k if that happens. This
+ might result in too many probes being generated only on the
+ oldest supported machine level z900. */
+ if (!DISP_IN_RANGE ((1 << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL))))
+ set_param_value ("stack-clash-protection-probe-interval", 12,
+ opts->x_param_values,
+ opts_set->x_param_values);
+
#ifdef TARGET_DEFAULT_LONG_DOUBLE_128
if (!TARGET_LONG_DOUBLE_128_P (opts_set->x_target_flags))
opts->x_target_flags |= MASK_LONG_DOUBLE_128;
@@ -15659,8 +14892,8 @@ s390_option_override_internal (bool main_args_p,
/* Use the alternative scheduling-pressure algorithm by default. */
maybe_set_param_value (PARAM_SCHED_PRESSURE_ALGORITHM, 2,
- opts->x_param_values,
- opts_set->x_param_values);
+ opts->x_param_values,
+ opts_set->x_param_values);
maybe_set_param_value (PARAM_MIN_VECT_LOOP_BOUND, 2,
opts->x_param_values,
@@ -15736,7 +14969,7 @@ s390_option_override (void)
/* Set up function hooks. */
init_machine_status = s390_init_machine_status;
- s390_option_override_internal (true, &global_options, &global_options_set);
+ s390_option_override_internal (&global_options, &global_options_set);
/* Save the initial options in case the user does function specific
options. */
@@ -15756,26 +14989,11 @@ s390_option_override (void)
{
/* Don't emit DWARF3/4 unless specifically selected. The TPF
debuggers do not yet support DWARF 3/4. */
- if (!global_options_set.x_dwarf_strict)
+ if (!global_options_set.x_dwarf_strict)
dwarf_strict = 1;
if (!global_options_set.x_dwarf_version)
dwarf_version = 2;
}
-
- /* Register a target-specific optimization-and-lowering pass
- to run immediately before prologue and epilogue generation.
-
- Registering the pass must be done at start up. It's
- convenient to do it here. */
- opt_pass *new_pass = new pass_s390_early_mach (g);
- struct register_pass_info insert_pass_s390_early_mach =
- {
- new_pass, /* pass */
- "pro_and_epilogue", /* reference_pass_name */
- 1, /* ref_pass_instance_number */
- PASS_POS_INSERT_BEFORE /* po_op */
- };
- register_pass (&insert_pass_s390_early_mach);
}
#if S390_USE_TARGET_ATTRIBUTE
@@ -16041,7 +15259,7 @@ s390_valid_target_attribute_tree (tree args,
dest[i] |= src[i];
/* Do any overrides, such as arch=xxx, or tune=xxx support. */
- s390_option_override_internal (false, opts, &new_opts_set);
+ s390_option_override_internal (opts, &new_opts_set);
/* Save the current options unless we are validating options for
#pragma. */
t = build_target_option_node (opts);
@@ -16672,7 +15890,7 @@ s390_output_indirect_thunk_function (unsigned int regno, bool z10_p)
if (!TARGET_CPU_Z10)
fputs ("\t.machine pop\n", asm_out_file);
}
- else if (TARGET_CPU_ZARCH)
+ else
{
/* larl %r1,1f */
fprintf (asm_out_file, "\tlarl\t%%r%d,1f\n",
@@ -16682,8 +15900,6 @@ s390_output_indirect_thunk_function (unsigned int regno, bool z10_p)
fprintf (asm_out_file, "\tex\t0,0(%%r%d)\n",
INDIRECT_BRANCH_THUNK_REGNUM);
}
- else
- gcc_unreachable ();
/* 0: j 0b */
fputs ("0:\tj\t0b\n", asm_out_file);
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index 71a12b8..4fb32b8 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -1,8 +1,8 @@
/* Definitions of target machine for GNU compiler, for IBM S/390
Copyright (C) 1999-2018 Free Software Foundation, Inc.
Contributed by Hartmut Penner (hpenner@de.ibm.com) and
- Ulrich Weigand (uweigand@de.ibm.com).
- Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
+ Ulrich Weigand (uweigand@de.ibm.com).
+ Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
This file is part of GCC.
@@ -54,10 +54,6 @@ enum processor_flags
(s390_arch_flags & PF_IEEE_FLOAT)
#define TARGET_CPU_IEEE_FLOAT_P(opts) \
(opts->x_s390_arch_flags & PF_IEEE_FLOAT)
-#define TARGET_CPU_ZARCH \
- (s390_arch_flags & PF_ZARCH)
-#define TARGET_CPU_ZARCH_P(opts) \
- (opts->x_s390_arch_flags & PF_ZARCH)
#define TARGET_CPU_LONG_DISPLACEMENT \
(s390_arch_flags & PF_LONG_DISPLACEMENT)
#define TARGET_CPU_LONG_DISPLACEMENT_P(opts) \
@@ -181,6 +177,16 @@ enum processor_flags
#define TARGET_AVOID_CMP_AND_BRANCH (s390_tune == PROCESSOR_2817_Z196)
+/* Issue a write prefetch for the +4 cache line. */
+#define TARGET_SETMEM_PREFETCH_DISTANCE 1024
+
+/* Expand to a C expressions evaluating to true if a setmem to VAL of
+ length LEN should be emitted using prefetch instructions. */
+#define TARGET_SETMEM_PFD(VAL,LEN) \
+ (TARGET_Z10 \
+ && (s390_tune < PROCESSOR_2964_Z13 || (VAL) != const0_rtx) \
+ && (!CONST_INT_P (LEN) || INTVAL ((LEN)) > TARGET_SETMEM_PREFETCH_DISTANCE))
+
/* Run-time target specification. */
/* Defaults for option flags defined only on some subtargets. */
@@ -196,13 +202,13 @@ enum processor_flags
#ifdef DEFAULT_TARGET_64BIT
#define TARGET_DEFAULT (MASK_64BIT | MASK_ZARCH | MASK_HARD_DFP \
- | MASK_OPT_HTM | MASK_OPT_VX)
+ | MASK_OPT_HTM | MASK_OPT_VX)
#else
#define TARGET_DEFAULT 0
#endif
/* Support for configure-time defaults. */
-#define OPTION_DEFAULT_SPECS \
+#define OPTION_DEFAULT_SPECS \
{ "mode", "%{!mesa:%{!mzarch:-m%(VALUE)}}" }, \
{ "arch", "%{!march=*:-march=%(VALUE)}" }, \
{ "tune", "%{!mtune=*:%{!march=*:-mtune=%(VALUE)}}" }
@@ -255,10 +261,10 @@ extern const char *s390_host_detect_local_cpu (int argc, const char **argv);
/* For signbit, the BFP-DFP-difference makes no difference. */
#define S390_TDC_SIGNBIT_SET (S390_TDC_NEGATIVE_ZERO \
- | S390_TDC_NEGATIVE_NORMALIZED_BFP_NUMBER \
- | S390_TDC_NEGATIVE_DENORMALIZED_BFP_NUMBER\
- | S390_TDC_NEGATIVE_INFINITY \
- | S390_TDC_NEGATIVE_QUIET_NAN \
+ | S390_TDC_NEGATIVE_NORMALIZED_BFP_NUMBER \
+ | S390_TDC_NEGATIVE_DENORMALIZED_BFP_NUMBER\
+ | S390_TDC_NEGATIVE_INFINITY \
+ | S390_TDC_NEGATIVE_QUIET_NAN \
| S390_TDC_NEGATIVE_SIGNALING_NAN )
#define S390_TDC_INFINITY (S390_TDC_POSITIVE_INFINITY \
@@ -412,51 +418,51 @@ extern const char *s390_host_detect_local_cpu (int argc, const char **argv);
All non-FP vector registers are call-clobbered v16-v31. */
#define FIXED_REGISTERS \
-{ 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, 1, 1, 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, \
1, 1, 1, 1, \
1, 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 }
#define CALL_USED_REGISTERS \
-{ 1, 1, 1, 1, \
- 1, 1, 0, 0, \
- 0, 0, 0, 0, \
+{ 1, 1, 1, 1, \
+ 1, 1, 0, 0, \
+ 0, 0, 0, 0, \
0, 1, 1, 1, \
- 1, 1, 1, 1, \
- 1, 1, 1, 1, \
- 1, 1, 1, 1, \
- 1, 1, 1, 1, \
1, 1, 1, 1, \
- 1, 1, \
- 1, 1, 1, 1, \
1, 1, 1, 1, \
- 1, 1, 1, 1, \
+ 1, 1, 1, 1, \
+ 1, 1, 1, 1, \
+ 1, 1, 1, 1, \
+ 1, 1, \
+ 1, 1, 1, 1, \
+ 1, 1, 1, 1, \
+ 1, 1, 1, 1, \
1, 1, 1, 1 }
#define CALL_REALLY_USED_REGISTERS \
-{ 1, 1, 1, 1, /* r0 - r15 */ \
- 1, 1, 0, 0, \
- 0, 0, 0, 0, \
+{ 1, 1, 1, 1, /* r0 - r15 */ \
+ 1, 1, 0, 0, \
+ 0, 0, 0, 0, \
0, 0, 0, 0, \
- 1, 1, 1, 1, /* f0 (16) - f15 (31) */ \
- 1, 1, 1, 1, \
- 1, 1, 1, 1, \
- 1, 1, 1, 1, \
+ 1, 1, 1, 1, /* f0 (16) - f15 (31) */ \
+ 1, 1, 1, 1, \
+ 1, 1, 1, 1, \
+ 1, 1, 1, 1, \
1, 1, 1, 1, /* arg, cc, fp, ret addr */ \
- 0, 0, /* a0 (36), a1 (37) */ \
- 1, 1, 1, 1, /* v16 (38) - v23 (45) */ \
+ 0, 0, /* a0 (36), a1 (37) */ \
+ 1, 1, 1, 1, /* v16 (38) - v23 (45) */ \
1, 1, 1, 1, \
- 1, 1, 1, 1, /* v24 (46) - v31 (53) */ \
+ 1, 1, 1, 1, /* v24 (46) - v31 (53) */ \
1, 1, 1, 1 }
/* Preferred register allocation order. */
@@ -464,7 +470,7 @@ extern const char *s390_host_detect_local_cpu (int argc, const char **argv);
{ 1, 2, 3, 4, 5, 0, 12, 11, 10, 9, 8, 7, 6, 14, 13, \
16, 17, 18, 19, 20, 21, 22, 23, \
24, 25, 26, 27, 28, 29, 30, 31, \
- 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, \
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, \
15, 32, 33, 34, 35, 36, 37 }
@@ -473,7 +479,7 @@ extern const char *s390_host_detect_local_cpu (int argc, const char **argv);
/* Maximum number of registers to represent a value of mode MODE
in a register of class CLASS. */
-#define CLASS_MAX_NREGS(CLASS, MODE) \
+#define CLASS_MAX_NREGS(CLASS, MODE) \
s390_class_max_nregs ((CLASS), (MODE))
/* We can reverse a CC mode safely if we know whether it comes from a
@@ -493,7 +499,7 @@ extern const char *s390_host_detect_local_cpu (int argc, const char **argv);
/* We use the following register classes:
GENERAL_REGS All general purpose registers
ADDR_REGS All general purpose registers except %r0
- (These registers can be used in address generation)
+ (These registers can be used in address generation)
FP_REGS All floating point registers
CC_REGS The condition code register
ACCESS_REGS The access registers
@@ -567,8 +573,8 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
/* Check whether REGNO is a hard register of the suitable class
or a pseudo register currently allocated to one such. */
#define REGNO_OK_FOR_INDEX_P(REGNO) \
- (((REGNO) < FIRST_PSEUDO_REGISTER \
- && REGNO_REG_CLASS ((REGNO)) == ADDR_REGS) \
+ (((REGNO) < FIRST_PSEUDO_REGISTER \
+ && REGNO_REG_CLASS ((REGNO)) == ADDR_REGS) \
|| ADDR_REGNO_P (reg_renumber[REGNO]))
#define REGNO_OK_FOR_BASE_P(REGNO) REGNO_OK_FOR_INDEX_P (REGNO)
@@ -739,7 +745,7 @@ CUMULATIVE_ARGS;
/* Profiling. */
-#define FUNCTION_PROFILER(FILE, LABELNO) \
+#define FUNCTION_PROFILER(FILE, LABELNO) \
s390_function_profiler ((FILE), ((LABELNO)))
#define PROFILE_BEFORE_PROLOGUE 1
@@ -1019,6 +1025,19 @@ do { \
extern const int processor_flags_table[];
+struct s390_processor
+{
+ /* The preferred name to be used in user visible output. */
+ const char *const name;
+ /* CPU name as it should be passed to Binutils via .machine */
+ const char *const binutils_name;
+ const enum processor_type processor;
+ const struct processor_costs *cost;
+ int arch_level;
+};
+
+extern const struct s390_processor processor_table[];
+
/* The truth element value for vector comparisons. Our instructions
always generate -1 in that case. */
#define VECTOR_STORE_FLAG_VALUE(MODE) CONSTM1_RTX (GET_MODE_INNER (MODE))
@@ -1096,9 +1115,6 @@ struct GTY(()) machine_function
/* Literal pool base register. */
rtx base_reg;
- /* True if we may need to perform branch splitting. */
- bool split_branches_pending_p;
-
bool has_landing_pad_p;
/* True if the current function may contain a tbegin clobbering
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index c4d391b..537ed35 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -75,7 +75,6 @@
; GOT/PLT and lt-relative accesses
UNSPEC_LTREL_OFFSET
- UNSPEC_LTREL_BASE
UNSPEC_POOL_OFFSET
UNSPEC_GOTENT
UNSPEC_GOT
@@ -405,6 +404,10 @@
; Bitposition of operand types
(PFPO_OP0_TYPE_SHIFT 16)
(PFPO_OP1_TYPE_SHIFT 8)
+ ; Decide whether current DFP or BFD rounding mode should be used
+ ; for the conversion.
+ (PFPO_RND_MODE_DFP 0)
+ (PFPO_RND_MODE_BFP 1)
])
; Immediate operands for tbegin and tbeginc
@@ -481,7 +484,7 @@
; mnemonics which only get defined through if_then_else currently
; don't get added to the list values automatically and hence need to
; be listed here.
-(define_attr "mnemonic" "b,bas,bc,bcr_flush,unknown" (const_string "unknown"))
+(define_attr "mnemonic" "b,bas,basr,bc,bcr_flush,unknown" (const_string "unknown"))
;; Length in bytes.
@@ -492,11 +495,9 @@
;; Processor type. This attribute must exactly match the processor_type
-;; enumeration in s390.h. The current machine description does not
-;; distinguish between g5 and g6, but there are differences between the two
-;; CPUs could in theory be modeled.
+;; enumeration in s390.h.
-(define_attr "cpu" "g5,g6,z900,z990,z9_109,z9_ec,z10,z196,zEC12,z13,arch12"
+(define_attr "cpu" "z900,z990,z9_109,z9_ec,z10,z196,zEC12,z13,arch12"
(const (symbol_ref "s390_tune_attr")))
(define_attr "cpu_facility"
@@ -527,8 +528,7 @@
(match_test "TARGET_DFP"))
(const_int 1)
- (and (eq_attr "cpu_facility" "cpu_zarch")
- (match_test "TARGET_CPU_ZARCH"))
+ (eq_attr "cpu_facility" "cpu_zarch")
(const_int 1)
(and (eq_attr "cpu_facility" "z10")
@@ -561,8 +561,7 @@
]
(const_int 0)))
-;; Pipeline description for z900. For lack of anything better,
-;; this description is also used for the g5 and g6.
+;; Pipeline description for z900.
(include "2064.md")
;; Pipeline description for z990, z9-109 and z9-ec.
@@ -1516,8 +1515,8 @@
; FIXME: More constants are possible by enabling jxx, jyy constraints
; for TImode (use double-int for the calculations)
(define_insn "movti"
- [(set (match_operand:TI 0 "nonimmediate_operand" "=d,S,v, v, v,v,d,v,R, d,o")
- (match_operand:TI 1 "general_operand" " S,d,v,j00,jm1,d,v,R,v,dT,d"))]
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=d,S,v, v, v,v,d,v,R,d, d, d, d, d,o")
+ (match_operand:TI 1 "general_operand" " S,d,v,j00,jm1,d,v,R,v,K,NxHD0,Os,NxSD0,dT,d"))]
"TARGET_ZARCH"
"@
lmg\t%0,%N0,%S1
@@ -1530,10 +1529,14 @@
vl\t%v0,%1
vst\t%v1,%0
#
+ #
+ #
+ #
+ #
#"
- [(set_attr "op_type" "RSY,RSY,VRR,VRI,VRI,VRR,*,VRX,VRX,*,*")
- (set_attr "type" "lm,stm,*,*,*,*,*,*,*,*,*")
- (set_attr "cpu_facility" "*,*,vx,vx,vx,vx,vx,vx,vx,*,*")])
+ [(set_attr "op_type" "RSY,RSY,VRR,VRI,VRI,VRR,*,VRX,VRX,*,*,*,*,*,*")
+ (set_attr "type" "lm,stm,*,*,*,*,*,*,*,*,*,*,*,*,*")
+ (set_attr "cpu_facility" "*,*,vx,vx,vx,vx,vx,vx,vx,*,*,*,extimm,*,*")])
(define_split
[(set (match_operand:TI 0 "nonimmediate_operand" "")
@@ -1987,7 +1990,7 @@
(define_insn "*movsi_larl"
[(set (match_operand:SI 0 "register_operand" "=d")
(match_operand:SI 1 "larl_operand" "X"))]
- "!TARGET_64BIT && TARGET_CPU_ZARCH
+ "!TARGET_64BIT
&& !FP_REG_P (operands[0])"
"larl\t%0,%1"
[(set_attr "op_type" "RIL")
@@ -3228,7 +3231,7 @@
(use (match_operand 2 "register_operand" ""))
(use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
(clobber (match_operand 3 "register_operand" ""))]
- "reload_completed && TARGET_CPU_ZARCH"
+ "reload_completed"
[(set (match_dup 3) (label_ref (match_dup 4)))
(parallel
[(unspec [(match_dup 2) (mem:BLK (match_dup 3))
@@ -3449,7 +3452,7 @@
(use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
(clobber (match_operand 2 "register_operand" ""))
(clobber (reg:CC CC_REGNUM))]
- "reload_completed && TARGET_CPU_ZARCH"
+ "reload_completed"
[(set (match_dup 2) (label_ref (match_dup 3)))
(parallel
[(unspec [(match_dup 1) (mem:BLK (match_dup 2))
@@ -3640,7 +3643,7 @@
(use (match_operand 2 "register_operand" ""))
(use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
(clobber (match_operand 3 "register_operand" ""))]
- "reload_completed && TARGET_CPU_ZARCH"
+ "reload_completed"
[(set (match_dup 3) (label_ref (match_dup 4)))
(parallel
[(unspec [(match_dup 2) (mem:BLK (match_dup 3))
@@ -5378,9 +5381,13 @@
{
HOST_WIDE_INT flags;
+ /* According to IEEE 754 2008 4.3 'Rounding-direction attributes' the
+ rounding mode of the target format needs to be used. */
+
flags = (PFPO_CONVERT |
PFPO_OP_TYPE_<DFP_ALL:MODE> << PFPO_OP0_TYPE_SHIFT |
- PFPO_OP_TYPE_<BFP:MODE> << PFPO_OP1_TYPE_SHIFT);
+ PFPO_OP_TYPE_<BFP:MODE> << PFPO_OP1_TYPE_SHIFT |
+ PFPO_RND_MODE_DFP);
operands[2] = GEN_INT (flags);
})
@@ -5400,9 +5407,13 @@
{
HOST_WIDE_INT flags;
+ /* According to IEEE 754 2008 4.3 'Rounding-direction attributes' the
+ rounding mode of the target format needs to be used. */
+
flags = (PFPO_CONVERT |
PFPO_OP_TYPE_<BFP:MODE> << PFPO_OP0_TYPE_SHIFT |
- PFPO_OP_TYPE_<DFP_ALL:MODE> << PFPO_OP1_TYPE_SHIFT);
+ PFPO_OP_TYPE_<DFP_ALL:MODE> << PFPO_OP1_TYPE_SHIFT |
+ PFPO_RND_MODE_BFP);
operands[2] = GEN_INT (flags);
})
@@ -5443,9 +5454,13 @@
{
HOST_WIDE_INT flags;
+ /* According to IEEE 754 2008 4.3 'Rounding-direction attributes' the
+ rounding mode of the target format needs to be used. */
+
flags = (PFPO_CONVERT |
PFPO_OP_TYPE_<DFP_ALL:MODE> << PFPO_OP0_TYPE_SHIFT |
- PFPO_OP_TYPE_<BFP:MODE> << PFPO_OP1_TYPE_SHIFT);
+ PFPO_OP_TYPE_<BFP:MODE> << PFPO_OP1_TYPE_SHIFT |
+ PFPO_RND_MODE_DFP);
operands[2] = GEN_INT (flags);
})
@@ -5465,9 +5480,13 @@
{
HOST_WIDE_INT flags;
+ /* According to IEEE 754 2008 4.3 'Rounding-direction attributes' the
+ rounding mode of the target format needs to be used. */
+
flags = (PFPO_CONVERT |
PFPO_OP_TYPE_<BFP:MODE> << PFPO_OP0_TYPE_SHIFT |
- PFPO_OP_TYPE_<DFP_ALL:MODE> << PFPO_OP1_TYPE_SHIFT);
+ PFPO_OP_TYPE_<DFP_ALL:MODE> << PFPO_OP1_TYPE_SHIFT |
+ PFPO_RND_MODE_BFP);
operands[2] = GEN_INT (flags);
})
@@ -5603,7 +5622,7 @@
(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
(match_operand:DI 2 "general_operand" "do") ) )
(clobber (reg:CC CC_REGNUM))]
- "!TARGET_ZARCH && TARGET_CPU_ZARCH"
+ "!TARGET_ZARCH"
"#"
"&& reload_completed"
[(parallel
@@ -5623,38 +5642,6 @@
operands[7] = operand_subword (operands[1], 1, 0, DImode);
operands[8] = operand_subword (operands[2], 1, 0, DImode);")
-(define_insn_and_split "*adddi3_31"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=&d")
- (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
- (match_operand:DI 2 "general_operand" "do") ) )
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_CPU_ZARCH"
- "#"
- "&& reload_completed"
- [(parallel
- [(set (match_dup 3) (plus:SI (match_dup 4) (match_dup 5)))
- (clobber (reg:CC CC_REGNUM))])
- (parallel
- [(set (reg:CCL1 CC_REGNUM)
- (compare:CCL1 (plus:SI (match_dup 7) (match_dup 8))
- (match_dup 7)))
- (set (match_dup 6) (plus:SI (match_dup 7) (match_dup 8)))])
- (set (pc)
- (if_then_else (ltu (reg:CCL1 CC_REGNUM) (const_int 0))
- (pc)
- (label_ref (match_dup 9))))
- (parallel
- [(set (match_dup 3) (plus:SI (match_dup 3) (const_int 1)))
- (clobber (reg:CC CC_REGNUM))])
- (match_dup 9)]
- "operands[3] = operand_subword (operands[0], 0, 0, DImode);
- operands[4] = operand_subword (operands[1], 0, 0, DImode);
- operands[5] = operand_subword (operands[2], 0, 0, DImode);
- operands[6] = operand_subword (operands[0], 1, 0, DImode);
- operands[7] = operand_subword (operands[1], 1, 0, DImode);
- operands[8] = operand_subword (operands[2], 1, 0, DImode);
- operands[9] = gen_label_rtx ();")
-
;
; addsi3 instruction pattern(s).
;
@@ -6105,7 +6092,7 @@
(minus:DI (match_operand:DI 1 "register_operand" "0")
(match_operand:DI 2 "general_operand" "do") ) )
(clobber (reg:CC CC_REGNUM))]
- "!TARGET_ZARCH && TARGET_CPU_ZARCH"
+ "!TARGET_ZARCH"
"#"
"&& reload_completed"
[(parallel
@@ -6124,38 +6111,6 @@
operands[7] = operand_subword (operands[1], 1, 0, DImode);
operands[8] = operand_subword (operands[2], 1, 0, DImode);")
-(define_insn_and_split "*subdi3_31"
- [(set (match_operand:DI 0 "register_operand" "=&d")
- (minus:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "general_operand" "do") ) )
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_CPU_ZARCH"
- "#"
- "&& reload_completed"
- [(parallel
- [(set (match_dup 3) (minus:SI (match_dup 4) (match_dup 5)))
- (clobber (reg:CC CC_REGNUM))])
- (parallel
- [(set (reg:CCL2 CC_REGNUM)
- (compare:CCL2 (minus:SI (match_dup 7) (match_dup 8))
- (match_dup 7)))
- (set (match_dup 6) (minus:SI (match_dup 7) (match_dup 8)))])
- (set (pc)
- (if_then_else (gtu (reg:CCL2 CC_REGNUM) (const_int 0))
- (pc)
- (label_ref (match_dup 9))))
- (parallel
- [(set (match_dup 3) (plus:SI (match_dup 3) (const_int -1)))
- (clobber (reg:CC CC_REGNUM))])
- (match_dup 9)]
- "operands[3] = operand_subword (operands[0], 0, 0, DImode);
- operands[4] = operand_subword (operands[1], 0, 0, DImode);
- operands[5] = operand_subword (operands[2], 0, 0, DImode);
- operands[6] = operand_subword (operands[0], 1, 0, DImode);
- operands[7] = operand_subword (operands[1], 1, 0, DImode);
- operands[8] = operand_subword (operands[2], 1, 0, DImode);
- operands[9] = gen_label_rtx ();")
-
;
; subsi3 instruction pattern(s).
;
@@ -6396,7 +6351,7 @@
(match_dup 1)))
(set (match_operand:GPR 0 "register_operand" "=d,d")
(plus:GPR (plus:GPR (match_dup 3) (match_dup 1)) (match_dup 2)))]
- "s390_match_ccmode (insn, CCL1mode) && TARGET_CPU_ZARCH"
+ "s390_match_ccmode (insn, CCL1mode)"
"@
alc<g>r\t%0,%2
alc<g>\t%0,%2"
@@ -6412,7 +6367,7 @@
(match_operand:GPR 2 "general_operand" "d,T"))
(match_dup 1)))
(clobber (match_scratch:GPR 0 "=d,d"))]
- "s390_match_ccmode (insn, CCL1mode) && TARGET_CPU_ZARCH"
+ "s390_match_ccmode (insn, CCL1mode)"
"@
alc<g>r\t%0,%2
alc<g>\t%0,%2"
@@ -6431,7 +6386,7 @@
(match_dup 2)))
(set (match_operand:GPR 0 "register_operand" "=d,d")
(plus:GPR (plus:GPR (match_dup 3) (match_dup 1)) (match_dup 2)))]
- "s390_match_ccmode (insn, CCL1mode) && TARGET_CPU_ZARCH"
+ "s390_match_ccmode (insn, CCL1mode)"
"@
alc<g>r\t%0,%2
alc<g>\t%0,%2"
@@ -6446,7 +6401,7 @@
(match_operand:GPR 2 "general_operand" "d,T"))
(match_dup 2)))
(clobber (match_scratch:GPR 0 "=d,d"))]
- "s390_match_ccmode (insn, CCL1mode) && TARGET_CPU_ZARCH"
+ "s390_match_ccmode (insn, CCL1mode)"
"@
alc<g>r\t%0,%2
alc<g>\t%0,%2"
@@ -6462,7 +6417,7 @@
(const_int 0)))
(set (match_operand:GPR 0 "register_operand" "=d,d")
(plus:GPR (plus:GPR (match_dup 3) (match_dup 1)) (match_dup 2)))]
- "s390_match_ccmode (insn, CCLmode) && TARGET_CPU_ZARCH"
+ "s390_match_ccmode (insn, CCLmode)"
"@
alc<g>r\t%0,%2
alc<g>\t%0,%2"
@@ -6475,7 +6430,7 @@
(match_operand:GPR 1 "nonimmediate_operand" "%0,0"))
(match_operand:GPR 2 "general_operand" "d,T")))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_CPU_ZARCH"
+ ""
"@
alc<g>r\t%0,%2
alc<g>\t%0,%2"
@@ -6491,7 +6446,7 @@
(const_int 0)))
(set (match_operand:GPR 0 "register_operand" "=d,d")
(minus:GPR (minus:GPR (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "s390_match_ccmode (insn, CCLmode) && TARGET_CPU_ZARCH"
+ "s390_match_ccmode (insn, CCLmode)"
"@
slb<g>r\t%0,%2
slb<g>\t%0,%2"
@@ -6505,7 +6460,7 @@
(match_operand:GPR 2 "general_operand" "d,T"))
(match_operand:GPR 3 "s390_slb_comparison" "")))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_CPU_ZARCH"
+ ""
"@
slb<g>r\t%0,%2
slb<g>\t%0,%2"
@@ -6517,7 +6472,7 @@
(match_operand 1 "comparison_operator" "")
(match_operand:GPR 2 "register_operand" "")
(match_operand:GPR 3 "const_int_operand" "")]
- "TARGET_CPU_ZARCH"
+ ""
"if (!s390_expand_addcc (GET_CODE (operands[1]),
XEXP (operands[1], 0), XEXP (operands[1], 1),
operands[0], operands[2],
@@ -6531,7 +6486,7 @@
[(set (match_operand:GPR 0 "register_operand" "=&d")
(match_operand:GPR 1 "s390_alc_comparison" ""))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_CPU_ZARCH"
+ ""
"#"
"&& reload_completed"
[(set (match_dup 0) (const_int 0))
@@ -6545,7 +6500,7 @@
[(set (match_operand:GPR 0 "register_operand" "=&d")
(match_operand:GPR 1 "s390_slb_comparison" ""))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_CPU_ZARCH"
+ ""
"#"
"&& reload_completed"
[(set (match_dup 0) (const_int 0))
@@ -6564,7 +6519,7 @@
(match_operator:SI 1 "s390_scond_operator"
[(match_operand:GPR 2 "register_operand" "")
(match_operand:GPR 3 "general_operand" "")]))]
- "TARGET_CPU_ZARCH"
+ ""
"if (!s390_expand_addcc (GET_CODE (operands[1]), operands[2], operands[3],
operands[0], const0_rtx, const1_rtx)) FAIL; DONE;")
@@ -6799,7 +6754,7 @@
(match_operand:<DWH> 1 "register_operand" "%0,0"))
(zero_extend:DW
(match_operand:<DWH> 2 "nonimmediate_operand" " d,T"))))]
- "TARGET_CPU_ZARCH"
+ ""
"@
ml<tg>r\t%0,%2
ml<tg>\t%0,%2"
@@ -7061,7 +7016,7 @@
(set (match_operand:SI 3 "general_operand" "")
(umod:SI (match_dup 1) (match_dup 2)))])
(clobber (match_dup 4))]
- "!TARGET_ZARCH && TARGET_CPU_ZARCH"
+ "!TARGET_ZARCH"
{
rtx div_equal, mod_equal, equal;
rtx_insn *insn;
@@ -7104,187 +7059,13 @@
(zero_extend:DI
(truncate:SI
(udiv:DI (match_dup 1) (zero_extend:DI (match_dup 2)))))))]
- "!TARGET_ZARCH && TARGET_CPU_ZARCH"
+ "!TARGET_ZARCH"
"@
dlr\t%0,%2
dl\t%0,%2"
[(set_attr "op_type" "RRE,RXY")
(set_attr "type" "idiv")])
-(define_expand "udivsi3"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (udiv:SI (match_operand:SI 1 "general_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (clobber (match_dup 3))]
- "!TARGET_ZARCH && !TARGET_CPU_ZARCH"
-{
- rtx udiv_equal, umod_equal, equal;
- rtx_insn *insn;
-
- udiv_equal = gen_rtx_UDIV (SImode, operands[1], operands[2]);
- umod_equal = gen_rtx_UMOD (SImode, operands[1], operands[2]);
- equal = gen_rtx_IOR (DImode,
- gen_rtx_ASHIFT (DImode,
- gen_rtx_ZERO_EXTEND (DImode, umod_equal),
- GEN_INT (32)),
- gen_rtx_ZERO_EXTEND (DImode, udiv_equal));
-
- operands[3] = gen_reg_rtx (DImode);
-
- if (CONSTANT_P (operands[2]))
- {
- if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
- {
- rtx_code_label *label1 = gen_label_rtx ();
-
- operands[1] = make_safe_from (operands[1], operands[0]);
- emit_move_insn (operands[0], const0_rtx);
- emit_cmp_and_jump_insns (operands[1], operands[2], LT, NULL_RTX,
- SImode, 1, label1);
- emit_move_insn (operands[0], const1_rtx);
- emit_label (label1);
- }
- else
- {
- operands[2] = force_reg (SImode, operands[2]);
- operands[2] = make_safe_from (operands[2], operands[0]);
-
- emit_insn (gen_zero_extendsidi2 (operands[3], operands[1]));
- insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3],
- operands[2]));
- set_unique_reg_note (insn, REG_EQUAL, equal);
-
- insn = emit_move_insn (operands[0],
- gen_lowpart (SImode, operands[3]));
- set_unique_reg_note (insn, REG_EQUAL, udiv_equal);
- }
- }
- else
- {
- rtx_code_label *label1 = gen_label_rtx ();
- rtx_code_label *label2 = gen_label_rtx ();
- rtx_code_label *label3 = gen_label_rtx ();
-
- operands[1] = force_reg (SImode, operands[1]);
- operands[1] = make_safe_from (operands[1], operands[0]);
- operands[2] = force_reg (SImode, operands[2]);
- operands[2] = make_safe_from (operands[2], operands[0]);
-
- emit_move_insn (operands[0], const0_rtx);
- emit_cmp_and_jump_insns (operands[2], operands[1], GT, NULL_RTX,
- SImode, 1, label3);
- emit_cmp_and_jump_insns (operands[2], const0_rtx, LT, NULL_RTX,
- SImode, 0, label2);
- emit_cmp_and_jump_insns (operands[2], const1_rtx, EQ, NULL_RTX,
- SImode, 0, label1);
- emit_insn (gen_zero_extendsidi2 (operands[3], operands[1]));
- insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3],
- operands[2]));
- set_unique_reg_note (insn, REG_EQUAL, equal);
-
- insn = emit_move_insn (operands[0],
- gen_lowpart (SImode, operands[3]));
- set_unique_reg_note (insn, REG_EQUAL, udiv_equal);
-
- emit_jump (label3);
- emit_label (label1);
- emit_move_insn (operands[0], operands[1]);
- emit_jump (label3);
- emit_label (label2);
- emit_move_insn (operands[0], const1_rtx);
- emit_label (label3);
- }
- emit_move_insn (operands[0], operands[0]);
- DONE;
-})
-
-(define_expand "umodsi3"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (umod:SI (match_operand:SI 1 "nonimmediate_operand" "")
- (match_operand:SI 2 "nonimmediate_operand" "")))
- (clobber (match_dup 3))]
- "!TARGET_ZARCH && !TARGET_CPU_ZARCH"
-{
- rtx udiv_equal, umod_equal, equal;
- rtx_insn *insn;
-
- udiv_equal = gen_rtx_UDIV (SImode, operands[1], operands[2]);
- umod_equal = gen_rtx_UMOD (SImode, operands[1], operands[2]);
- equal = gen_rtx_IOR (DImode,
- gen_rtx_ASHIFT (DImode,
- gen_rtx_ZERO_EXTEND (DImode, umod_equal),
- GEN_INT (32)),
- gen_rtx_ZERO_EXTEND (DImode, udiv_equal));
-
- operands[3] = gen_reg_rtx (DImode);
-
- if (CONSTANT_P (operands[2]))
- {
- if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) <= 0)
- {
- rtx_code_label *label1 = gen_label_rtx ();
-
- operands[1] = make_safe_from (operands[1], operands[0]);
- emit_move_insn (operands[0], operands[1]);
- emit_cmp_and_jump_insns (operands[0], operands[2], LT, NULL_RTX,
- SImode, 1, label1);
- emit_insn (gen_abssi2 (operands[0], operands[2]));
- emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
- emit_label (label1);
- }
- else
- {
- operands[2] = force_reg (SImode, operands[2]);
- operands[2] = make_safe_from (operands[2], operands[0]);
-
- emit_insn (gen_zero_extendsidi2 (operands[3], operands[1]));
- insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3],
- operands[2]));
- set_unique_reg_note (insn, REG_EQUAL, equal);
-
- insn = emit_move_insn (operands[0],
- gen_highpart (SImode, operands[3]));
- set_unique_reg_note (insn, REG_EQUAL, umod_equal);
- }
- }
- else
- {
- rtx_code_label *label1 = gen_label_rtx ();
- rtx_code_label *label2 = gen_label_rtx ();
- rtx_code_label *label3 = gen_label_rtx ();
-
- operands[1] = force_reg (SImode, operands[1]);
- operands[1] = make_safe_from (operands[1], operands[0]);
- operands[2] = force_reg (SImode, operands[2]);
- operands[2] = make_safe_from (operands[2], operands[0]);
-
- emit_move_insn(operands[0], operands[1]);
- emit_cmp_and_jump_insns (operands[2], operands[1], GT, NULL_RTX,
- SImode, 1, label3);
- emit_cmp_and_jump_insns (operands[2], const0_rtx, LT, NULL_RTX,
- SImode, 0, label2);
- emit_cmp_and_jump_insns (operands[2], const1_rtx, EQ, NULL_RTX,
- SImode, 0, label1);
- emit_insn (gen_zero_extendsidi2 (operands[3], operands[1]));
- insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3],
- operands[2]));
- set_unique_reg_note (insn, REG_EQUAL, equal);
-
- insn = emit_move_insn (operands[0],
- gen_highpart (SImode, operands[3]));
- set_unique_reg_note (insn, REG_EQUAL, umod_equal);
-
- emit_jump (label3);
- emit_label (label1);
- emit_move_insn (operands[0], const0_rtx);
- emit_jump (label3);
- emit_label (label2);
- emit_insn (gen_subsi3 (operands[0], operands[0], operands[2]));
- emit_label (label3);
- }
- DONE;
-})
-
;
; div(df|sf)3 instruction pattern(s).
;
@@ -8891,7 +8672,7 @@
[(set (match_operand:GPR 0 "register_operand" "")
(rotate:GPR (match_operand:GPR 1 "register_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
- "TARGET_CPU_ZARCH"
+ ""
"")
; rll, rllg
@@ -8899,7 +8680,7 @@
[(set (match_operand:GPR 0 "register_operand" "=d")
(rotate:GPR (match_operand:GPR 1 "register_operand" "d")
(match_operand:SI 2 "nonmemory_operand" "an")))]
- "TARGET_CPU_ZARCH"
+ ""
"rll<g>\t%0,%1,<addr_style_op_ops>"
[(set_attr "op_type" "RSE")
(set_attr "atype" "reg")
@@ -9045,7 +8826,7 @@
(match_operand 2 "const_int_operand" "")])
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_CPU_ZARCH"
+ ""
{
if (get_attr_length (insn) == 4)
return "j%C1\t%l0";
@@ -9058,27 +8839,6 @@
(if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
(const_int 4) (const_int 6)))])
-(define_insn "*cjump_31"
- [(set (pc)
- (if_then_else
- (match_operator 1 "s390_comparison" [(reg CC_REGNUM)
- (match_operand 2 "const_int_operand" "")])
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "!TARGET_CPU_ZARCH"
-{
- gcc_assert (get_attr_length (insn) == 4);
- return "j%C1\t%l0";
-}
- [(set_attr "op_type" "RI")
- (set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (not (match_test "flag_pic"))
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 6))
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 8))))])
-
(define_insn "*cjump_long"
[(set (pc)
(if_then_else
@@ -9142,7 +8902,7 @@
(match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
(pc)
(label_ref (match_operand 0 "" ""))))]
- "TARGET_CPU_ZARCH"
+ ""
{
if (get_attr_length (insn) == 4)
return "j%D1\t%l0";
@@ -9155,26 +8915,6 @@
(if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
(const_int 4) (const_int 6)))])
-(define_insn "*icjump_31"
- [(set (pc)
- (if_then_else
- (match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "!TARGET_CPU_ZARCH"
-{
- gcc_assert (get_attr_length (insn) == 4);
- return "j%D1\t%l0";
-}
- [(set_attr "op_type" "RI")
- (set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (not (match_test "flag_pic"))
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 6))
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 8))))])
-
(define_insn "*icjump_long"
[(set (pc)
(if_then_else
@@ -9310,7 +9050,7 @@
(set (match_operand:GPR 4 "nonimmediate_operand" "")
(plus:GPR (match_dup 1) (match_dup 2)))
(clobber (match_scratch:GPR 5 ""))]
- "TARGET_CPU_ZARCH"
+ ""
"#"
"!reload_completed && !reload_in_progress"
[(set (match_dup 7) (match_dup 2)) ; the increment
@@ -9436,7 +9176,7 @@
(subreg:SI (match_dup 2) 0)))
(clobber (match_scratch:SI 4 "=X,&1,&?d"))
(clobber (reg:CC CC_REGNUM))]
- "!TARGET_ZARCH && TARGET_CPU_ZARCH"
+ "!TARGET_ZARCH"
{
if (which_alternative != 0)
return "#";
@@ -9471,9 +9211,7 @@
(use (match_operand 1 "" ""))] ; label
""
{
- if (GET_MODE (operands[0]) == SImode && !TARGET_CPU_ZARCH)
- emit_jump_insn (gen_doloop_si31 (operands[1], operands[0], operands[0]));
- else if (GET_MODE (operands[0]) == SImode && TARGET_CPU_ZARCH)
+ if (GET_MODE (operands[0]) == SImode)
emit_jump_insn (gen_doloop_si64 (operands[1], operands[0], operands[0]));
else if (GET_MODE (operands[0]) == DImode && TARGET_ZARCH)
emit_jump_insn (gen_doloop_di (operands[1], operands[0], operands[0]));
@@ -9494,7 +9232,7 @@
(plus:SI (match_dup 1) (const_int -1)))
(clobber (match_scratch:SI 3 "=X,&1,&?d"))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_CPU_ZARCH"
+ ""
{
if (which_alternative != 0)
return "#";
@@ -9525,77 +9263,6 @@
(if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
(const_int 4) (const_int 10)))])
-(define_insn_and_split "doloop_si31"
- [(set (pc)
- (if_then_else
- (ne (match_operand:SI 1 "register_operand" "d,d,d")
- (const_int 1))
- (label_ref (match_operand 0 "" ""))
- (pc)))
- (set (match_operand:SI 2 "nonimmediate_operand" "=1,?X,?X")
- (plus:SI (match_dup 1) (const_int -1)))
- (clobber (match_scratch:SI 3 "=X,&1,&?d"))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_CPU_ZARCH"
-{
- if (which_alternative != 0)
- return "#";
- else if (get_attr_length (insn) == 4)
- return "brct\t%1,%l0";
- else
- gcc_unreachable ();
-}
- "&& reload_completed
- && (! REG_P (operands[2])
- || ! rtx_equal_p (operands[1], operands[2]))"
- [(set (match_dup 3) (match_dup 1))
- (parallel [(set (reg:CCAN CC_REGNUM)
- (compare:CCAN (plus:SI (match_dup 3) (const_int -1))
- (const_int 0)))
- (set (match_dup 3) (plus:SI (match_dup 3) (const_int -1)))])
- (set (match_dup 2) (match_dup 3))
- (set (pc) (if_then_else (ne (reg:CCAN CC_REGNUM) (const_int 0))
- (label_ref (match_dup 0))
- (pc)))]
- ""
- [(set_attr "op_type" "RI")
- ; Strictly speaking, the z10 properties are valid for brct only, however, it does not
- ; hurt us in the (rare) case of ahi.
- (set_attr "z10prop" "z10_super_E1")
- (set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (not (match_test "flag_pic"))
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 6))
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 8))))])
-
-(define_insn "*doloop_si_long"
- [(set (pc)
- (if_then_else
- (ne (match_operand:SI 1 "register_operand" "d")
- (const_int 1))
- (match_operand 0 "address_operand" "ZR")
- (pc)))
- (set (match_operand:SI 2 "register_operand" "=1")
- (plus:SI (match_dup 1) (const_int -1)))
- (clobber (match_scratch:SI 3 "=X"))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_CPU_ZARCH"
-{
- if (get_attr_op_type (insn) == OP_TYPE_RR)
- return "bctr\t%1,%0";
- else
- return "bct\t%1,%a0";
-}
- [(set (attr "op_type")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "RR") (const_string "RX")))
- (set_attr "type" "branch")
- (set_attr "atype" "agen")
- (set_attr "z10prop" "z10_c")
- (set_attr "z196prop" "z196_cracked")])
-
(define_insn_and_split "doloop_di"
[(set (pc)
(if_then_else
@@ -9653,7 +9320,7 @@
(define_insn "*jump64"
[(set (pc) (label_ref (match_operand 0 "" "")))]
- "TARGET_CPU_ZARCH"
+ ""
{
if (get_attr_length (insn) == 4)
return "j\t%l0";
@@ -9666,22 +9333,6 @@
(if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
(const_int 4) (const_int 6)))])
-(define_insn "*jump31"
- [(set (pc) (label_ref (match_operand 0 "" "")))]
- "!TARGET_CPU_ZARCH"
-{
- gcc_assert (get_attr_length (insn) == 4);
- return "j\t%l0";
-}
- [(set_attr "op_type" "RI")
- (set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (not (match_test "flag_pic"))
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 6))
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 8))))])
-
;
; indirect-jump instruction pattern(s).
;
@@ -10150,7 +9801,7 @@
(define_insn "*sibcall_brcl"
[(call (mem:QI (match_operand 0 "bras_sym_operand" "X"))
(match_operand 1 "const_int_operand" "n"))]
- "SIBLING_CALL_P (insn) && TARGET_CPU_ZARCH"
+ "SIBLING_CALL_P (insn)"
"jg\t%0"
[(set_attr "op_type" "RIL")
(set_attr "type" "branch")])
@@ -10212,7 +9863,7 @@
[(set (match_operand 0 "" "")
(call (mem:QI (match_operand 1 "bras_sym_operand" "X"))
(match_operand 2 "const_int_operand" "n")))]
- "SIBLING_CALL_P (insn) && TARGET_CPU_ZARCH"
+ "SIBLING_CALL_P (insn)"
"jg\t%1"
[(set_attr "op_type" "RIL")
(set_attr "type" "branch")])
@@ -10250,7 +9901,7 @@
(match_operand 1 "const_int_operand" "n"))
(clobber (match_operand 2 "register_operand" "=r"))]
"!SIBLING_CALL_P (insn)
- && TARGET_CPU_ZARCH
+
&& GET_MODE (operands[2]) == Pmode"
"brasl\t%2,%0"
[(set_attr "op_type" "RIL")
@@ -10356,7 +10007,7 @@
(match_operand 2 "const_int_operand" "n")))
(clobber (match_operand 3 "register_operand" "=r"))]
"!SIBLING_CALL_P (insn)
- && TARGET_CPU_ZARCH
+
&& GET_MODE (operands[3]) == Pmode"
"brasl\t%3,%1"
[(set_attr "op_type" "RIL")
@@ -10499,7 +10150,7 @@
(clobber (match_operand 3 "register_operand" "=r"))
(use (match_operand 4 "" ""))]
"!SIBLING_CALL_P (insn)
- && TARGET_CPU_ZARCH
+
&& GET_MODE (operands[3]) == Pmode"
"brasl\t%3,%1%J4"
[(set_attr "op_type" "RIL")
@@ -10707,7 +10358,7 @@
; cdsg, csg
(define_insn "*atomic_compare_and_swap<mode>_1"
[(set (match_operand:TDI 0 "register_operand" "=r")
- (match_operand:TDI 1 "memory_operand" "+S"))
+ (match_operand:TDI 1 "nonsym_memory_operand" "+S"))
(set (match_dup 1)
(unspec_volatile:TDI
[(match_dup 1)
@@ -10725,7 +10376,7 @@
; cds, cdsy
(define_insn "*atomic_compare_and_swapdi_2"
[(set (match_operand:DI 0 "register_operand" "=r,r")
- (match_operand:DI 1 "memory_operand" "+Q,S"))
+ (match_operand:DI 1 "nonsym_memory_operand" "+Q,S"))
(set (match_dup 1)
(unspec_volatile:DI
[(match_dup 1)
@@ -10746,7 +10397,7 @@
; cs, csy
(define_insn "*atomic_compare_and_swapsi_3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
- (match_operand:SI 1 "memory_operand" "+Q,S"))
+ (match_operand:SI 1 "nonsym_memory_operand" "+Q,S"))
(set (match_dup 1)
(unspec_volatile:SI
[(match_dup 1)
@@ -11037,7 +10688,7 @@
(define_insn "nop_6_byte"
[(unspec_volatile [(const_int 0)] UNSPECV_NOP_6_BYTE)]
- "TARGET_CPU_ZARCH"
+ ""
"brcl\t0, 0"
[(set_attr "op_type" "RIL")])
@@ -11085,28 +10736,10 @@
}
[(set_attr "length" "0")])
-(define_insn "main_base_31_small"
- [(set (match_operand 0 "register_operand" "=a")
- (unspec [(label_ref (match_operand 1 "" ""))] UNSPEC_MAIN_BASE))]
- "!TARGET_CPU_ZARCH && GET_MODE (operands[0]) == Pmode"
- "basr\t%0,0"
- [(set_attr "op_type" "RR")
- (set_attr "type" "la")
- (set_attr "z196prop" "z196_cracked")])
-
-(define_insn "main_base_31_large"
- [(set (match_operand 0 "register_operand" "=a")
- (unspec [(label_ref (match_operand 1 "" ""))] UNSPEC_MAIN_BASE))
- (set (pc) (label_ref (match_operand 2 "" "")))]
- "!TARGET_CPU_ZARCH && GET_MODE (operands[0]) == Pmode"
- "bras\t%0,%2"
- [(set_attr "op_type" "RI")
- (set_attr "z196prop" "z196_cracked")])
-
(define_insn "main_base_64"
[(set (match_operand 0 "register_operand" "=a")
(unspec [(label_ref (match_operand 1 "" ""))] UNSPEC_MAIN_BASE))]
- "TARGET_CPU_ZARCH && GET_MODE (operands[0]) == Pmode"
+ "GET_MODE (operands[0]) == Pmode"
"larl\t%0,%1"
[(set_attr "op_type" "RIL")
(set_attr "type" "larl")
@@ -11120,22 +10753,12 @@
gcc_unreachable ();
}
[(set (attr "type")
- (if_then_else (match_test "TARGET_CPU_ZARCH")
- (const_string "larl") (const_string "la")))])
-
-(define_insn "reload_base_31"
- [(set (match_operand 0 "register_operand" "=a")
- (unspec [(label_ref (match_operand 1 "" ""))] UNSPEC_RELOAD_BASE))]
- "!TARGET_CPU_ZARCH && GET_MODE (operands[0]) == Pmode"
- "basr\t%0,0\;la\t%0,%1-.(%0)"
- [(set_attr "length" "6")
- (set_attr "type" "la")
- (set_attr "z196prop" "z196_cracked")])
+ (const_string "larl"))])
(define_insn "reload_base_64"
[(set (match_operand 0 "register_operand" "=a")
(unspec [(label_ref (match_operand 1 "" ""))] UNSPEC_RELOAD_BASE))]
- "TARGET_CPU_ZARCH && GET_MODE (operands[0]) == Pmode"
+ "GET_MODE (operands[0]) == Pmode"
"larl\t%0,%1"
[(set_attr "op_type" "RIL")
(set_attr "type" "larl")
@@ -11419,7 +11042,7 @@
(define_insn "bswap<mode>2"
[(set (match_operand:GPR 0 "nonimmediate_operand" "=d,d,T")
(bswap:GPR (match_operand:GPR 1 "nonimmediate_operand" " d,T,d")))]
- "TARGET_CPU_ZARCH"
+ ""
"@
lrv<g>r\t%0,%1
lrv<g>\t%0,%1
@@ -11431,7 +11054,7 @@
(define_insn "bswaphi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,T")
(bswap:HI (match_operand:HI 1 "nonimmediate_operand" " d,T,d")))]
- "TARGET_CPU_ZARCH"
+ ""
"@
#
lrvh\t%0,%1
@@ -11443,7 +11066,7 @@
(define_split
[(set (match_operand:HI 0 "register_operand" "")
(bswap:HI (match_operand:HI 1 "register_operand" "")))]
- "TARGET_CPU_ZARCH"
+ ""
[(set (match_dup 2) (bswap:SI (match_dup 3)))
(set (match_dup 2) (lshiftrt:SI (match_dup 2) (const_int 16)))]
{
@@ -11881,7 +11504,7 @@
(match_operand 2 "const_int_operand" "X")
(match_operand 3 "const_int_operand" "X")]
UNSPECV_SPLIT_STACK_DATA)]
- "TARGET_CPU_ZARCH"
+ ""
{
switch_to_section (targetm.asm_out.function_rodata_section
(current_function_decl));
@@ -11916,7 +11539,7 @@
(define_expand "split_stack_call"
[(match_operand 0 "bras_sym_operand" "X")
(match_operand 1 "" "")]
- "TARGET_CPU_ZARCH"
+ ""
{
if (TARGET_64BIT)
emit_jump_insn (gen_split_stack_call_di (operands[0], operands[1]));
@@ -11930,7 +11553,7 @@
(set (reg:P 1) (unspec_volatile [(match_operand 0 "bras_sym_operand" "X")
(reg:P 1)]
UNSPECV_SPLIT_STACK_CALL))]
- "TARGET_CPU_ZARCH"
+ ""
"jg\t%0"
[(set_attr "op_type" "RIL")
(set_attr "type" "branch")])
@@ -11941,7 +11564,7 @@
[(match_operand 0 "bras_sym_operand" "X")
(match_operand 1 "" "")
(match_operand 2 "" "")]
- "TARGET_CPU_ZARCH"
+ ""
{
if (TARGET_64BIT)
emit_jump_insn (gen_split_stack_cond_call_di (operands[0], operands[1], operands[2]));
@@ -11959,7 +11582,7 @@
(set (reg:P 1) (unspec_volatile [(match_operand 0 "bras_sym_operand" "X")
(reg:P 1)]
UNSPECV_SPLIT_STACK_CALL))]
- "TARGET_CPU_ZARCH"
+ ""
"jg%C1\t%0"
[(set_attr "op_type" "RIL")
(set_attr "type" "branch")])
diff --git a/gcc/config/s390/s390.opt b/gcc/config/s390/s390.opt
index 4214b17..c56eceb 100644
--- a/gcc/config/s390/s390.opt
+++ b/gcc/config/s390/s390.opt
@@ -59,15 +59,6 @@ Enum
Name(processor_type) Type(enum processor_type)
EnumValue
-Enum(processor_type) String(g5) Value(PROCESSOR_9672_G5)
-
-EnumValue
-Enum(processor_type) String(arch3) Value(PROCESSOR_9672_G5)
-
-EnumValue
-Enum(processor_type) String(g6) Value(PROCESSOR_9672_G6)
-
-EnumValue
Enum(processor_type) String(z900) Value(PROCESSOR_2064_Z900)
EnumValue
diff --git a/gcc/config/s390/t-s390 b/gcc/config/s390/t-s390
index cdea373..8ca0c78 100644
--- a/gcc/config/s390/t-s390
+++ b/gcc/config/s390/t-s390
@@ -18,6 +18,7 @@
TM_H += $(srcdir)/config/s390/s390-builtins.def
TM_H += $(srcdir)/config/s390/s390-builtin-types.def
+PASSES_EXTRA += $(srcdir)/config/s390/s390-passes.def
s390-c.o: $(srcdir)/config/s390/s390-c.c \
$(srcdir)/config/s390/s390-protos.h $(CONFIG_H) $(SYSTEM_H) coretypes.h \
diff --git a/gcc/config/s390/tpf.h b/gcc/config/s390/tpf.h
index 5871a6b..9e91244 100644
--- a/gcc/config/s390/tpf.h
+++ b/gcc/config/s390/tpf.h
@@ -1,8 +1,8 @@
/* Definitions for target OS TPF for GNU compiler, for IBM S/390 hardware
Copyright (C) 2003-2018 Free Software Foundation, Inc.
Contributed by P.J. Darcy (darcypj@us.ibm.com),
- Hartmut Penner (hpenner@de.ibm.com), and
- Ulrich Weigand (uweigand@de.ibm.com).
+ Hartmut Penner (hpenner@de.ibm.com), and
+ Ulrich Weigand (uweigand@de.ibm.com).
This file is part of GCC.
@@ -44,7 +44,7 @@ along with GCC; see the file COPYING3. If not see
/* TPF OS specific stack-pointer offset. */
#undef STACK_POINTER_OFFSET
-#define STACK_POINTER_OFFSET 448
+#define STACK_POINTER_OFFSET 448
/* When building for TPF, set a generic default target that is 64 bits. Also
enable TPF profiling support and the standard backchain by default. */
@@ -94,7 +94,6 @@ along with GCC; see the file COPYING3. If not see
#undef ASM_SPEC
#define ASM_SPEC \
"%{m31&m64}%{mesa&mzarch}%{march=z*}" \
- "%{march=arch3:-march=g5}" \
"%{march=arch5:-march=z900}" \
"%{march=arch6:-march=z990}" \
"%{march=arch7:-march=z9-ec}" \
@@ -106,10 +105,10 @@ along with GCC; see the file COPYING3. If not see
#undef LIB_SPEC
#define LIB_SPEC "-lCTIS -lCISO -lCLBM -lCTAL -lCFVS -lCTBX -lCTXO \
- -lCJ00 -lCTDF -lCOMX -lCOMS -lCTHD -lCTAD -lTPFSTUB"
+ -lCJ00 -lCTDF -lCOMX -lCOMS -lCTHD -lCTAD -lTPFSTUB"
#define ENTRY_SPEC "%{mmain:-entry=_start} \
- %{!mmain:-entry=0}"
+ %{!mmain:-entry=0}"
/* All linking is done shared on TPF-OS. */
/* FIXME: When binutils patch for new emulation is committed
diff --git a/gcc/config/spu/spu-c.c b/gcc/config/spu/spu-c.c
index a148c5c..166f91d 100644
--- a/gcc/config/spu/spu-c.c
+++ b/gcc/config/spu/spu-c.c
@@ -64,7 +64,7 @@ spu_macro_to_expand (cpp_reader *pfile, const cpp_token *tok)
if (ident)
{
enum rid rid_code = (enum rid)(ident->rid_code);
- if (ident->type == NT_MACRO)
+ if (cpp_macro_p (ident))
{
(void) cpp_get_token (pfile);
tok = cpp_peek_token (pfile, 0);
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index e2f45dd..45dd2dc 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -7463,6 +7463,9 @@ static const struct attribute_spec spu_attribute_table[] =
#undef TARGET_CONSTANT_ALIGNMENT
#define TARGET_CONSTANT_ALIGNMENT spu_constant_alignment
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-spu.h"
diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c
index 25f7ce0..6fbbbe2 100644
--- a/gcc/config/stormy16/stormy16.c
+++ b/gcc/config/stormy16/stormy16.c
@@ -2728,6 +2728,9 @@ xstormy16_push_rounding (poly_int64 bytes)
#undef TARGET_CONSTANT_ALIGNMENT
#define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-stormy16.h"
diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c
index 8936c73..75b1ec0 100644
--- a/gcc/config/v850/v850.c
+++ b/gcc/config/v850/v850.c
@@ -3327,6 +3327,9 @@ v850_modes_tieable_p (machine_mode mode1, machine_mode mode2)
#undef TARGET_FLAGS_REGNUM
#define TARGET_FLAGS_REGNUM 32
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-v850.h"
diff --git a/gcc/config/visium/visium.c b/gcc/config/visium/visium.c
index 2b402d1..d8ea128 100644
--- a/gcc/config/visium/visium.c
+++ b/gcc/config/visium/visium.c
@@ -280,17 +280,19 @@ static HOST_WIDE_INT visium_constant_alignment (const_tree, HOST_WIDE_INT);
#undef TARGET_LEGITIMATE_CONSTANT_P
#define TARGET_LEGITIMATE_CONSTANT_P visium_legitimate_constant_p
-#undef TARGET_LRA_P
+#undef TARGET_LRA_P
#define TARGET_LRA_P hook_bool_void_false
#undef TARGET_LEGITIMATE_ADDRESS_P
#define TARGET_LEGITIMATE_ADDRESS_P visium_legitimate_address_p
-#undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
+#undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
#define TARGET_PRINT_OPERAND_PUNCT_VALID_P visium_print_operand_punct_valid_p
-#undef TARGET_PRINT_OPERAND
+
+#undef TARGET_PRINT_OPERAND
#define TARGET_PRINT_OPERAND visium_print_operand
-#undef TARGET_PRINT_OPERAND_ADDRESS
+
+#undef TARGET_PRINT_OPERAND_ADDRESS
#define TARGET_PRINT_OPERAND_ADDRESS visium_print_operand_address
#undef TARGET_ATTRIBUTE_TABLE
@@ -347,27 +349,30 @@ static HOST_WIDE_INT visium_constant_alignment (const_tree, HOST_WIDE_INT);
#undef TARGET_TRAMPOLINE_INIT
#define TARGET_TRAMPOLINE_INIT visium_trampoline_init
-#undef TARGET_MD_ASM_ADJUST
+#undef TARGET_MD_ASM_ADJUST
#define TARGET_MD_ASM_ADJUST visium_md_asm_adjust
-#undef TARGET_FLAGS_REGNUM
+#undef TARGET_FLAGS_REGNUM
#define TARGET_FLAGS_REGNUM FLAGS_REGNUM
-#undef TARGET_HARD_REGNO_NREGS
+#undef TARGET_HARD_REGNO_NREGS
#define TARGET_HARD_REGNO_NREGS visium_hard_regno_nregs
-#undef TARGET_HARD_REGNO_MODE_OK
+#undef TARGET_HARD_REGNO_MODE_OK
#define TARGET_HARD_REGNO_MODE_OK visium_hard_regno_mode_ok
-#undef TARGET_MODES_TIEABLE_P
+#undef TARGET_MODES_TIEABLE_P
#define TARGET_MODES_TIEABLE_P visium_modes_tieable_p
-#undef TARGET_CAN_CHANGE_MODE_CLASS
+#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS visium_can_change_mode_class
-#undef TARGET_CONSTANT_ALIGNMENT
+#undef TARGET_CONSTANT_ALIGNMENT
#define TARGET_CONSTANT_ALIGNMENT visium_constant_alignment
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
struct gcc_target targetm = TARGET_INITIALIZER;
namespace {
diff --git a/gcc/config/vxworks-dummy.h b/gcc/config/vxworks-dummy.h
index 33ed0c7..fb5edee 100644
--- a/gcc/config/vxworks-dummy.h
+++ b/gcc/config/vxworks-dummy.h
@@ -22,11 +22,19 @@ 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/>. */
-/* True if we're targeting VxWorks. */
+/* True if we're targeting VxWorks, VxWorks7 and/or 64bit. */
#ifndef TARGET_VXWORKS
#define TARGET_VXWORKS 0
#endif
+#ifndef TARGET_VXWORKS7
+#define TARGET_VXWORKS7 0
+#endif
+
+#ifndef TARGET_VXWORKS64
+#define TARGET_VXWORKS64 0
+#endif
+
/* True if generating code for a VxWorks RTP. */
#ifndef TARGET_VXWORKS_RTP
#define TARGET_VXWORKS_RTP false
diff --git a/gcc/config/vxworks.c b/gcc/config/vxworks.c
index 061f020..3b6b234 100644
--- a/gcc/config/vxworks.c
+++ b/gcc/config/vxworks.c
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see
#include "output.h"
#include "fold-const.h"
+#if !HAVE_INITFINI_ARRAY_SUPPORT
/* Like default_named_section_asm_out_constructor, except that even
constructors with DEFAULT_INIT_PRIORITY must go in a numbered
section on VxWorks. The VxWorks runtime uses a clever trick to get
@@ -56,6 +57,7 @@ vxworks_asm_out_destructor (rtx symbol, int priority)
/*constructor_p=*/false);
assemble_addr_to_section (symbol, sec);
}
+#endif
/* Return the list of FIELD_DECLs that make up an emulated TLS
variable's control object. TYPE is the structure these are fields
@@ -143,8 +145,11 @@ vxworks_override_options (void)
targetm.emutls.debug_form_tls_address = true;
}
- /* We can use .ctors/.dtors sections only in RTP mode. */
- targetm.have_ctors_dtors = TARGET_VXWORKS_RTP;
+ /* We can use .ctors/.dtors sections only in RTP mode. But, if the
+ compiler was built with --enable-initfini-array, assume the
+ toolchain implements the proper glue to make .init_array and
+ .fini_array work. */
+ targetm.have_ctors_dtors = TARGET_VXWORKS_RTP || HAVE_INITFINI_ARRAY_SUPPORT;
/* PIC is only supported for RTPs. */
if (flag_pic && !TARGET_VXWORKS_RTP)
diff --git a/gcc/config/vxworks.h b/gcc/config/vxworks.h
index e37af77..3ed706e 100644
--- a/gcc/config/vxworks.h
+++ b/gcc/config/vxworks.h
@@ -23,11 +23,6 @@ along with GCC; see the file COPYING3. If not see
#undef TARGET_VXWORKS
#define TARGET_VXWORKS 1
-/* If TARGET_VXWORKS7 is undefined, then we're not targeting it. */
-#ifndef TARGET_VXWORKS7
-#define TARGET_VXWORKS7 0
-#endif
-
/* In kernel mode, VxWorks provides all the libraries itself, as well as
the functionality of startup files, etc. In RTP mode, it behaves more
like a traditional Unix, with more external files. Most of our specs
@@ -61,34 +56,42 @@ along with GCC; see the file COPYING3. If not see
#undef VXWORKS_ADDITIONAL_CPP_SPEC
#define VXWORKS_ADDITIONAL_CPP_SPEC \
"%{!nostdinc: \
- %{isystem*} -idirafter \
- %{mrtp: %:getenv(WIND_USR /h) \
- ;: %:getenv(WIND_BASE /target/h)}}"
+ %{isystem*} \
+ %{mrtp: -idirafter %:getenv(WIND_USR /h) \
+ -idirafter %:getenv(WIND_USR /h/wrn/coreip) \
+ ;: -idirafter %:getenv(WIND_BASE /target/h) \
+ -idirafter %:getenv(WIND_BASE /target/h/wrn/coreip) \
+}}"
#endif
-/* The references to __init and __fini will be satisfied by
- libc_internal.a, and some versions of VxWorks rely on explicit
- extra libraries for system calls. */
+/* For VxWorks static rtps, the system provides libc_internal.a, a superset of
+ libgcc.a that we need to use e.g. to satisfy references to __init and
+ __fini. We still want our libgcc to prevail for symbols it would provide
+ (e.g. register save entry points), so re-place it here between libraries
+ that might reference it and libc_internal. Also, some versions of VxWorks
+ rely on explicit extra libraries for system calls. */
#define VXWORKS_SYSCALL_LIBS_RTP
#define VXWORKS_LIBS_RTP \
- VXWORKS_SYSCALL_LIBS_RTP " -lc -lgcc -lc_internal -lnet -ldsi"
+ VXWORKS_SYSCALL_LIBS_RTP " -lnet -ldsi -lc -lgcc -lc_internal"
/* On Vx6 and previous, the libraries to pick up depends on the architecture,
so cannot be defined for all archs at once. On Vx7, a VSB is always needed
and its structure is fixed and does not depend on the arch. We can thus
- tell gcc where to look for when linking with RTP libraries. */
+ tell gcc where to look for when linking with RTP libraries. Use
+ STARTFILE_PREFIX_SPEC for this, instead of explicit -L options in LIB_SPEC,
+ so they survive -nodefaultlibs. */
/* On Vx7 RTP, we need to drag the __tls__ symbol to trigger initialization of
tlsLib, responsible for TLS support by the OS. */
#if TARGET_VXWORKS7
-#define VXWORKS_LIBS_DIR_RTP "-L%:getenv(VSB_DIR /usr/lib/common)"
+#undef STARTFILE_PREFIX_SPEC
+#define STARTFILE_PREFIX_SPEC "%:getenv(VSB_DIR /usr/lib/common)"
#define TLS_SYM "-u __tls__"
#else
-#define VXWORKS_LIBS_DIR_RTP ""
#define TLS_SYM ""
#endif
@@ -97,8 +100,7 @@ along with GCC; see the file COPYING3. If not see
"%{mrtp:%{shared:-u " USER_LABEL_PREFIX "__init -u " USER_LABEL_PREFIX "__fini} \
%{!shared:%{non-static:-u " USER_LABEL_PREFIX "_STI__6__rtld -ldl} \
" TLS_SYM " \
- --start-group " VXWORKS_LIBS_RTP " --end-group} \
- " VXWORKS_LIBS_DIR_RTP "}"
+ --start-group " VXWORKS_LIBS_RTP " --end-group}}"
/* The no-op spec for "-shared" below is present because otherwise GCC
will treat it as an unrecognized option. */
@@ -119,13 +121,8 @@ along with GCC; see the file COPYING3. If not see
%{mrtp:%{!shared:%{!non-static:-static} \
%{non-static:--force-dynamic --export-dynamic}}}"
-/* For VxWorks static rtps, the system provides libc_internal.a, a superset
- of libgcc.a that we want to use. Make sure not to dynamically export any
- of its symbols, though, and always look for libgcc.a first so that we get
- the latest versions of the GNU intrinsics during our builds. */
#undef VXWORKS_LIBGCC_SPEC
-#define VXWORKS_LIBGCC_SPEC \
- "-lgcc %{mrtp:%{!shared:--exclude-libs=libc_internal,libgcc -lc_internal}}"
+#define VXWORKS_LIBGCC_SPEC "-lgcc"
#undef VXWORKS_STARTFILE_SPEC
#define VXWORKS_STARTFILE_SPEC "%{mrtp:%{!shared:-l:crt0.o}}"
@@ -139,10 +136,15 @@ along with GCC; see the file COPYING3. If not see
#define VXWORKS_OVERRIDE_OPTIONS vxworks_override_options ()
extern void vxworks_override_options (void);
-/* Only RTPs support prioritized constructors and destructors:
- the implementation relies on numbered .ctors* sections. */
-#define SUPPORTS_INIT_PRIORITY TARGET_VXWORKS_RTP
+/* RTPs support prioritized constructors and destructors: the
+ implementation relies on numbered .ctors* sections. If the compiler
+ was built with --enable-initfini-array, we assume the user uses a
+ linker script that sorts and merges the .init_array.* sections
+ appropriately. */
+#define SUPPORTS_INIT_PRIORITY \
+ (TARGET_VXWORKS_RTP || HAVE_INITFINI_ARRAY_SUPPORT)
+#if !HAVE_INITFINI_ARRAY_SUPPORT
/* VxWorks requires special handling of constructors and destructors.
All VxWorks configurations must use these functions. */
#undef TARGET_ASM_CONSTRUCTOR
@@ -151,6 +153,7 @@ extern void vxworks_override_options (void);
#define TARGET_ASM_DESTRUCTOR vxworks_asm_out_destructor
extern void vxworks_asm_out_constructor (rtx symbol, int priority);
extern void vxworks_asm_out_destructor (rtx symbol, int priority);
+#endif
/* Override the vxworks-dummy.h definitions. TARGET_VXWORKS_RTP
is defined by vxworks.opt. */
@@ -160,10 +163,10 @@ extern void vxworks_asm_out_destructor (rtx symbol, int priority);
#define VXWORKS_GOTT_INDEX "__GOTT_INDEX__"
#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "int"
+#define PTRDIFF_TYPE (TARGET_VXWORKS64 ? "long int" : "int")
#undef SIZE_TYPE
-#define SIZE_TYPE "unsigned int"
+#define SIZE_TYPE (TARGET_VXWORKS64 ? "long unsigned int" : "unsigned int")
#undef TARGET_LIBC_HAS_FUNCTION
#define TARGET_LIBC_HAS_FUNCTION no_c99_libc_has_function
@@ -203,6 +206,10 @@ extern void vxworks_asm_out_destructor (rtx symbol, int priority);
/* The diab linker does not handle .gnu_attribute sections. */
#undef HAVE_AS_GNU_ATTRIBUTE
+/* We provide our own version of __clear_cache in libgcc, using a separate C
+ file to facilitate #inclusion of VxWorks header files. */
+#define CLEAR_INSN_CACHE 1
+
/* Default dwarf control values, for non-gdb debuggers that come with
VxWorks. */
diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
index 7cfe64d..080bb4a 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -1614,9 +1614,9 @@ xtensa_expand_atomic (enum rtx_code code, rtx target, rtx mem, rtx val,
break;
case MULT: /* NAND */
- tmp = expand_simple_binop (SImode, XOR, old, ac.modemask,
+ tmp = expand_simple_binop (SImode, AND, old, val,
NULL_RTX, 1, OPTAB_DIRECT);
- tmp = expand_simple_binop (SImode, AND, tmp, val,
+ tmp = expand_simple_binop (SImode, XOR, tmp, ac.modemask,
new_rtx, 1, OPTAB_DIRECT);
break;
diff --git a/gcc/configure b/gcc/configure
index 80ac4a3..b3205ad 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -11836,7 +11836,10 @@ xm_file="auto-host.h ansidecl.h ${xm_file}"
if test -f configargs.h ; then
# Being re-configured.
gcc_config_arguments=`grep configuration_arguments configargs.h | sed -e 's/.*"\([^"]*\)".*/\1/'`
- gcc_config_arguments="$gcc_config_arguments : (reconfigured) $TOPLEVEL_CONFIGURE_ARGUMENTS"
+ gcc_reconf_arguments=`echo "$gcc_config_arguments" | sed -e 's/^.*\( : (reconfigured) .*$\)/\1/'`
+ if [ "$gcc_reconf_arguments" != " : (reconfigured) $TOPLEVEL_CONFIGURE_ARGUMENTS" ]; then
+ gcc_config_arguments="$gcc_config_arguments : (reconfigured) $TOPLEVEL_CONFIGURE_ARGUMENTS"
+ fi
else
gcc_config_arguments="$TOPLEVEL_CONFIGURE_ARGUMENTS"
fi
@@ -18460,7 +18463,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 18463 "configure"
+#line 18466 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -18566,7 +18569,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 18569 "configure"
+#line 18572 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -19731,20 +19734,20 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
prelink_cmds_CXX='tpldir=Template.dir~
rm -rf $tpldir~
$CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
- compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"'
+ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
old_archive_cmds_CXX='tpldir=Template.dir~
rm -rf $tpldir~
$CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
- $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~
+ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
$RANLIB $oldlib'
archive_cmds_CXX='tpldir=Template.dir~
rm -rf $tpldir~
$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
- $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
archive_expsym_cmds_CXX='tpldir=Template.dir~
rm -rf $tpldir~
$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
- $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
;;
*) # Version 6 and above use weak symbols
archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
@@ -23939,6 +23942,44 @@ _ACEOF
;;
esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for line table is_stmt support" >&5
+$as_echo_n "checking assembler for line table is_stmt support... " >&6; }
+if test "${gcc_cv_as_is_stmt+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_is_stmt=no
+ if test $in_tree_gas = yes; then
+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 16 \) \* 1000 + 92`
+ then gcc_cv_as_is_stmt=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ $as_echo ' .text
+ .file 1 "conf.c"
+ .loc 1 1 0 is_stmt 1' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ gcc_cv_as_is_stmt=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_is_stmt" >&5
+$as_echo "$gcc_cv_as_is_stmt" >&6; }
+if test $gcc_cv_as_is_stmt = yes; then
+
+$as_echo "#define HAVE_GAS_LOC_STMT 1" >>confdefs.h
+
+fi
+
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for line table discriminator support" >&5
$as_echo_n "checking assembler for line table discriminator support... " >&6; }
if test "${gcc_cv_as_discriminator+set}" = set; then :
@@ -27838,7 +27879,7 @@ esac
# ??? Once 2.11 is released, probably need to add first known working
# version to the per-target configury.
case "$cpu_type" in
- aarch64 | alpha | arc | arm | avr | bfin | cris | i386 | m32c | m68k \
+ aarch64 | alpha | arc | arm | avr | bfin | cris | csky | i386 | m32c | m68k \
| microblaze | mips | nios2 | pa | riscv | rs6000 | score | sparc | spu \
| tilegx | tilepro | visium | xstormy16 | xtensa)
insn="nop"
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 4fc851c..92cecbd 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -1744,7 +1744,10 @@ changequote(,)dnl
if test -f configargs.h ; then
# Being re-configured.
gcc_config_arguments=`grep configuration_arguments configargs.h | sed -e 's/.*"\([^"]*\)".*/\1/'`
- gcc_config_arguments="$gcc_config_arguments : (reconfigured) $TOPLEVEL_CONFIGURE_ARGUMENTS"
+ gcc_reconf_arguments=`echo "$gcc_config_arguments" | sed -e 's/^.*\( : (reconfigured) .*$\)/\1/'`
+ if [ "$gcc_reconf_arguments" != " : (reconfigured) $TOPLEVEL_CONFIGURE_ARGUMENTS" ]; then
+ gcc_config_arguments="$gcc_config_arguments : (reconfigured) $TOPLEVEL_CONFIGURE_ARGUMENTS"
+ fi
else
gcc_config_arguments="$TOPLEVEL_CONFIGURE_ARGUMENTS"
fi
@@ -3143,6 +3146,15 @@ case "${target}" in
;;
esac
+gcc_GAS_CHECK_FEATURE([line table is_stmt support],
+ gcc_cv_as_is_stmt,
+ [2,16,92],,
+[ .text
+ .file 1 "conf.c"
+ .loc 1 1 0 is_stmt 1],,
+[AC_DEFINE(HAVE_GAS_LOC_STMT, 1,
+ [Define if your assembler supports the .loc is_stmt sub-directive.])])
+
gcc_GAS_CHECK_FEATURE([line table discriminator support],
gcc_cv_as_discriminator,
[2,19,51],,
@@ -4932,7 +4944,7 @@ esac
# ??? Once 2.11 is released, probably need to add first known working
# version to the per-target configury.
case "$cpu_type" in
- aarch64 | alpha | arc | arm | avr | bfin | cris | i386 | m32c | m68k \
+ aarch64 | alpha | arc | arm | avr | bfin | cris | csky | i386 | m32c | m68k \
| microblaze | mips | nios2 | pa | riscv | rs6000 | score | sparc | spu \
| tilegx | tilepro | visium | xstormy16 | xtensa)
insn="nop"
diff --git a/gcc/coverage.c b/gcc/coverage.c
index bae6f5c..8f12778 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see
#include "intl.h"
#include "params.h"
#include "auto-profile.h"
+#include "profile.h"
#include "gcov-io.c"
@@ -73,7 +74,6 @@ struct counts_entry : pointer_hash <counts_entry>
unsigned lineno_checksum;
unsigned cfg_checksum;
gcov_type *counts;
- gcov_summary summary;
/* hash_table support. */
static inline hashval_t hash (const counts_entry *);
@@ -185,8 +185,6 @@ static void
read_counts_file (void)
{
gcov_unsigned_t fn_ident = 0;
- gcov_summary summary;
- unsigned new_summary = 1;
gcov_unsigned_t tag;
int is_error = 0;
unsigned lineno_checksum = 0;
@@ -236,27 +234,12 @@ read_counts_file (void)
}
else
fn_ident = lineno_checksum = cfg_checksum = 0;
- new_summary = 1;
}
- else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
+ else if (tag == GCOV_TAG_OBJECT_SUMMARY)
{
- struct gcov_summary sum;
-
- if (new_summary)
- memset (&summary, 0, sizeof (summary));
-
- gcov_read_summary (&sum);
- summary.runs += sum.runs;
- summary.sum_all += sum.sum_all;
- if (summary.run_max < sum.run_max)
- summary.run_max = sum.run_max;
- summary.sum_max += sum.sum_max;
- if (new_summary)
- memcpy (summary.histogram, sum.histogram,
- sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
- else
- gcov_histogram_merge (summary.histogram, sum.histogram);
- new_summary = 0;
+ profile_info = XCNEW (gcov_summary);
+ profile_info->runs = gcov_read_unsigned ();
+ profile_info->sum_max = gcov_read_unsigned ();
}
else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
{
@@ -276,9 +259,6 @@ read_counts_file (void)
entry->ctr = elt.ctr;
entry->lineno_checksum = lineno_checksum;
entry->cfg_checksum = cfg_checksum;
- if (elt.ctr == GCOV_COUNTER_ARCS)
- entry->summary = summary;
- entry->summary.num = n_counts;
entry->counts = XCNEWVEC (gcov_type, n_counts);
}
else if (entry->lineno_checksum != lineno_checksum
@@ -292,22 +272,6 @@ read_counts_file (void)
counts_hash = NULL;
break;
}
- else if (entry->summary.num != n_counts)
- {
- error ("Profile data for function %u is corrupted", fn_ident);
- error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
- delete counts_hash;
- counts_hash = NULL;
- break;
- }
- else
- {
- entry->summary.runs += summary.runs;
- entry->summary.sum_all += summary.sum_all;
- if (entry->summary.run_max < summary.run_max)
- entry->summary.run_max = summary.run_max;
- entry->summary.sum_max += summary.sum_max;
- }
for (ix = 0; ix != n_counts; ix++)
entry->counts[ix] += gcov_read_counter ();
}
@@ -330,9 +294,8 @@ read_counts_file (void)
/* Returns the counters for a particular tag. */
gcov_type *
-get_coverage_counts (unsigned counter, unsigned expected,
- unsigned cfg_checksum, unsigned lineno_checksum,
- const gcov_summary **summary)
+get_coverage_counts (unsigned counter, unsigned cfg_checksum,
+ unsigned lineno_checksum)
{
counts_entry *entry, elt;
@@ -363,23 +326,23 @@ get_coverage_counts (unsigned counter, unsigned expected,
}
elt.ctr = counter;
entry = counts_hash->find (&elt);
- if (!entry || !entry->summary.num)
+ if (!entry)
/* The function was not emitted, or is weak and not chosen in the
final executable. Silently fail, because there's nothing we
can do about it. */
return NULL;
- if (entry->cfg_checksum != cfg_checksum
- || entry->summary.num != expected)
+ if (entry->cfg_checksum != cfg_checksum)
{
static int warned = 0;
bool warning_printed = false;
- tree id = DECL_ASSEMBLER_NAME (current_function_decl);
warning_printed =
- warning_at (input_location, OPT_Wcoverage_mismatch,
- "the control flow of function %qE does not match "
- "its profile data (counter %qs)", id, ctr_names[counter]);
+ warning_at (DECL_SOURCE_LOCATION (current_function_decl),
+ OPT_Wcoverage_mismatch,
+ "the control flow of function %qD does not match "
+ "its profile data (counter %qs)", current_function_decl,
+ ctr_names[counter]);
if (warning_printed && dump_enabled_p ())
{
dump_user_location_t loc
@@ -408,15 +371,13 @@ get_coverage_counts (unsigned counter, unsigned expected,
}
else if (entry->lineno_checksum != lineno_checksum)
{
- warning (OPT_Wcoverage_mismatch,
- "source locations for function %qE have changed,"
- " the profile data may be out of date",
- DECL_ASSEMBLER_NAME (current_function_decl));
+ warning_at (DECL_SOURCE_LOCATION (current_function_decl),
+ OPT_Wcoverage_mismatch,
+ "source locations for function %qD have changed,"
+ " the profile data may be out of date",
+ current_function_decl);
}
- if (summary)
- *summary = &entry->summary;
-
return entry->counts;
}
diff --git a/gcc/coverage.h b/gcc/coverage.h
index 842d695..d612c38 100644
--- a/gcc/coverage.h
+++ b/gcc/coverage.h
@@ -51,10 +51,8 @@ extern tree tree_coverage_counter_addr (unsigned /*counter*/, unsigned/*num*/);
/* Get all the counters for the current function. */
extern gcov_type *get_coverage_counts (unsigned /*counter*/,
- unsigned /*expected*/,
unsigned /*cfg_checksum*/,
- unsigned /*lineno_checksum*/,
- const gcov_summary **);
+ unsigned /*lineno_checksum*/);
extern tree get_gcov_type (void);
extern bool coverage_node_map_initialized_p (void);
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1283607..6d4e93b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,8 +1,624 @@
+2018-09-24 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/85070
+ * method.c (lazily_declare_fn): During error-recovery add_method
+ may return false.
+
+2018-09-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87372 - __func__ constexpr evaluation.
+ * constexpr.c (maybe_constant_init_1): Pass false for strict down to
+ cxx_eval_outermost_constant_expr.
+
+2018-09-20 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87109 - wrong ctor with maybe-rvalue semantics.
+ * call.c (build_user_type_conversion_1): Refine the maybe-rvalue
+ check to only return if we're converting the return value to a base
+ class.
+
+2018-09-20 Allan Sandfeld Jensen <allan.jensen@qt.io>
+
+ * g++spec.c (lang_specific_driver): Handle -r like -nostdlib.
+
+2018-09-20 Jason Merrill <jason@redhat.com>
+
+ PR c++/87075 - ICE with constexpr array initialization.
+ * constexpr.c (cxx_eval_vec_init_1): Handle trivial initialization.
+
+2018-09-19 Marek Polacek <polacek@redhat.com>
+
+ Add -Wclass-conversion.
+ * decl.c (grok_op_properties): Change a warning from -Wconversion to
+ -Wclass-conversion. Make it print the types.
+
+2018-09-19 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/87324
+ * parser.c (cp_parser_initializer_list): Assign error_mark_node
+ to the index upon error.
+
+2018-09-19 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87357 - missing -Wconversion warning
+ * decl.c (grok_op_properties): Remove diagnostic parts mentioning
+ a conversion to a reference to void. Use
+ same_type_ignoring_top_level_qualifiers_p rather than comparing types
+ directly.
+
+2018-09-18 Marek Polacek <polacek@redhat.com>
+
+ P1064R0 - Allowing Virtual Function Calls in Constant Expressions
+ * call.c (build_over_call): No longer check if we're outside a template
+ function.
+ * class.c (build_vtbl_initializer): Build vtable's constructor with
+ indexes.
+ * constexpr.c (cxx_eval_constant_expression): Don't ignore _vptr's
+ initializer. Handle OBJ_TYPE_REF.
+ (potential_constant_expression_1): Handle OBJ_TYPE_REF.
+ * decl.c (maybe_commonize_var): Bail out for any DECL_ARTIFICIAL.
+ (initialize_artificial_var): Mark the variable as constexpr.
+ (grokdeclarator): Change error to pedwarn. Only warn when
+ pedantic and not C++2a.
+
+2018-09-18 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/85065
+ * cp-tree.h (NON_ERROR): New.
+ * pt.c (auto_hash::hash): Use it.
+ (do_auto_deduction): Likewise.
+
+2018-09-18 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/86881
+ * name-lookup.c (check_local_shadow): Ignore auto types.
+
+2018-09-17 David Malcolm <dmalcolm@redhat.com>
+
+ * error.c (range_label_for_type_mismatch::get_text): Update for
+ new param.
+
+2018-09-13 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * typeck2.c (digest_init_r): Fix overlength strings.
+
+2018-09-13 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ PR c++/87093
+ * method.c (constructible_expr): We're in an unevaluated context
+ in all cases, not just for class targets.
+
+2018-09-12 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/85110
+ * call.c (struct conversion_info): Add "loc" field.
+ (arg_conversion_rejection): Add "loc" param, using it to
+ initialize the new field.
+ (bad_arg_conversion_rejection): Likewise.
+ (explicit_conversion_rejection): Initialize the new field to
+ UNKNOWN_LOCATION.
+ (template_conversion_rejection): Likewise.
+ (add_function_candidate): Pass on the argument location to the new
+ param of arg_conversion_rejection.
+ (add_conv_candidate): Likewise.
+ (build_builtin_candidate): Likewise.
+ (build_user_type_conversion_1): Likewise.
+ (single_z_candidate): New function.
+ (maybe_get_bad_conversion_for_unmatched_call): New function.
+ (complain_about_bad_argument): New function, based on part of
+ convert_for_assignment.
+ (build_new_method_call_1): Split out handling of the "no viable
+ candidates" case into...
+ (complain_about_no_candidates_for_method_call): ...this new
+ function, and use the new functions above to special-case the
+ handling of a single non-viable candidate due to a bad argument.
+ * cp-tree.h (complain_about_bad_argument): New decl.
+ * typeck.c (convert_for_assignment): Split out one error-handling
+ case into complain_about_bad_argument.
+
+2018-09-09 Cesar Philippidis <cesar@codesourcery.com>
+ Julian Brown <julian@codesourcery.com>
+
+ PR middle-end/86336
+ * semantics.c (finish_omp_clauses): Treat C++ references the same in
+ OpenACC as OpenMP.
+
+2018-08-28 Martin Liska <mliska@suse.cz>
+
+ * constexpr.c (cxx_eval_call_expression): Add quotes
+ to -fconstexpr-depth=.
+
+2018-09-10 Marek Polacek <polacek@redhat.com>
+
+ * class.c (build_vtbl_ref): Remove.
+ (build_vtbl_ref_1): Rename to build_vtbl_ref.
+ (build_vfn_ref): Call build_vtbl_ref instead of build_vtbl_ref_1.
+
+2018-09-08 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87150 - wrong ctor with maybe-rvalue semantics.
+ * call.c (struct conversion): Update commentary.
+ (standard_conversion): Set rvaluedness_matches_p if LOOKUP_PREFER_RVALUE
+ for ck_base.
+
+2018-09-08 Jason Merrill <jason@redhat.com>
+
+ PR c++/86678 - constexpr function with non-constant after return.
+ * constexpr.c (potential_constant_expression_1): Add jump_target.
+ (breaks): Check for BREAK_STMT.
+ (continues): Check for CONTINUE_STMT.
+
+2018-09-08 Marek Polacek <polacek@redhat.com>
+
+ * cxx-pretty-print.c (cxx_pretty_printer::statement) <case
+ RANGE_FOR_SMT>: Handle RANGE_FOR_INIT_STMT.
+
+2018-09-07 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87152 - range-based for loops with initializer broken in templates.
+ * constexpr.c (potential_constant_expression_1) <case RANGE_FOR_STMT>:
+ Recur into RANGE_FOR_INIT_STMT.
+ * cp-tree.def: Add RANGE_FOR_INIT_STMT to RANGE_FOR_STMT.
+ * cp-tree.h (RANGE_FOR_INIT_STMT): Define.
+ * dump.c (cp_dump_tree) <case RANGE_FOR_STMT>: Also dump
+ RANGE_FOR_INIT_STMT.
+ * pt.c (tsubst_expr) <case RANGE_FOR_STMT>: Recur into
+ RANGE_FOR_INIT_STMT.
+ * semantics.c (begin_range_for_stmt): Adjust call to build_stmt.
+ Do put the init statement in RANGE_FOR_INIT_STMT.
+ (finish_range_for_decl): Pop it for templates.
+
+2018-09-06 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * decl.c (check_initializer): Call cp_complete_array_type.
+
+2018-09-05 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87109, wrong overload with ref-qualifiers.
+ * call.c (build_user_type_conversion_1): Use NULL instead of 0. Bail
+ out if performing the maybe-rvalue overload resolution and a conversion
+ function is getting called.
+
+ PR c++/86982, -Wreturn-local-addr and std::move and std::forward.
+ * typeck.c (maybe_warn_about_returning_address_of_local): Handle calls
+ to std::move or std::forward.
+ (is_std_forward_p): New function.
+
+2018-09-05 Pádraig Brady <p@draigbrady.com>
+
+ PR c++/87185
+ * lambda.c (prune_lambda_captures): Protect against const_vars.get
+ returning NULL.
+
+2018-09-04 Marek Polacek <polacek@redhat.com>
+
+ * cp-tree.h (treat_lvalue_as_rvalue_p): Declare.
+ * except.c (build_throw): Use it. Use CP_TYPE_VOLATILE_P.
+ * typeck.c (treat_lvalue_as_rvalue_p): No longer static. Add PARM_OK
+ parameter.
+ (maybe_warn_pessimizing_move): Adjust treat_lvalue_as_rvalue_p call.
+ (check_return_expr): Likewise.
+
+2018-09-03 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/84980
+ * constraint.cc (finish_shorthand_constraint): Early return if the
+ constraint is erroneous.
+
+2018-09-02 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * decl.c (eval_check_narrowing): Remove.
+ (check_initializer): Move call to braced_list_to_string from here ...
+ * typeck2.c (store_init_value): ... to here.
+ (digest_init_r): Remove handing of signed/unsigned char strings.
+
+2018-08-31 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/87155
+ PR c++/84707
+ * name-lookup.c (name_lookup::search_namespace): Don't look at
+ inlines when searching for NULL names.
+
+ * decl.c (decls_match): Remove SYSTEM_IMPLICIT_EXTERN_C matching
+ of return types and parms.
+ * parser.c (cp_parser_parameter_declaration_clause): Likewise,
+ '()' always means '(void)'.
+
+2018-08-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/87095
+ * decl.c (begin_destructor_body): If current_class_type has
+ virtual bases and the primary base is nearly empty virtual base,
+ voidify clearing of vptr and make it conditional on in-charge
+ argument.
+
+2018-08-29 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/85265
+ * parser.c (cp_parser_introduction_list): If cp_parser_identifier
+ returns error_mark_node early exit the loop.
+ (cp_parser_template_introduction): Improve error-recovery, remove
+ error call about empty introduction-list.
+
+2018-08-29 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/85110
+ * call.c (print_conversion_rejection): Add "fn" param and use it
+ for "no known conversion" messages to underline the pertinent
+ param.
+ (print_z_candidate): Supply "fn" to the new param above.
+
+2018-08-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/87122
+ * pt.c (tsubst_expr) <case RANGE_FOR_STMT>: If
+ processing_template_decl and decl is structured binding decl, call
+ cp_finish_decomp.
+
+2018-08-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/86546
+ * decl.c (finish_case_label): If the type is erroneous early
+ return error_mark_node.
+
+2018-08-27 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/63392
+ * parser.c (cp_parser_diagnose_invalid_type_name): Add fix-it
+ hint.
+
+2018-08-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/86993
+ * cp-tree.h (cxx_readonly_error): Add location_t argument.
+ * typeck2.c (cxx_readonly_error): Add LOC argument, pass it to
+ ERROR_FOR_ASSIGNMENT macro and readonly_error. Add LOC argument
+ to ERROR_FOR_ASSIGNMENT macro, use error_at instead of error and
+ pass LOC to it. Formatting fixes.
+ * typeck.c (cp_build_unary_op): Pass location to cxx_readonly_error.
+ (cp_build_modify_expr): Pass loc to cxx_readonly_error.
+ * semantics.c (finish_asm_stmt): Pass input_location to
+ cxx_readonly_error.
+
+2018-08-27 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/87091
+ * decl.c (grokdeclarator): Update for conversion of show_caret_p
+ to a tri-state.
+ * error.c (cp_printer): Likewise.
+ * name-lookup.c (maybe_suggest_missing_std_header): Update call to
+ maybe_add_include_fixit to suggest overriding the location, as it
+ is for a note.
+ * parser.c (cp_parser_string_literal): Update for conversion of
+ show_caret_p to a tri-state.
+ (cp_parser_elaborated_type_specifier): Likewise.
+ (set_and_check_decl_spec_loc): Likewise.
+ * pt.c (listify): Update call to maybe_add_include_fixit to not
+ override the location, as it is for an error.
+ * rtti.c (typeid_ok_p): Likewise.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ * call.c (build_call_a): Use new function
+ fndecl_built_in_p and remove check for FUNCTION_DECL if
+ possible.
+ (build_cxx_call): Likewise.
+ * constexpr.c (constexpr_fn_retval): Likewise.
+ (cxx_eval_builtin_function_call): Likewise.
+ (cxx_eval_call_expression): Likewise.
+ (potential_constant_expression_1): Likewise.
+ * cp-gimplify.c (cp_gimplify_expr): Likewise.
+ (cp_fold): Likewise.
+ * decl.c (decls_match): Likewise.
+ (validate_constexpr_redeclaration): Likewise.
+ (duplicate_decls): Likewise.
+ (make_rtl_for_nonlocal_decl): Likewise.
+ * name-lookup.c (consider_binding_level): Likewise.
+ (cp_emit_debug_info_for_using): Likewise.
+ * semantics.c (finish_call_expr): Likewise.
+ * tree.c (builtin_valid_in_constant_expr_p): Likewise.
+
+2018-08-26 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87080
+ * typeck.c (maybe_warn_pessimizing_move): Do nothing in a template.
+
+ PR c++/87029, Implement -Wredundant-move.
+ * typeck.c (treat_lvalue_as_rvalue_p): New function.
+ (maybe_warn_pessimizing_move): Call convert_from_reference.
+ Warn about redundant moves.
+
+2018-08-24 Marek Polacek <polacek@redhat.com>
+
+ PR c++/67012
+ PR c++/86942
+ * decl.c (grokdeclarator): Disallow functions with trailing return
+ type with decltype(auto) as its type. Also check the function if
+ it's inner declarator doesn't exist
+
+2018-08-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/86499
+ * parser.c (cp_parser_lambda_introducer): Give error if a non-local
+ lambda has a capture-default.
+
+2018-08-21 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * decl.c (check_static_variable_definition): Change to return void.
+
+2018-08-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/86981, Implement -Wpessimizing-move.
+ * typeck.c (decl_in_std_namespace_p): New.
+ (is_std_move_p): New.
+ (maybe_warn_pessimizing_move): New.
+ (can_do_nrvo_p): New, factored out of ...
+ (check_return_expr): ... here. Warn about potentially harmful
+ std::move in a return statement.
+
+ PR c++/65043
+ * call.c (standard_conversion): Set check_narrowing.
+ * typeck2.c (check_narrowing): Use CP_INTEGRAL_TYPE_P rather
+ than comparing with INTEGER_TYPE.
+
+ * cp-tree.h: Fix typo.
+
+2018-08-20 David Malcolm <dmalcolm@redhat.com>
+
+ PR other/84889
+ * call.c (build_user_type_conversion_1): Add auto_diagnostic_group
+ instance(s).
+ (print_error_for_call_failure): Likewise.
+ (build_op_call_1): Likewise.
+ (build_conditional_expr_1): Likewise.
+ (build_new_op_1): Likewise.
+ (build_op_delete_call): Likewise.
+ (convert_like_real): Likewise.
+ (build_over_call): Likewise.
+ (build_new_method_call_1): Likewise.
+ (joust): Likewise.
+ * class.c (check_tag): Likewise.
+ (finish_struct_anon_r): Likewise.
+ (one_inherited_ctor): Likewise.
+ (finalize_literal_type_property): Likewise.
+ (explain_non_literal_class): Likewise.
+ (find_flexarrays): Likewise.
+ (resolve_address_of_overloaded_function): Likewise.
+ * constexpr.c (ensure_literal_type_for_constexpr_object): Likewise.
+ (is_valid_constexpr_fn): Likewise.
+ (cx_check_missing_mem_inits): Likewise.
+ * cp-gimplify.c (cp_genericize_r): Likewise.
+ * cvt.c (maybe_warn_nodiscard): Likewise.
+ * decl.c (warn_extern_redeclared_static): Likewise.
+ (check_redeclaration_exception_specification): Likewise.
+ (check_no_redeclaration_friend_default_args): Likewise.
+ (duplicate_decls): Likewise.
+ (redeclaration_error_message): Likewise.
+ (warn_misplaced_attr_for_class_type): Likewise.
+ * decl2.c (finish_static_data_member_decl): Likewise.
+ (no_linkage_error): Likewise.
+ (cp_warn_deprecated_use): Likewise.
+ * error.c (qualified_name_lookup_error): Likewise.
+ * friend.c (make_friend_class): Likewise.
+ (do_friend): Likewise.
+ * init.c (perform_member_init): Likewise.
+ (build_new_1): Likewise.
+ (build_vec_delete_1): Likewise.
+ (build_delete): Likewise.
+ * lex.c (unqualified_name_lookup_error): Likewise.
+ * name-lookup.c (check_extern_c_conflict): Likewise.
+ (inform_shadowed): New function.
+ (check_local_shadow): Add auto_diagnostic_group instances,
+ replacing goto "inform_shadowed" label with call to subroutine.
+ (set_local_extern_decl_linkage): Add auto_diagnostic_group
+ instance(s).
+ * parser.c (cp_parser_diagnose_invalid_type_name): Likewise.
+ (cp_parser_namespace_name): Likewise.
+ * pt.c (check_specialization_namespace): Likewise.
+ (check_template_variable): Likewise.
+ (warn_spec_missing_attributes): Likewise.
+ (check_explicit_specialization): Likewise.
+ (process_partial_specialization): Likewise.
+ (lookup_template_class_1): Likewise.
+ (finish_template_variable): Likewise.
+ (do_auto_deduction): Likewise.
+ * search.c (check_final_overrider): Likewise.
+ (look_for_overrides_r): Likewise.
+ * tree.c (maybe_warn_parm_abi): Likewise.
+ * typeck.c (cxx_sizeof_expr): Likewise.
+ (cp_build_function_call_vec): Likewise.
+ (cp_build_binary_op): Likewise.
+ (convert_for_assignment): Likewise.
+ (maybe_warn_about_returning_address_of_local): Likewise.
+ * typeck2.c (abstract_virtuals_error_sfinae): Likewise.
+ (check_narrowing): Likewise.
+
+2018-08-17 David Malcolm <dmalcolm@redhat.com>
+
+ * typeck.c (string_conv_p): Extract location from EXP and use it
+ in preference to input_location when issuing warnings.
+
+2018-08-15 David Malcolm <dmalcolm@redhat.com>
+
+ * call.c: Include "gcc-rich-location.h".
+ (convert_like_real): Add range label for "invalid conversion"
+ diagnostic.
+ (perform_implicit_conversion_flags): Add type label to the
+ "could not convert" error.
+ * error.c: Include "gcc-rich-location.h".
+ (range_label_for_type_mismatch::get_text): New function.
+ * typeck.c (convert_for_assignment): Add type label to
+ the "cannot convert" error if a location is available.
+
+2018-08-15 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * decl.c (check_previous_goto_1): When decl_jump_unsafe returns 2
+ emit an error instead of a permerror.
+
+2018-08-13 Marek Polacek <polacek@redhat.com>
+
+ PR c++/57891
+ * call.c (struct conversion): Add check_narrowing_const_only.
+ (build_converted_constant_expr): Set check_narrowing and
+ check_narrowing_const_only. Give error if expr is error node.
+ (convert_like_real): Pass it to check_narrowing.
+ * cp-tree.h (check_narrowing): Add a default parameter.
+ * decl.c (compute_array_index_type): Use input_location instead of
+ location_of.
+ * pt.c (convert_nontype_argument): Return NULL_TREE if tf_error.
+ * typeck2.c (check_narrowing): Don't warn for instantiation-dependent
+ expressions. Call maybe_constant_value instead of
+ fold_non_dependent_expr. Don't mention { } in diagnostic. Only check
+ narrowing for constants if CONST_ONLY.
+
+2018-08-13 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/71625
+ * decl.c (check_initializer): Call braced_list_to_string.
+ (eval_check_narrowing): New function.
+ * gcc/cp/typeck2.c (digest_init_r): Accept strings literals
+ as initilizers for all narrow character types.
+
+2018-08-13 Marek Polacek <polacek@redhat.com>
+
+ P0806R2 - Deprecate implicit capture of this via [=]
+ * lambda.c (add_default_capture): Formatting fixes. Warn about
+ deprecated implicit capture of this via [=].
+
+ PR c++/86915
+ * decl.c (create_array_type_for_decl): Handle null name.
+
+2018-08-10 Jason Merrill <jason@redhat.com>
+
+ PR c++/86728 - C variadic generic lambda.
+ * parser.c (cp_parser_parameter_declaration): Don't turn 'auto' into
+ a pack if it's followed by a declarator-id.
+
+2018-08-08 Jakub Jelinek <jakub@redhat.com>
+
+ P0595R1 - is_constant_evaluated
+ * cp-tree.h (enum cp_built_in_function): New.
+ (maybe_constant_init): Add pretend_const_required argument.
+ * typeck2.c (store_init_value): Pass true as new argument to
+ maybe_constant_init.
+ * constexpr.c (constexpr_fn_retval): Check also DECL_BUILT_IN_CLASS
+ for BUILT_IN_UNREACHABLE.
+ (struct constexpr_ctx): Add pretend_const_required field.
+ (cxx_eval_builtin_function_call): Use DECL_IS_BUILTIN_CONSTANT_P
+ macro. Handle CP_BUILT_IN_IS_CONSTANT_EVALUATED. Check also
+ DECL_BUILT_IN_CLASS for BUILT_IN_UNREACHABLE.
+ (cxx_eval_outermost_constant_expr): Add pretend_const_required
+ argument, initialize pretend_const_required field in ctx. If the
+ result is TREE_CONSTANT and non_constant_p, retry with
+ pretend_const_required false if it was true.
+ (is_sub_constant_expr): Initialize pretend_const_required_field in
+ ctx.
+ (cxx_constant_value): Pass true as pretend_const_required to
+ cxx_eval_outermost_constant_expr.
+ (maybe_constant_value): Pass false as pretend_const_required to
+ cxx_eval_outermost_constant_expr.
+ (fold_non_dependent_expr): Likewise.
+ (maybe_constant_init_1): Add pretend_const_required argument, pass it
+ down to cxx_eval_outermost_constant_expr. Pass !allow_non_constant
+ instead of false as strict to cxx_eval_outermost_constant_expr.
+ (maybe_constant_init): Add pretend_const_required argument, pass it
+ down to maybe_constant_init_1.
+ (cxx_constant_init): Pass true as pretend_const_required to
+ maybe_constant_init_1.
+ * cp-gimplify.c (cp_gimplify_expr): Handle CALL_EXPRs to
+ CP_BUILT_IN_IS_CONSTANT_EVALUATED.
+ (cp_fold): Don't fold CP_BUILT_IN_IS_CONSTANT_EVALUATED calls.
+ * decl.c: Include langhooks.h.
+ (cxx_init_decl_processing): Register __builtin_is_constant_evaluated
+ built-in.
+ * tree.c (builtin_valid_in_constant_expr_p): Return true for
+ CP_BUILT_IN_IS_CONSTANT_EVALUATED.
+ * pt.c (declare_integer_pack): Initialize DECL_FUNCTION_CODE.
+
+ PR c++/86836
+ * pt.c (tsubst_expr): For structured bindings, call tsubst_decomp_names
+ before tsubst_init, not after it.
+
+ PR c++/86738
+ * constexpr.c (cxx_eval_binary_expression): For arithmetics involving
+ NULL pointer set *non_constant_p to true.
+ (cxx_eval_component_reference): For dereferencing of a NULL pointer,
+ set *non_constant_p to true and return t.
+
+2018-08-07 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/59480, DR 136
+ * decl.c (check_no_redeclaration_friend_default_args): New.
+ (duplicate_decls): Use the latter; also check that a friend
+ declaration specifying default arguments is a definition.
+
+2018-08-07 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ PR c++/79133
+ * name-lookup.c (check_local_shadow): Reject captures and parameters
+ with the same name.
+
+2018-08-06 Marek Polacek <polacek@redhat.com>
+
+ PR c++/86767
+ * constexpr.c (cxx_eval_statement_list): Handle continue.
+
+2018-08-03 David Malcolm <dmalcolm@redhat.com>
+ Jonathan Wakely <jwakely@redhat.com>
+
+ * decl.c: Include "gcc-rich-location.h".
+ (add_return_star_this_fixit): New function.
+ (finish_function): When warning about missing return statements in
+ functions returning non-void, add a "return *this;" fix-it hint for
+ assignment operators.
+
+2018-08-03 Jason Merrill <jason@redhat.com>
+
+ PR c++/86706
+ * class.c (build_base_path): Use currently_open_class.
+
+2018-08-02 David Malcolm <dmalcolm@redhat.com>
+
+ * error.c (cxx_print_error_function): Duplicate "file" before
+ passing it to pp_set_prefix.
+ (cp_print_error_function): Use pp_take_prefix when saving the
+ existing prefix.
+
+2018-08-02 Richard Biener <rguenther@suse.de>
+
+ PR c++/86763
+ * class.c (layout_class_type): Copy TYPE_TYPELESS_STORAGE
+ to the CLASSTYPE_AS_BASE.
+
+2018-08-01 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/86650
+ * error.c (cp_printer): Move usage of EXPR_LOCATION (t) and
+ TREE_BLOCK (t) from within percent_K_format to this callsite.
+
+2018-08-01 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/86661
+ * class.c (note_name_declared_in_class): Use location_of in permerror
+ instead of DECL_SOURCE_LOCATION (for OVERLOADs).
+
+2018-07-31 Tom de Vries <tdevries@suse.de>
+
+ PR debug/86687
+ * optimize.c (update_cloned_parm): Copy DECL_BY_REFERENCE.
+
+2018-07-31 Jakub Jelinek <jakub@redhat.com>
+
+ P1008R1 - prohibit aggregates with user-declared constructors
+ * class.c (check_bases_and_members): For C++2a set
+ CLASSTYPE_NON_AGGREGATE based on TYPE_HAS_USER_CONSTRUCTOR rather than
+ type_has_user_provided_or_explicit_constructor.
+
2018-07-31 Martin Liska <mliska@suse.cz>
- PR c++/86653
+ PR c++/86653
* parser.c (cp_parser_condition): Initialize non_constant_p
- to false.
+ to false.
2018-07-28 David Malcolm <dmalcolm@redhat.com>
@@ -3249,7 +3865,7 @@
2018-01-10 Paolo Carlini <paolo.carlini@oracle.com>
* parser.c (cp_parser_std_attribute_spec): When
- token_pair::require_open / require_close return false simply
+ token_pair::require_open / require_close return false simply
return error_mark_node, avoid duplicate cp_parser_error about
expected '(' / ')', respectively.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 209c1fd..b2ca667 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see
#include "internal-fn.h"
#include "stringpool.h"
#include "attribs.h"
+#include "gcc-rich-location.h"
/* The various kinds of conversion. */
@@ -101,12 +102,15 @@ struct conversion {
BOOL_BITFIELD base_p : 1;
/* If KIND is ck_ref_bind, true when either an lvalue reference is
being bound to an lvalue expression or an rvalue reference is
- being bound to an rvalue expression. If KIND is ck_rvalue,
+ being bound to an rvalue expression. If KIND is ck_rvalue or ck_base,
true when we are treating an lvalue as an rvalue (12.8p33). If
- KIND is ck_base, always false. If ck_identity, we will be
- binding a reference directly or decaying to a pointer. */
+ ck_identity, we will be binding a reference directly or decaying to
+ a pointer. */
BOOL_BITFIELD rvaluedness_matches_p: 1;
BOOL_BITFIELD check_narrowing: 1;
+ /* Whether check_narrowing should only check TREE_CONSTANTs; used
+ in build_converted_constant_expr. */
+ BOOL_BITFIELD check_narrowing_const_only: 1;
/* The type of the expression resulting from the conversion. */
tree type;
union {
@@ -385,7 +389,7 @@ build_call_a (tree function, int n, tree *argarray)
/* Don't pass empty class objects by value. This is useful
for tags in STL, which are used to control overload resolution.
We don't need to handle other cases of copying empty classes. */
- if (! decl || ! DECL_BUILT_IN (decl))
+ if (!decl || !fndecl_built_in_p (decl))
for (i = 0; i < n; i++)
{
tree arg = CALL_EXPR_ARG (function, i);
@@ -432,6 +436,8 @@ struct conversion_info {
tree from;
/* The type of the parameter. */
tree to_type;
+ /* The location of the argument. */
+ location_t loc;
};
struct rejection_reason {
@@ -623,24 +629,28 @@ arity_rejection (tree first_arg, int expected, int actual)
}
static struct rejection_reason *
-arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to)
+arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to,
+ location_t loc)
{
struct rejection_reason *r = alloc_rejection (rr_arg_conversion);
int adjust = first_arg != NULL_TREE;
r->u.conversion.n_arg = n_arg - adjust;
r->u.conversion.from = from;
r->u.conversion.to_type = to;
+ r->u.conversion.loc = loc;
return r;
}
static struct rejection_reason *
-bad_arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to)
+bad_arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to,
+ location_t loc)
{
struct rejection_reason *r = alloc_rejection (rr_bad_arg_conversion);
int adjust = first_arg != NULL_TREE;
r->u.bad_conversion.n_arg = n_arg - adjust;
r->u.bad_conversion.from = from;
r->u.bad_conversion.to_type = to;
+ r->u.bad_conversion.loc = loc;
return r;
}
@@ -651,6 +661,7 @@ explicit_conversion_rejection (tree from, tree to)
r->u.conversion.n_arg = 0;
r->u.conversion.from = from;
r->u.conversion.to_type = to;
+ r->u.conversion.loc = UNKNOWN_LOCATION;
return r;
}
@@ -661,6 +672,7 @@ template_conversion_rejection (tree from, tree to)
r->u.conversion.n_arg = 0;
r->u.conversion.from = from;
r->u.conversion.to_type = to;
+ r->u.conversion.loc = UNKNOWN_LOCATION;
return r;
}
@@ -1384,6 +1396,8 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
conv->rank = cr_pbool;
if (NULLPTR_TYPE_P (from) && (flags & LOOKUP_ONLYCONVERTING))
conv->bad_p = true;
+ if (flags & LOOKUP_NO_NARROWING)
+ conv->check_narrowing = true;
return conv;
}
@@ -1419,6 +1433,9 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
type. A temporary object is created to hold the result of
the conversion unless we're binding directly to a reference. */
conv->need_temporary_p = !(flags & LOOKUP_NO_TEMP_BIND);
+ if (flags & LOOKUP_PREFER_RVALUE)
+ /* Tell convert_like_real to set LOOKUP_PREFER_RVALUE. */
+ conv->rvaluedness_matches_p = true;
}
else
return NULL;
@@ -2248,14 +2265,17 @@ add_function_candidate (struct z_candidate **candidates,
if (! t)
{
viable = 0;
- reason = arg_conversion_rejection (first_arg, i, argtype, to_type);
+ reason = arg_conversion_rejection (first_arg, i, argtype, to_type,
+ EXPR_LOCATION (arg));
break;
}
if (t->bad_p)
{
viable = -1;
- reason = bad_arg_conversion_rejection (first_arg, i, arg, to_type);
+ reason = bad_arg_conversion_rejection (first_arg, i, arg, to_type,
+ EXPR_LOCATION (arg));
+
}
}
@@ -2344,7 +2364,8 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
if (t->bad_p)
{
viable = -1;
- reason = bad_arg_conversion_rejection (NULL_TREE, i, arg, convert_type);
+ reason = bad_arg_conversion_rejection (NULL_TREE, i, arg, convert_type,
+ EXPR_LOCATION (arg));
}
if (i == 0)
@@ -2405,13 +2426,14 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname,
/* We need something for printing the candidate. */
t = build_identity_conv (types[i], NULL_TREE);
reason = arg_conversion_rejection (NULL_TREE, i, argtypes[i],
- types[i]);
+ types[i], EXPR_LOCATION (args[i]));
}
else if (t->bad_p)
{
viable = 0;
reason = bad_arg_conversion_rejection (NULL_TREE, i, args[i],
- types[i]);
+ types[i],
+ EXPR_LOCATION (args[i]));
}
convs[i] = t;
}
@@ -2430,7 +2452,8 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname,
{
viable = 0;
reason = arg_conversion_rejection (NULL_TREE, 0, argtypes[2],
- boolean_type_node);
+ boolean_type_node,
+ EXPR_LOCATION (args[2]));
}
}
@@ -3426,10 +3449,11 @@ equal_functions (tree fn1, tree fn2)
return fn1 == fn2;
}
-/* Print information about a candidate being rejected due to INFO. */
+/* Print information about a candidate FN being rejected due to INFO. */
static void
-print_conversion_rejection (location_t loc, struct conversion_info *info)
+print_conversion_rejection (location_t loc, struct conversion_info *info,
+ tree fn)
{
tree from = info->from;
if (!TYPE_P (from))
@@ -3460,8 +3484,12 @@ print_conversion_rejection (location_t loc, struct conversion_info *info)
inform (loc, " no known conversion from %qH to %qI",
from, info->to_type);
else
- inform (loc, " no known conversion for argument %d from %qH to %qI",
- info->n_arg + 1, from, info->to_type);
+ {
+ if (TREE_CODE (fn) == FUNCTION_DECL)
+ loc = get_fndecl_argument_location (fn, info->n_arg);
+ inform (loc, " no known conversion for argument %d from %qH to %qI",
+ info->n_arg + 1, from, info->to_type);
+ }
}
/* Print information about a candidate with WANT parameters and we found
@@ -3536,10 +3564,10 @@ print_z_candidate (location_t loc, const char *msgstr,
r->u.arity.expected);
break;
case rr_arg_conversion:
- print_conversion_rejection (cloc, &r->u.conversion);
+ print_conversion_rejection (cloc, &r->u.conversion, fn);
break;
case rr_bad_arg_conversion:
- print_conversion_rejection (cloc, &r->u.bad_conversion);
+ print_conversion_rejection (cloc, &r->u.bad_conversion, fn);
break;
case rr_explicit_conversion:
inform (cloc, " return type %qT of explicit conversion function "
@@ -3916,7 +3944,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags,
{
cand->viable = 0;
cand->reason = arg_conversion_rejection (NULL_TREE, -2,
- rettype, totype);
+ rettype, totype,
+ EXPR_LOCATION (expr));
}
else if (DECL_NONCONVERTING_P (cand->fn)
&& ics->rank > cr_exact)
@@ -3936,7 +3965,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags,
cand->viable = -1;
cand->reason
= bad_arg_conversion_rejection (NULL_TREE, -2,
- rettype, totype);
+ rettype, totype,
+ EXPR_LOCATION (expr));
}
else if (primary_template_specialization_p (cand->fn)
&& ics->rank > cr_exact)
@@ -3960,10 +3990,11 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags,
}
cand = tourney (candidates, complain);
- if (cand == 0)
+ if (cand == NULL)
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
error ("conversion from %qH to %qI is ambiguous",
fromtype, totype);
print_z_candidates (location_of (expr), candidates);
@@ -4002,6 +4033,14 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags,
if (cand->viable == -1)
conv->bad_p = true;
+ /* We're performing the maybe-rvalue overload resolution and
+ a conversion function is in play. Reject converting the return
+ value of the conversion function to a base class. */
+ if ((flags & LOOKUP_PREFER_RVALUE) && !DECL_CONSTRUCTOR_P (cand->fn))
+ for (conversion *t = cand->second_conv; t; t = next_conversion (t))
+ if (t->kind == ck_base)
+ return NULL;
+
/* Remember that this was a list-initialization. */
if (flags & LOOKUP_NO_NARROWING)
conv->check_narrowing = true;
@@ -4152,9 +4191,18 @@ build_converted_constant_expr (tree type, tree expr, tsubst_flags_t complain)
}
if (conv)
- expr = convert_like (conv, expr, complain);
+ {
+ conv->check_narrowing = true;
+ conv->check_narrowing_const_only = true;
+ expr = convert_like (conv, expr, complain);
+ }
else
- expr = error_mark_node;
+ {
+ if (complain & tf_error)
+ error_at (loc, "could not convert %qE from %qH to %qI", expr,
+ TREE_TYPE (expr), type);
+ expr = error_mark_node;
+ }
/* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p);
@@ -4267,6 +4315,7 @@ print_error_for_call_failure (tree fn, vec<tree, va_gc> *args,
if (targs)
name = lookup_template_function (name, targs);
+ auto_diagnostic_group d;
if (!any_strictly_viable (candidates))
error_at (loc, "no matching function for call to %<%D(%A)%>",
name, build_tree_list_vec (args));
@@ -4577,6 +4626,7 @@ build_op_call_1 (tree obj, vec<tree, va_gc> **args, tsubst_flags_t complain)
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
error ("no match for call to %<(%T) (%A)%>", TREE_TYPE (obj),
build_tree_list_vec (*args));
print_z_candidates (location_of (TREE_TYPE (obj)), candidates);
@@ -4590,6 +4640,7 @@ build_op_call_1 (tree obj, vec<tree, va_gc> **args, tsubst_flags_t complain)
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
error ("call of %<(%T) (%A)%> is ambiguous",
TREE_TYPE (obj), build_tree_list_vec (*args));
print_z_candidates (location_of (TREE_TYPE (obj)), candidates);
@@ -5216,6 +5267,7 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
op_error (loc, COND_EXPR, NOP_EXPR, arg1, arg2, arg3, FALSE);
print_z_candidates (loc, candidates);
}
@@ -5847,6 +5899,7 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
{
/* ... Otherwise, report the more generic
"no matching operator found" error */
+ auto_diagnostic_group d;
op_error (loc, code, code2, arg1, arg2, arg3, FALSE);
print_z_candidates (loc, candidates);
}
@@ -5862,6 +5915,7 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
op_error (loc, code, code2, arg1, arg2, arg3, TRUE);
print_z_candidates (loc, candidates);
}
@@ -6298,14 +6352,18 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
-Wc++14-compat. */
else if (!flag_sized_deallocation)
{
- if ((complain & tf_warning)
- && warning (OPT_Wc__14_compat, msg1))
- inform (DECL_SOURCE_LOCATION (fn), msg2, fn);
+ if (complain & tf_warning)
+ {
+ auto_diagnostic_group d;
+ if (warning (OPT_Wc__14_compat, msg1))
+ inform (DECL_SOURCE_LOCATION (fn), msg2, fn);
+ }
goto ok;
}
if (complain & tf_warning_or_error)
{
+ auto_diagnostic_group d;
if (permerror (input_location, msg1))
{
/* Only mention C++14 for namespace-scope delete. */
@@ -6699,6 +6757,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
{
if (t->kind == ck_user && t->cand->reason)
{
+ auto_diagnostic_group d;
complained = permerror (loc, "invalid user-defined conversion "
"from %qH to %qI", TREE_TYPE (expr),
totype);
@@ -6736,8 +6795,13 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
break;
}
if (!complained)
- complained = permerror (loc, "invalid conversion from %qH to %qI",
- TREE_TYPE (expr), totype);
+ {
+ range_label_for_type_mismatch label (TREE_TYPE (expr), totype);
+ gcc_rich_location richloc (loc, &label);
+ complained = permerror (&richloc,
+ "invalid conversion from %qH to %qI",
+ TREE_TYPE (expr), totype);
+ }
if (complained && fn)
inform (get_fndecl_argument_location (fn, argnum),
" initializing argument %P of %qD", argnum, fn);
@@ -6777,6 +6841,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
if (CONSTRUCTOR_NELTS (expr) == 0
&& FUNCTION_FIRST_USER_PARMTYPE (convfn) != void_list_node)
{
+ auto_diagnostic_group d;
if (pedwarn (loc, 0, "converting to %qT from initializer list "
"would use explicit constructor %qD",
totype, convfn))
@@ -6955,6 +7020,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
maybe_print_user_conv_context (convs);
if (fn)
inform (DECL_SOURCE_LOCATION (fn),
@@ -7007,6 +7073,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
expr = build_temp (expr, totype, flags, &diag_kind, complain);
if (diag_kind && complain)
{
+ auto_diagnostic_group d;
maybe_print_user_conv_context (convs);
if (fn)
inform (DECL_SOURCE_LOCATION (fn),
@@ -7022,6 +7089,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
if (convs->bad_p && !next_conversion (convs)->bad_p)
{
tree extype = TREE_TYPE (expr);
+ auto_diagnostic_group d;
if (TYPE_REF_IS_RVALUE (ref_type)
&& lvalue_p (expr))
error_at (loc, "cannot bind rvalue reference of type %qH to "
@@ -7142,7 +7210,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
}
if (convs->check_narrowing
- && !check_narrowing (totype, expr, complain))
+ && !check_narrowing (totype, expr, complain,
+ convs->check_narrowing_const_only))
return error_mark_node;
warning_sentinel w (warn_zero_as_null_pointer_constant);
@@ -7885,7 +7954,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
{
/* The implicit move specified in 15.8.3/3 fails "...if the type of
the first parameter of the selected constructor is not an rvalue
- reference to the object’s type (possibly cv-qualified)...." */
+ reference to the object's type (possibly cv-qualified)...." */
gcc_assert (!(complain & tf_error));
tree ptype = convs[0]->type;
if (!TYPE_REF_P (ptype)
@@ -7912,6 +7981,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
if (permerror (input_location, "passing %qT as %<this%> "
"argument discards qualifiers",
TREE_TYPE (argtype)))
@@ -8331,10 +8401,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
&& DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL)
maybe_warn_class_memaccess (input_location, fn, args);
- if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0
- /* Don't mess with virtual lookup in instantiate_non_dependent_expr;
- virtual functions can't be constexpr. */
- && !in_template_function ())
+ if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0)
{
tree t;
tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (argarray[0])),
@@ -8831,8 +8898,7 @@ build_cxx_call (tree fn, int nargs, tree *argarray,
/* Check that arguments to builtin functions match the expectations. */
if (fndecl
&& !processing_template_decl
- && DECL_BUILT_IN (fndecl)
- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+ && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
{
int i;
@@ -9114,6 +9180,129 @@ name_as_c_string (tree name, tree type, bool *free_p)
return CONST_CAST (char *, pretty_name);
}
+/* If CANDIDATES contains exactly one candidate, return it, otherwise
+ return NULL. */
+
+static z_candidate *
+single_z_candidate (z_candidate *candidates)
+{
+ if (candidates == NULL)
+ return NULL;
+
+ if (candidates->next)
+ return NULL;
+
+ return candidates;
+}
+
+/* If CANDIDATE is invalid due to a bad argument type, return the
+ pertinent conversion_info.
+
+ Otherwise, return NULL. */
+
+static const conversion_info *
+maybe_get_bad_conversion_for_unmatched_call (const z_candidate *candidate)
+{
+ /* Must be an rr_arg_conversion or rr_bad_arg_conversion. */
+ rejection_reason *r = candidate->reason;
+
+ if (r == NULL)
+ return NULL;
+
+ switch (r->code)
+ {
+ default:
+ return NULL;
+
+ case rr_arg_conversion:
+ return &r->u.conversion;
+
+ case rr_bad_arg_conversion:
+ return &r->u.bad_conversion;
+ }
+}
+
+/* Issue an error and note complaining about a bad argument type at a
+ callsite with a single candidate FNDECL.
+
+ ARG_LOC is the location of the argument (or UNKNOWN_LOCATION, in which
+ case input_location is used).
+ FROM_TYPE is the type of the actual argument; TO_TYPE is the type of
+ the formal parameter. */
+
+void
+complain_about_bad_argument (location_t arg_loc,
+ tree from_type, tree to_type,
+ tree fndecl, int parmnum)
+{
+ auto_diagnostic_group d;
+ range_label_for_type_mismatch rhs_label (from_type, to_type);
+ range_label *label = &rhs_label;
+ if (arg_loc == UNKNOWN_LOCATION)
+ {
+ arg_loc = input_location;
+ label = NULL;
+ }
+ gcc_rich_location richloc (arg_loc, label);
+ error_at (&richloc,
+ "cannot convert %qH to %qI",
+ from_type, to_type);
+ inform (get_fndecl_argument_location (fndecl, parmnum),
+ " initializing argument %P of %qD", parmnum, fndecl);
+}
+
+/* Subroutine of build_new_method_call_1, for where there are no viable
+ candidates for the call. */
+
+static void
+complain_about_no_candidates_for_method_call (tree instance,
+ z_candidate *candidates,
+ tree explicit_targs,
+ tree basetype,
+ tree optype, tree name,
+ bool skip_first_for_error,
+ vec<tree, va_gc> *user_args)
+{
+ auto_diagnostic_group d;
+ if (!COMPLETE_OR_OPEN_TYPE_P (basetype))
+ cxx_incomplete_type_error (instance, basetype);
+ else if (optype)
+ error ("no matching function for call to %<%T::operator %T(%A)%#V%>",
+ basetype, optype, build_tree_list_vec (user_args),
+ TREE_TYPE (instance));
+ else
+ {
+ /* Special-case for when there's a single candidate that's failing
+ due to a bad argument type. */
+ if (z_candidate *candidate = single_z_candidate (candidates))
+ if (const conversion_info *conv
+ = maybe_get_bad_conversion_for_unmatched_call (candidate))
+ {
+ complain_about_bad_argument (conv->loc,
+ conv->from, conv->to_type,
+ candidate->fn, conv->n_arg);
+ return;
+ }
+
+ tree arglist = build_tree_list_vec (user_args);
+ tree errname = name;
+ bool twiddle = false;
+ if (IDENTIFIER_CDTOR_P (errname))
+ {
+ twiddle = IDENTIFIER_DTOR_P (errname);
+ errname = constructor_name (basetype);
+ }
+ if (explicit_targs)
+ errname = lookup_template_function (errname, explicit_targs);
+ if (skip_first_for_error)
+ arglist = TREE_CHAIN (arglist);
+ error ("no matching function for call to %<%T::%s%E(%A)%#V%>",
+ basetype, &"~"[!twiddle], errname, arglist,
+ TREE_TYPE (instance));
+ }
+ print_z_candidates (location_of (name), candidates);
+}
+
/* Build a call to "INSTANCE.FN (ARGS)". If FN_P is non-NULL, it will
be set, upon return, to the function called. ARGS may be NULL.
This may change ARGS. */
@@ -9193,6 +9382,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
basetype = DECL_CONTEXT (fn);
name = constructor_name (basetype);
+ auto_diagnostic_group d;
if (permerror (input_location,
"cannot call constructor %<%T::%D%> directly",
basetype, name))
@@ -9330,33 +9520,11 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
if (!any_viable_p)
{
if (complain & tf_error)
- {
- if (!COMPLETE_OR_OPEN_TYPE_P (basetype))
- cxx_incomplete_type_error (instance, basetype);
- else if (optype)
- error ("no matching function for call to %<%T::operator %T(%A)%#V%>",
- basetype, optype, build_tree_list_vec (user_args),
- TREE_TYPE (instance));
- else
- {
- tree arglist = build_tree_list_vec (user_args);
- tree errname = name;
- bool twiddle = false;
- if (IDENTIFIER_CDTOR_P (errname))
- {
- twiddle = IDENTIFIER_DTOR_P (errname);
- errname = constructor_name (basetype);
- }
- if (explicit_targs)
- errname = lookup_template_function (errname, explicit_targs);
- if (skip_first_for_error)
- arglist = TREE_CHAIN (arglist);
- error ("no matching function for call to %<%T::%s%E(%A)%#V%>",
- basetype, &"~"[!twiddle], errname, arglist,
- TREE_TYPE (instance));
- }
- print_z_candidates (location_of (name), candidates);
- }
+ complain_about_no_candidates_for_method_call (instance, candidates,
+ explicit_targs, basetype,
+ optype, name,
+ skip_first_for_error,
+ user_args);
call = error_mark_node;
}
else
@@ -9374,6 +9542,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
arglist = build_tree_list_vec (user_args);
if (skip_first_for_error)
arglist = TREE_CHAIN (arglist);
+ auto_diagnostic_group d;
if (!any_strictly_viable (candidates))
error ("no matching function for call to %<%s(%A)%>",
pretty_name, arglist);
@@ -10280,6 +10449,7 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn,
tree source = source_type (w->convs[0]);
if (INDIRECT_TYPE_P (source))
source = TREE_TYPE (source);
+ auto_diagnostic_group d;
if (warning (OPT_Wconversion, "choosing %qD over %qD", w->fn, l->fn)
&& warning (OPT_Wconversion, " for conversion from %qH to %qI",
source, w->second_conv->type))
@@ -10507,6 +10677,7 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn,
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
if (permerror (input_location,
"default argument mismatch in "
"overload resolution"))
@@ -10558,6 +10729,7 @@ tweak:
return 0;
if (warn)
{
+ auto_diagnostic_group d;
pedwarn (input_location, 0,
"ISO C++ says that these are ambiguous, even "
"though the worst conversion for the first is better than "
@@ -10742,8 +10914,12 @@ perform_implicit_conversion_flags (tree type, tree expr,
else if (invalid_nonstatic_memfn_p (loc, expr, complain))
/* We gave an error. */;
else
- error_at (loc, "could not convert %qE from %qH to %qI", expr,
- TREE_TYPE (expr), type);
+ {
+ range_label_for_type_mismatch label (TREE_TYPE (expr), type);
+ gcc_rich_location rich_loc (loc, &label);
+ error_at (&rich_loc, "could not convert %qE from %qH to %qI",
+ expr, TREE_TYPE (expr), type);
+ }
}
expr = error_mark_node;
}
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index d2f7808..9ca4644 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -133,7 +133,6 @@ static void maybe_warn_about_overly_private_class (tree);
static void add_implicitly_declared_members (tree, tree*, int, int);
static tree fixed_type_or_null (tree, int *, int *);
static tree build_simple_base_path (tree expr, tree binfo);
-static tree build_vtbl_ref_1 (tree, tree);
static void build_vtbl_initializer (tree, tree, tree, tree, int *,
vec<constructor_elt, va_gc> **);
static bool check_bitfield_decl (tree);
@@ -278,6 +277,9 @@ build_base_path (enum tree_code code,
probe = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
if (want_pointer)
probe = TYPE_MAIN_VARIANT (TREE_TYPE (probe));
+ if (dependent_type_p (probe))
+ if (tree open = currently_open_class (probe))
+ probe = open;
if (code == PLUS_EXPR
&& !SAME_BINFO_TYPE_P (BINFO_TYPE (d_binfo), probe))
@@ -696,8 +698,8 @@ build_vfield_ref (tree datum, tree type)
cases for INSTANCE which we take care of here, mainly to avoid
creating extra tree nodes when we don't have to. */
-static tree
-build_vtbl_ref_1 (tree instance, tree idx)
+tree
+build_vtbl_ref (tree instance, tree idx)
{
tree aref;
tree vtbl = NULL_TREE;
@@ -727,14 +729,6 @@ build_vtbl_ref_1 (tree instance, tree idx)
return aref;
}
-tree
-build_vtbl_ref (tree instance, tree idx)
-{
- tree aref = build_vtbl_ref_1 (instance, idx);
-
- return aref;
-}
-
/* Given a stable object pointer INSTANCE_PTR, return an expression which
yields a function pointer corresponding to vtable element INDEX. */
@@ -743,8 +737,7 @@ build_vfn_ref (tree instance_ptr, tree idx)
{
tree aref;
- aref = build_vtbl_ref_1 (cp_build_fold_indirect_ref (instance_ptr),
- idx);
+ aref = build_vtbl_ref (cp_build_fold_indirect_ref (instance_ptr), idx);
/* When using function descriptors, the address of the
vtable entry is treated as a function pointer. */
@@ -1328,6 +1321,7 @@ check_tag (tree tag, tree id, tree *tp, abi_tag_data *p)
/* Otherwise we're diagnosing missing tags. */
if (TREE_CODE (p->t) == FUNCTION_DECL)
{
+ auto_diagnostic_group d;
if (warning (OPT_Wabi_tag, "%qD inherits the %E ABI tag "
"that %qT (used in its return type) has",
p->t, tag, *tp))
@@ -1335,12 +1329,14 @@ check_tag (tree tag, tree id, tree *tp, abi_tag_data *p)
}
else if (VAR_P (p->t))
{
+ auto_diagnostic_group d;
if (warning (OPT_Wabi_tag, "%qD inherits the %E ABI tag "
"that %qT (used in its type) has", p->t, tag, *tp))
inform (location_of (*tp), "%qT declared here", *tp);
}
else if (TYPE_P (p->subob))
{
+ auto_diagnostic_group d;
if (warning (OPT_Wabi_tag, "%qT does not have the %E ABI tag "
"that base %qT has", p->t, tag, p->subob))
inform (location_of (p->subob), "%qT declared here",
@@ -1348,6 +1344,7 @@ check_tag (tree tag, tree id, tree *tp, abi_tag_data *p)
}
else
{
+ auto_diagnostic_group d;
if (warning (OPT_Wabi_tag, "%qT does not have the %E ABI tag "
"that %qT (used in the type of %qD) has",
p->t, tag, *tp, p->subob))
@@ -2901,20 +2898,24 @@ finish_struct_anon_r (tree field, bool complain)
{
/* We already complained about static data members in
finish_static_data_member_decl. */
- if (!VAR_P (elt)
- && permerror (DECL_SOURCE_LOCATION (elt),
- TREE_CODE (TREE_TYPE (field)) == UNION_TYPE
- ? "%q#D invalid; an anonymous union may "
- "only have public non-static data members"
- : "%q#D invalid; an anonymous struct may "
- "only have public non-static data members", elt))
+ if (!VAR_P (elt))
{
- static bool hint;
- if (flag_permissive && !hint)
+ auto_diagnostic_group d;
+ if (permerror (DECL_SOURCE_LOCATION (elt),
+ TREE_CODE (TREE_TYPE (field)) == UNION_TYPE
+ ? "%q#D invalid; an anonymous union may "
+ "only have public non-static data members"
+ : "%q#D invalid; an anonymous struct may "
+ "only have public non-static data members", elt))
{
- hint = true;
- inform (DECL_SOURCE_LOCATION (elt),
- "this flexibility is deprecated and will be removed");
+ static bool hint;
+ if (flag_permissive && !hint)
+ {
+ hint = true;
+ inform (DECL_SOURCE_LOCATION (elt),
+ "this flexibility is deprecated and will be "
+ "removed");
+ }
}
}
}
@@ -3104,6 +3105,7 @@ one_inherited_ctor (tree ctor, tree t, tree using_decl)
one_inheriting_sig (t, ctor, new_parms, i);
if (parms == NULL_TREE)
{
+ auto_diagnostic_group d;
if (warning (OPT_Winherited_variadic_ctor,
"the ellipsis in %qD is not inherited", ctor))
inform (DECL_SOURCE_LOCATION (ctor), "%qD declared here", ctor);
@@ -5396,11 +5398,14 @@ finalize_literal_type_property (tree t)
&& !DECL_CONSTRUCTOR_P (fn))
{
DECL_DECLARED_CONSTEXPR_P (fn) = false;
- if (!DECL_GENERATED_P (fn)
- && pedwarn (DECL_SOURCE_LOCATION (fn), OPT_Wpedantic,
- "enclosing class of %<constexpr%> non-static member "
- "function %q+#D is not a literal type", fn))
- explain_non_literal_class (t);
+ if (!DECL_GENERATED_P (fn))
+ {
+ auto_diagnostic_group d;
+ if (pedwarn (DECL_SOURCE_LOCATION (fn), OPT_Wpedantic,
+ "enclosing class of %<constexpr%> non-static "
+ "member function %q+#D is not a literal type", fn))
+ explain_non_literal_class (t);
+ }
}
}
@@ -5422,6 +5427,7 @@ explain_non_literal_class (tree t)
/* Already explained. */
return;
+ auto_diagnostic_group d;
inform (UNKNOWN_LOCATION, "%q+T is not literal because:", t);
if (cxx_dialect < cxx17 && LAMBDA_TYPE_P (t))
inform (UNKNOWN_LOCATION,
@@ -5571,7 +5577,9 @@ check_bases_and_members (tree t)
Again, other conditions for being an aggregate are checked
elsewhere. */
CLASSTYPE_NON_AGGREGATE (t)
- |= (type_has_user_provided_or_explicit_constructor (t)
+ |= ((cxx_dialect < cxx2a
+ ? type_has_user_provided_or_explicit_constructor (t)
+ : TYPE_HAS_USER_CONSTRUCTOR (t))
|| TYPE_POLYMORPHIC_P (t));
/* This is the C++98/03 definition of POD; it changed in C++0x, but we
retain the old definition internally for ABI reasons. */
@@ -6277,6 +6285,7 @@ layout_class_type (tree t, tree *virtuals_p)
bitsize_int (BITS_PER_UNIT)));
SET_TYPE_ALIGN (base_t, rli->record_align);
TYPE_USER_ALIGN (base_t) = TYPE_USER_ALIGN (t);
+ TYPE_TYPELESS_STORAGE (base_t) = TYPE_TYPELESS_STORAGE (t);
/* Copy the non-static data members of T. This will include its
direct non-virtual bases & vtable. */
@@ -6620,17 +6629,20 @@ find_flexarrays (tree t, flexmems_t *fmem, bool base_p,
static void
diagnose_invalid_flexarray (const flexmems_t *fmem)
{
- if (fmem->array && fmem->enclosing
- && pedwarn (location_of (fmem->enclosing), OPT_Wpedantic,
- TYPE_DOMAIN (TREE_TYPE (fmem->array))
- ? G_("invalid use of %q#T with a zero-size array "
- "in %q#D")
- : G_("invalid use of %q#T with a flexible array member "
- "in %q#T"),
- DECL_CONTEXT (fmem->array),
- DECL_CONTEXT (fmem->enclosing)))
- inform (DECL_SOURCE_LOCATION (fmem->array),
- "array member %q#D declared here", fmem->array);
+ if (fmem->array && fmem->enclosing)
+ {
+ auto_diagnostic_group d;
+ if (pedwarn (location_of (fmem->enclosing), OPT_Wpedantic,
+ TYPE_DOMAIN (TREE_TYPE (fmem->array))
+ ? G_("invalid use of %q#T with a zero-size array "
+ "in %q#D")
+ : G_("invalid use of %q#T with a flexible array member "
+ "in %q#T"),
+ DECL_CONTEXT (fmem->array),
+ DECL_CONTEXT (fmem->enclosing)))
+ inform (DECL_SOURCE_LOCATION (fmem->array),
+ "array member %q#D declared here", fmem->array);
+ }
}
/* Issue diagnostics for invalid flexible array members or zero-length
@@ -6665,6 +6677,7 @@ diagnose_flexarrays (tree t, const flexmems_t *fmem)
{
location_t loc = DECL_SOURCE_LOCATION (fmem->array);
+ auto_diagnostic_group d;
if (pedwarn (loc, OPT_Wpedantic, msg, fmem->array, t))
{
inform (location_of (t), "in the definition of %q#T", t);
@@ -6684,6 +6697,7 @@ diagnose_flexarrays (tree t, const flexmems_t *fmem)
location_t loc = DECL_SOURCE_LOCATION (fmem->array);
diagd = true;
+ auto_diagnostic_group d;
error_at (loc, msg, fmem->array, t);
/* In the unlikely event that the member following the flexible
@@ -7917,6 +7931,7 @@ resolve_address_of_overloaded_function (tree target_type,
if (!(complain & tf_error))
return error_mark_node;
+ auto_diagnostic_group d;
if (permerror (input_location, "assuming pointer to member %qD", fn)
&& !explained)
{
@@ -8283,7 +8298,7 @@ note_name_declared_in_class (tree name, tree decl)
A name N used in a class S shall refer to the same declaration
in its context and when re-evaluated in the completed scope of
S. */
- if (permerror (DECL_SOURCE_LOCATION (decl),
+ if (permerror (location_of (decl),
"declaration of %q#D changes meaning of %qD",
decl, OVL_NAME (decl)))
inform (location_of ((tree) n->value),
@@ -9251,6 +9266,7 @@ build_vtbl_initializer (tree binfo,
tree vcall_index;
tree fn, fn_original;
tree init = NULL_TREE;
+ tree idx = size_int (jx++);
fn = BV_FN (v);
fn_original = fn;
@@ -9354,7 +9370,7 @@ build_vtbl_initializer (tree binfo,
int i;
if (init == size_zero_node)
for (i = 0; i < TARGET_VTABLE_USES_DESCRIPTORS; ++i)
- CONSTRUCTOR_APPEND_ELT (*inits, NULL_TREE, init);
+ CONSTRUCTOR_APPEND_ELT (*inits, idx, init);
else
for (i = 0; i < TARGET_VTABLE_USES_DESCRIPTORS; ++i)
{
@@ -9362,11 +9378,11 @@ build_vtbl_initializer (tree binfo,
fn, build_int_cst (NULL_TREE, i));
TREE_CONSTANT (fdesc) = 1;
- CONSTRUCTOR_APPEND_ELT (*inits, NULL_TREE, fdesc);
+ CONSTRUCTOR_APPEND_ELT (*inits, idx, fdesc);
}
}
else
- CONSTRUCTOR_APPEND_ELT (*inits, NULL_TREE, init);
+ CONSTRUCTOR_APPEND_ELT (*inits, idx, init);
}
}
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 365296d..08d00e8 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -97,6 +97,7 @@ ensure_literal_type_for_constexpr_object (tree decl)
{
if (DECL_DECLARED_CONSTEXPR_P (decl))
{
+ auto_diagnostic_group d;
error ("the type %qT of %<constexpr%> variable %qD "
"is not literal", type, decl);
explain_non_literal_class (type);
@@ -106,6 +107,7 @@ ensure_literal_type_for_constexpr_object (tree decl)
{
if (!is_instantiation_of_constexpr (current_function_decl))
{
+ auto_diagnostic_group d;
error ("variable %qD of non-literal type %qT in %<constexpr%> "
"function", decl, type);
explain_non_literal_class (type);
@@ -200,6 +202,7 @@ is_valid_constexpr_fn (tree fun, bool complain)
ret = false;
if (complain)
{
+ auto_diagnostic_group d;
error ("invalid type for parameter %d of %<constexpr%> "
"function %q+#D", DECL_PARM_INDEX (parm), fun);
explain_non_literal_class (TREE_TYPE (parm));
@@ -222,6 +225,7 @@ is_valid_constexpr_fn (tree fun, bool complain)
ret = false;
if (complain)
{
+ auto_diagnostic_group d;
error ("invalid return type %qT of %<constexpr%> function %q+D",
rettype, fun);
explain_non_literal_class (rettype);
@@ -234,11 +238,15 @@ is_valid_constexpr_fn (tree fun, bool complain)
&& !CLASSTYPE_LITERAL_P (DECL_CONTEXT (fun)))
{
ret = false;
- if (complain
- && pedwarn (DECL_SOURCE_LOCATION (fun), OPT_Wpedantic,
- "enclosing class of %<constexpr%> non-static member "
- "function %q+#D is not a literal type", fun))
- explain_non_literal_class (DECL_CONTEXT (fun));
+ if (complain)
+ {
+ auto_diagnostic_group d;
+ if (pedwarn (DECL_SOURCE_LOCATION (fun), OPT_Wpedantic,
+ "enclosing class of %<constexpr%> non-static"
+ " member function %q+#D is not a literal type",
+ fun))
+ explain_non_literal_class (DECL_CONTEXT (fun));
+ }
}
}
else if (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fun)))
@@ -713,7 +721,7 @@ constexpr_fn_retval (tree body)
{
tree fun = get_function_named_in_call (body);
if (fun != NULL_TREE
- && DECL_FUNCTION_CODE (fun) == BUILT_IN_UNREACHABLE)
+ && fndecl_built_in_p (fun, BUILT_IN_UNREACHABLE))
return NULL_TREE;
}
/* Fallthru. */
@@ -817,6 +825,7 @@ cx_check_missing_mem_inits (tree ctype, tree body, bool complain)
}
if (!complain)
return true;
+ auto_diagnostic_group d;
error ("member %qD must be initialized by mem-initializer "
"in %<constexpr%> constructor", field);
inform (DECL_SOURCE_LOCATION (field), "declared here");
@@ -1007,6 +1016,8 @@ struct constexpr_ctx {
/* Whether we are strictly conforming to constant expression rules or
trying harder to get a constant value. */
bool strict;
+ /* Whether __builtin_is_constant_evaluated () should be true. */
+ bool pretend_const_required;
};
/* A table of all constexpr calls that have been evaluated by the
@@ -1171,7 +1182,7 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
int i;
/* Don't fold __builtin_constant_p within a constexpr function. */
- bool bi_const_p = (DECL_FUNCTION_CODE (fun) == BUILT_IN_CONSTANT_P);
+ bool bi_const_p = DECL_IS_BUILTIN_CONSTANT_P (fun);
/* If we aren't requiring a constant expression, defer __builtin_constant_p
in a constexpr function until we have values for the parameters. */
@@ -1184,6 +1195,19 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
return t;
}
+ /* For __builtin_is_constant_evaluated, defer it if not
+ ctx->pretend_const_required, otherwise fold it to true. */
+ if (fndecl_built_in_p (fun, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
+ BUILT_IN_FRONTEND))
+ {
+ if (!ctx->pretend_const_required)
+ {
+ *non_constant_p = true;
+ return t;
+ }
+ return boolean_true_node;
+ }
+
/* Be permissive for arguments to built-ins; __builtin_constant_p should
return constant false for a non-constant argument. */
constexpr_ctx new_ctx = *ctx;
@@ -1217,7 +1241,7 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
/* Do not allow__builtin_unreachable in constexpr function.
The __builtin_unreachable call with BUILTINS_LOCATION
comes from cp_maybe_instrument_return. */
- if (DECL_FUNCTION_CODE (fun) == BUILT_IN_UNREACHABLE
+ if (fndecl_built_in_p (fun, BUILT_IN_UNREACHABLE)
&& EXPR_LOCATION (t) == BUILTINS_LOCATION)
error ("%<constexpr%> call flows off the end of the function");
else
@@ -1502,7 +1526,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
if (is_ubsan_builtin_p (fun))
return void_node;
- if (is_builtin_fn (fun))
+ if (fndecl_built_in_p (fun))
return cxx_eval_builtin_function_call (ctx, t, fun,
lval, non_constant_p, overflow_p);
if (!DECL_DECLARED_CONSTEXPR_P (fun))
@@ -1645,7 +1669,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
{
if (!ctx->quiet)
error ("%<constexpr%> evaluation depth exceeds maximum of %d (use "
- "-fconstexpr-depth= to increase the maximum)",
+ "%<-fconstexpr-depth=%> to increase the maximum)",
max_constexpr_depth);
*non_constant_p = true;
result = error_mark_node;
@@ -2082,6 +2106,7 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t,
{
if (!ctx->quiet)
error ("arithmetic involving a null pointer in %qE", lhs);
+ *non_constant_p = true;
return t;
}
else if (code == POINTER_PLUS_EXPR)
@@ -2522,9 +2547,13 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t,
lval,
non_constant_p, overflow_p);
if (INDIRECT_REF_P (whole)
- && integer_zerop (TREE_OPERAND (whole, 0))
- && !ctx->quiet)
- error ("dereferencing a null pointer in %qE", orig_whole);
+ && integer_zerop (TREE_OPERAND (whole, 0)))
+ {
+ if (!ctx->quiet)
+ error ("dereferencing a null pointer in %qE", orig_whole);
+ *non_constant_p = true;
+ return t;
+ }
if (TREE_CODE (whole) == PTRMEM_CST)
whole = cplus_expand_constant (whole);
@@ -3005,6 +3034,9 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
{
/* Initializing an element using value or default initialization
we just pre-built above. */
+ if (init == void_node)
+ /* Trivial default-init, don't do anything to the CONSTRUCTOR. */
+ return ctx->ctor;
eltinit = cxx_eval_constant_expression (&new_ctx, init, lval,
non_constant_p, overflow_p);
reuse = i == 0;
@@ -3864,6 +3896,7 @@ breaks (tree *jump_target)
return *jump_target
&& ((TREE_CODE (*jump_target) == LABEL_DECL
&& LABEL_DECL_BREAK (*jump_target))
+ || TREE_CODE (*jump_target) == BREAK_STMT
|| TREE_CODE (*jump_target) == EXIT_EXPR);
}
@@ -3871,8 +3904,10 @@ static bool
continues (tree *jump_target)
{
return *jump_target
- && TREE_CODE (*jump_target) == LABEL_DECL
- && LABEL_DECL_CONTINUE (*jump_target);
+ && ((TREE_CODE (*jump_target) == LABEL_DECL
+ && LABEL_DECL_CONTINUE (*jump_target))
+ || TREE_CODE (*jump_target) == CONTINUE_STMT);
+
}
static bool
@@ -3950,6 +3985,16 @@ cxx_eval_statement_list (const constexpr_ctx *ctx, tree t,
for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
{
tree stmt = tsi_stmt (i);
+ /* We've found a continue, so skip everything until we reach
+ the label its jumping to. */
+ if (continues (jump_target))
+ {
+ if (label_matches (ctx, jump_target, stmt))
+ /* Found it. */
+ *jump_target = NULL_TREE;
+ else
+ continue;
+ }
if (TREE_CODE (stmt) == DEBUG_BEGIN_STMT)
continue;
r = cxx_eval_constant_expression (ctx, stmt, false,
@@ -4084,7 +4129,7 @@ static tree
cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
bool lval,
bool *non_constant_p, bool *overflow_p,
- tree *jump_target)
+ tree *jump_target /* = NULL */)
{
constexpr_ctx new_ctx;
tree r = t;
@@ -4110,7 +4155,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
return NULL_TREE;
}
}
- if (t == error_mark_node)
+ if (error_operand_p (t))
{
*non_constant_p = true;
return t;
@@ -4167,7 +4212,11 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
CONST_DECL for aggregate constants. */
if (lval)
return t;
+ /* is_really_empty_class doesn't take into account _vptr, so initializing
+ otherwise empty class with { } would overwrite the initializer that
+ initialize_vtable created for us. */
if (COMPLETE_TYPE_P (TREE_TYPE (t))
+ && !TYPE_POLYMORPHIC_P (TREE_TYPE (t))
&& is_really_empty_class (TREE_TYPE (t)))
{
/* If the class is empty, we aren't actually loading anything. */
@@ -4271,6 +4320,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
{
if (!ctx->quiet)
{
+ auto_diagnostic_group d;
error ("temporary of non-literal type %qT in a "
"constant expression", TREE_TYPE (t));
explain_non_literal_class (TREE_TYPE (t));
@@ -4735,7 +4785,6 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
case MODOP_EXPR:
/* GCC internal stuff. */
case VA_ARG_EXPR:
- case OBJ_TYPE_REF:
case NON_DEPENDENT_EXPR:
case BASELINK:
case OFFSET_REF:
@@ -4745,6 +4794,34 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
*non_constant_p = true;
break;
+ case OBJ_TYPE_REF:
+ {
+ /* Virtual function call. Let the constexpr machinery figure out
+ the dynamic type. */
+ int token = tree_to_shwi (OBJ_TYPE_REF_TOKEN (t));
+ tree obj = OBJ_TYPE_REF_OBJECT (t);
+ obj = cxx_eval_constant_expression (ctx, obj, lval, non_constant_p,
+ overflow_p);
+ /* We expect something in the form of &x.D.2103.D.2094; get x. */
+ if (TREE_CODE (obj) != ADDR_EXPR)
+ {
+ if (!ctx->quiet)
+ error_at (cp_expr_loc_or_loc (t, input_location),
+ "expression %qE is not a constant expression", t);
+ *non_constant_p = true;
+ return t;
+ }
+ obj = TREE_OPERAND (obj, 0);
+ while (handled_component_p (obj))
+ obj = TREE_OPERAND (obj, 0);
+ tree objtype = TREE_TYPE (obj);
+ /* Find the function decl in the virtual functions list. TOKEN is
+ the DECL_VINDEX that says which function we're looking for. */
+ tree virtuals = BINFO_VIRTUALS (TYPE_BINFO (objtype));
+ r = TREE_VALUE (chain_index (token, virtuals));
+ break;
+ }
+
case PLACEHOLDER_EXPR:
/* Use of the value or address of the current object. */
if (tree ctor = lookup_placeholder (ctx, lval, TREE_TYPE (t)))
@@ -4882,9 +4959,18 @@ instantiate_constexpr_fns (tree t)
input_location = loc;
}
+/* ALLOW_NON_CONSTANT is false if T is required to be a constant expression.
+ STRICT has the same sense as for constant_value_1: true if we only allow
+ conforming C++ constant expressions, or false if we want a constant value
+ even if it doesn't conform.
+ PRETEND_CONST_REQUIRED is true if T is required to be const-evaluated as
+ per P0595 even when ALLOW_NON_CONSTANT is true. */
+
static tree
cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
- bool strict = true, tree object = NULL_TREE)
+ bool strict = true,
+ bool pretend_const_required = false,
+ tree object = NULL_TREE)
{
auto_timevar time (TV_CONSTEXPR);
@@ -4893,7 +4979,8 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
hash_map<tree,tree> map;
constexpr_ctx ctx = { NULL, &map, NULL, NULL, NULL, NULL,
- allow_non_constant, strict };
+ allow_non_constant, strict,
+ pretend_const_required || !allow_non_constant };
tree type = initialized_type (t);
tree r = t;
@@ -4982,6 +5069,12 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
return error_mark_node;
else if (non_constant_p && TREE_CONSTANT (r))
{
+ /* If __builtin_is_constant_evaluated () was evaluated to true
+ and the result is not a valid constant expression, we need to
+ punt. */
+ if (pretend_const_required)
+ return cxx_eval_outermost_constant_expr (t, true, strict,
+ false, object);
/* This isn't actually constant, so unset TREE_CONSTANT.
Don't clear TREE_CONSTANT on ADDR_EXPR, as the middle-end requires
it to be set if it is invariant address, even when it is not
@@ -5027,7 +5120,8 @@ is_sub_constant_expr (tree t)
bool overflow_p = false;
hash_map <tree, tree> map;
- constexpr_ctx ctx = { NULL, &map, NULL, NULL, NULL, NULL, true, true };
+ constexpr_ctx ctx
+ = { NULL, &map, NULL, NULL, NULL, NULL, true, true, false };
instantiate_constexpr_fns (t);
cxx_eval_constant_expression (&ctx, t, false, &non_constant_p,
@@ -5042,7 +5136,7 @@ is_sub_constant_expr (tree t)
tree
cxx_constant_value (tree t, tree decl)
{
- return cxx_eval_outermost_constant_expr (t, false, true, decl);
+ return cxx_eval_outermost_constant_expr (t, false, true, true, decl);
}
/* Helper routine for fold_simple function. Either return simplified
@@ -5148,7 +5242,7 @@ maybe_constant_value (tree t, tree decl)
if (tree *cached = cv_cache->get (t))
return *cached;
- r = cxx_eval_outermost_constant_expr (t, true, true, decl);
+ r = cxx_eval_outermost_constant_expr (t, true, true, false, decl);
gcc_checking_assert (r == t
|| CONVERT_EXPR_P (t)
|| TREE_CODE (t) == VIEW_CONVERT_EXPR
@@ -5222,7 +5316,8 @@ fold_non_dependent_expr (tree t,
return t;
}
- tree r = cxx_eval_outermost_constant_expr (t, true, true, NULL_TREE);
+ tree r = cxx_eval_outermost_constant_expr (t, true, true, false,
+ NULL_TREE);
/* cp_tree_equal looks through NOPs, so allow them. */
gcc_checking_assert (r == t
|| CONVERT_EXPR_P (t)
@@ -5243,10 +5338,14 @@ fold_non_dependent_expr (tree t,
}
/* Like maybe_constant_value, but returns a CONSTRUCTOR directly, rather
- than wrapped in a TARGET_EXPR. */
+ than wrapped in a TARGET_EXPR.
+ ALLOW_NON_CONSTANT is false if T is required to be a constant expression.
+ PRETEND_CONST_REQUIRED is true if T is required to be const-evaluated as
+ per P0595 even when ALLOW_NON_CONSTANT is true. */
static tree
-maybe_constant_init_1 (tree t, tree decl, bool allow_non_constant)
+maybe_constant_init_1 (tree t, tree decl, bool allow_non_constant,
+ bool pretend_const_required)
{
if (!t)
return t;
@@ -5264,7 +5363,9 @@ maybe_constant_init_1 (tree t, tree decl, bool allow_non_constant)
else if (CONSTANT_CLASS_P (t) && allow_non_constant)
/* No evaluation needed. */;
else
- t = cxx_eval_outermost_constant_expr (t, allow_non_constant, false, decl);
+ t = cxx_eval_outermost_constant_expr (t, allow_non_constant,
+ /*strict*/false,
+ pretend_const_required, decl);
if (TREE_CODE (t) == TARGET_EXPR)
{
tree init = TARGET_EXPR_INITIAL (t);
@@ -5277,9 +5378,9 @@ maybe_constant_init_1 (tree t, tree decl, bool allow_non_constant)
/* Wrapper for maybe_constant_init_1 which permits non constants. */
tree
-maybe_constant_init (tree t, tree decl)
+maybe_constant_init (tree t, tree decl, bool pretend_const_required)
{
- return maybe_constant_init_1 (t, decl, true);
+ return maybe_constant_init_1 (t, decl, true, pretend_const_required);
}
/* Wrapper for maybe_constant_init_1 which does not permit non constants. */
@@ -5287,7 +5388,7 @@ maybe_constant_init (tree t, tree decl)
tree
cxx_constant_init (tree t, tree decl)
{
- return maybe_constant_init_1 (t, decl, false);
+ return maybe_constant_init_1 (t, decl, false, true);
}
#if 0
@@ -5337,10 +5438,10 @@ check_automatic_or_tls (tree ref)
static bool
potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
- tsubst_flags_t flags)
+ tsubst_flags_t flags, tree *jump_target)
{
#define RECUR(T,RV) \
- potential_constant_expression_1 ((T), (RV), strict, now, flags)
+ potential_constant_expression_1 ((T), (RV), strict, now, flags, jump_target)
enum { any = false, rval = true };
int i;
@@ -5351,6 +5452,14 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
if (t == NULL_TREE)
return true;
location_t loc = cp_expr_loc_or_loc (t, input_location);
+
+ if (*jump_target)
+ /* If we are jumping, ignore everything. This is simpler than the
+ cxx_eval_constant_expression handling because we only need to be
+ conservatively correct, and we don't necessarily have a constant value
+ available, so we don't bother with switch tracking. */
+ return true;
+
if (TREE_THIS_VOLATILE (t) && !DECL_P (t))
{
if (flags & tf_error)
@@ -5388,13 +5497,21 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case USING_DECL:
case USING_STMT:
case PLACEHOLDER_EXPR:
- case BREAK_STMT:
- case CONTINUE_STMT:
case REQUIRES_EXPR:
case STATIC_ASSERT:
case DEBUG_BEGIN_STMT:
return true;
+ case RETURN_EXPR:
+ if (!RECUR (TREE_OPERAND (t, 0), any))
+ return false;
+ /* FALLTHROUGH */
+
+ case BREAK_STMT:
+ case CONTINUE_STMT:
+ *jump_target = t;
+ return true;
+
case PARM_DECL:
if (now)
{
@@ -5459,7 +5576,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
if (!DECL_DECLARED_CONSTEXPR_P (fun)
/* Allow any built-in function; if the expansion
isn't constant, we'll deal with that then. */
- && !is_builtin_fn (fun))
+ && !fndecl_built_in_p (fun))
{
if (flags & tf_error)
{
@@ -5483,7 +5600,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
constexpr substitution might not use the value. */
bool sub_now = false;
if (!potential_constant_expression_1 (x, rval, strict,
- sub_now, flags))
+ sub_now, flags,
+ jump_target))
return false;
i = 1;
}
@@ -5517,7 +5635,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
substitution might not use the value of the argument. */
bool sub_now = false;
if (!potential_constant_expression_1 (x, rv, strict,
- sub_now, flags))
+ sub_now, flags, jump_target))
return false;
}
return true;
@@ -5692,6 +5810,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
return false;
if (!RECUR (DO_BODY (t), any))
return false;
+ if (breaks (jump_target) || continues (jump_target))
+ *jump_target = NULL_TREE;
return true;
case FOR_STMT:
@@ -5703,13 +5823,19 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
return false;
if (!RECUR (FOR_BODY (t), any))
return false;
+ if (breaks (jump_target) || continues (jump_target))
+ *jump_target = NULL_TREE;
return true;
case RANGE_FOR_STMT:
+ if (!RECUR (RANGE_FOR_INIT_STMT (t), any))
+ return false;
if (!RECUR (RANGE_FOR_EXPR (t), any))
return false;
if (!RECUR (RANGE_FOR_BODY (t), any))
return false;
+ if (breaks (jump_target) || continues (jump_target))
+ *jump_target = NULL_TREE;
return true;
case WHILE_STMT:
@@ -5717,6 +5843,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
return false;
if (!RECUR (WHILE_BODY (t), any))
return false;
+ if (breaks (jump_target) || continues (jump_target))
+ *jump_target = NULL_TREE;
return true;
case SWITCH_STMT:
@@ -5780,7 +5908,6 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case OACC_UPDATE:
/* GCC internal stuff. */
case VA_ARG_EXPR:
- case OBJ_TYPE_REF:
case TRANSACTION_EXPR:
case ASM_EXPR:
case AT_ENCODE_EXPR:
@@ -5789,6 +5916,14 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
error_at (loc, "expression %qE is not a constant expression", t);
return false;
+ case OBJ_TYPE_REF:
+ if (cxx_dialect >= cxx2a)
+ /* In C++2a virtual calls can be constexpr, don't give up yet. */
+ return true;
+ else if (flags & tf_error)
+ error_at (loc, "virtual functions cannot be constexpr before C++2a");
+ return false;
+
case TYPEID_EXPR:
/* -- a typeid expression whose operand is of polymorphic
class type; */
@@ -5900,7 +6035,6 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case PAREN_EXPR:
case NON_DEPENDENT_EXPR:
/* For convenience. */
- case RETURN_EXPR:
case LOOP_EXPR:
case EXIT_EXPR:
return RECUR (TREE_OPERAND (t, 0), want_rval);
@@ -5942,6 +6076,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
{
if (flags & tf_error)
{
+ auto_diagnostic_group d;
error_at (loc, "temporary of non-literal type %qT in a "
"constant expression", TREE_TYPE (t));
explain_non_literal_class (TREE_TYPE (t));
@@ -6109,7 +6244,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
return RECUR (TREE_OPERAND (t, 1), want_rval);
for (i = 1; i < 3; ++i)
if (potential_constant_expression_1 (TREE_OPERAND (t, i),
- want_rval, strict, now, tf_none))
+ want_rval, strict, now,
+ tf_none, jump_target))
return true;
if (flags & tf_error)
error_at (loc, "expression %qE is not a constant expression", t);
@@ -6140,7 +6276,10 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
tree *target = &TREE_OPERAND (t, 0);
/* Gotos representing break and continue are OK. */
if (breaks (target) || continues (target))
- return true;
+ {
+ *jump_target = *target;
+ return true;
+ }
if (flags & tf_error)
error_at (loc, "%<goto%> is not a constant expression");
return false;
@@ -6160,6 +6299,15 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
#undef RECUR
}
+bool
+potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
+ tsubst_flags_t flags)
+{
+ tree target = NULL_TREE;
+ return potential_constant_expression_1 (t, want_rval, strict, now,
+ flags, &target);
+}
+
/* The main entry point to the above. */
bool
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 9f9fb52..7b32355 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -1259,6 +1259,9 @@ finish_shorthand_constraint (tree decl, tree constr)
if (!constr)
return NULL_TREE;
+ if (error_operand_p (constr))
+ return NULL_TREE;
+
tree proto = CONSTRAINED_PARM_PROTOTYPE (constr);
tree con = CONSTRAINED_PARM_CONCEPT (constr);
tree args = CONSTRAINED_PARM_EXTRA_ARGS (constr);
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 28802b5..90a8f9f 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -793,6 +793,14 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
ret = GS_ERROR;
}
}
+ if (ret != GS_ERROR)
+ {
+ tree decl = cp_get_callee_fndecl_nofold (*expr_p);
+ if (decl
+ && fndecl_built_in_p (decl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
+ BUILT_IN_FRONTEND))
+ *expr_p = boolean_false_node;
+ }
break;
case RETURN_EXPR:
@@ -1411,12 +1419,15 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
/* Never mind. */;
else if (wtd->try_block)
{
- if (TREE_CODE (wtd->try_block) == MUST_NOT_THROW_EXPR
- && warning_at (loc, OPT_Wterminate,
- "throw will always call terminate()")
- && cxx_dialect >= cxx11
- && DECL_DESTRUCTOR_P (current_function_decl))
- inform (loc, "in C++11 destructors default to noexcept");
+ if (TREE_CODE (wtd->try_block) == MUST_NOT_THROW_EXPR)
+ {
+ auto_diagnostic_group d;
+ if (warning_at (loc, OPT_Wterminate,
+ "throw will always call terminate()")
+ && cxx_dialect >= cxx11
+ && DECL_DESTRUCTOR_P (current_function_decl))
+ inform (loc, "in C++11 destructors default to noexcept");
+ }
}
else
{
@@ -2477,12 +2488,18 @@ cp_fold (tree x)
/* Some built-in function calls will be evaluated at compile-time in
fold (). Set optimize to 1 when folding __builtin_constant_p inside
a constexpr function so that fold_builtin_1 doesn't fold it to 0. */
- if (callee && DECL_BUILT_IN (callee) && !optimize
+ if (callee && fndecl_built_in_p (callee) && !optimize
&& DECL_IS_BUILTIN_CONSTANT_P (callee)
&& current_function_decl
&& DECL_DECLARED_CONSTEXPR_P (current_function_decl))
nw = 1;
+ /* Defer folding __builtin_is_constant_evaluated. */
+ if (callee
+ && fndecl_built_in_p (callee, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
+ BUILT_IN_FRONTEND))
+ break;
+
x = copy_node (x);
m = call_expr_nargs (x);
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index 1b0326f..c64225d 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -301,9 +301,10 @@ DEFTREECODE (IF_STMT, "if_stmt", tcc_statement, 4)
DEFTREECODE (FOR_STMT, "for_stmt", tcc_statement, 5)
/* Used to represent a range-based `for' statement. The operands are
- RANGE_FOR_DECL, RANGE_FOR_EXPR, RANGE_FOR_BODY, and RANGE_FOR_SCOPE,
- RANGE_FOR_UNROLL respectively. Only used in templates. */
-DEFTREECODE (RANGE_FOR_STMT, "range_for_stmt", tcc_statement, 5)
+ RANGE_FOR_DECL, RANGE_FOR_EXPR, RANGE_FOR_BODY, RANGE_FOR_SCOPE,
+ RANGE_FOR_UNROLL, and RANGE_FOR_INIT_STMT, respectively. Only used in
+ templates. */
+DEFTREECODE (RANGE_FOR_STMT, "range_for_stmt", tcc_statement, 6)
/* Used to represent a 'while' statement. The operands are WHILE_COND
and WHILE_BODY, respectively. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d225702..efbdad8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1877,6 +1877,8 @@ struct GTY(()) language_function {
/* In parser.c. */
extern tree cp_literal_operator_id (const char *);
+#define NON_ERROR(NODE) ((NODE) == error_mark_node ? NULL_TREE : (NODE))
+
/* TRUE if a tree code represents a statement. */
extern bool statement_code_p[MAX_TREE_CODES];
@@ -3656,7 +3658,7 @@ struct GTY(()) lang_decl {
(LANG_DECL_FN_CHECK (FUNCTION_DECL_CHECK (NODE)) \
->u.saved_language_function)
-/* True if NODE is an implicit INDIRECT_EXPR from convert_from_reference. */
+/* True if NODE is an implicit INDIRECT_REF from convert_from_reference. */
#define REFERENCE_REF_P(NODE) \
(INDIRECT_REF_P (NODE) \
&& TREE_TYPE (TREE_OPERAND (NODE, 0)) \
@@ -4923,6 +4925,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define RANGE_FOR_BODY(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 2)
#define RANGE_FOR_SCOPE(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 3)
#define RANGE_FOR_UNROLL(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 4)
+#define RANGE_FOR_INIT_STMT(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 5)
#define RANGE_FOR_IVDEP(NODE) TREE_LANG_FLAG_6 (RANGE_FOR_STMT_CHECK (NODE))
#define SWITCH_STMT_COND(NODE) TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 0)
@@ -5966,6 +5969,13 @@ struct GTY((chain_next ("%h.next"))) tinst_level {
static const unsigned short refcount_infinity = (unsigned short) ~0;
};
+/* BUILT_IN_FRONTEND function codes. */
+enum cp_built_in_function {
+ CP_BUILT_IN_IS_CONSTANT_EVALUATED,
+ CP_BUILT_IN_INTEGER_PACK,
+ CP_BUILT_IN_LAST
+};
+
bool decl_spec_seq_has_spec_p (const cp_decl_specifier_seq *, cp_decl_spec);
/* Return the type of the `this' parameter of FNTYPE. */
@@ -6080,6 +6090,9 @@ extern bool can_convert_arg_bad (tree, tree, tree, int,
extern int conv_flags (int, int, tree, tree, int);
extern struct conversion * good_conversion (tree, tree, tree, int, tsubst_flags_t);
extern location_t get_fndecl_argument_location (tree, int);
+extern void complain_about_bad_argument (location_t arg_loc,
+ tree from_type, tree to_type,
+ tree fndecl, int parmnum);
/* A class for recording information about access failures (e.g. private
@@ -6448,7 +6461,7 @@ extern void perform_deferred_noexcept_checks (void);
extern bool nothrow_spec_p (const_tree);
extern bool type_noexcept_p (const_tree);
extern bool type_throw_all_p (const_tree);
-extern tree build_noexcept_spec (tree, int);
+extern tree build_noexcept_spec (tree, tsubst_flags_t);
extern void choose_personality_routine (enum languages);
extern tree build_must_not_throw_expr (tree,tree);
extern tree eh_type_info (tree);
@@ -7347,6 +7360,7 @@ extern tree cp_perform_integral_promotions (tree, tsubst_flags_t);
extern tree finish_left_unary_fold_expr (tree, int);
extern tree finish_right_unary_fold_expr (tree, int);
extern tree finish_binary_fold_expr (tree, tree, int);
+extern bool treat_lvalue_as_rvalue_p (tree, bool);
/* in typeck2.c */
extern void require_complete_eh_spec_types (tree, tree);
@@ -7381,7 +7395,8 @@ cxx_incomplete_type_error (const_tree value, const_tree type)
extern void cxx_incomplete_type_inform (const_tree);
extern tree error_not_base_type (tree, tree);
extern tree binfo_or_else (tree, tree);
-extern void cxx_readonly_error (tree, enum lvalue_use);
+extern void cxx_readonly_error (location_t, tree,
+ enum lvalue_use);
extern void complete_type_check_abstract (tree);
extern int abstract_virtuals_error (tree, tree);
extern int abstract_virtuals_error (abstract_class_use, tree);
@@ -7390,7 +7405,8 @@ extern int abstract_virtuals_error_sfinae (abstract_class_use, tree, tsubst_flag
extern tree store_init_value (tree, tree, vec<tree, va_gc>**, int);
extern tree split_nonconstant_init (tree, tree);
-extern bool check_narrowing (tree, tree, tsubst_flags_t);
+extern bool check_narrowing (tree, tree, tsubst_flags_t,
+ bool = false);
extern tree digest_init (tree, tree, tsubst_flags_t);
extern tree digest_init_flags (tree, tree, int, tsubst_flags_t);
extern tree digest_nsdmi_init (tree, tree, tsubst_flags_t);
@@ -7399,7 +7415,7 @@ extern tree build_x_arrow (location_t, tree,
tsubst_flags_t);
extern tree build_m_component_ref (tree, tree, tsubst_flags_t);
extern tree build_functional_cast (tree, tree, tsubst_flags_t);
-extern tree add_exception_specifier (tree, tree, int);
+extern tree add_exception_specifier (tree, tree, tsubst_flags_t);
extern tree merge_exception_specifiers (tree, tree);
/* in mangle.c */
@@ -7572,7 +7588,7 @@ extern bool require_potential_rvalue_constant_expression (tree);
extern tree cxx_constant_value (tree, tree = NULL_TREE);
extern tree cxx_constant_init (tree, tree = NULL_TREE);
extern tree maybe_constant_value (tree, tree = NULL_TREE);
-extern tree maybe_constant_init (tree, tree = NULL_TREE);
+extern tree maybe_constant_init (tree, tree = NULL_TREE, bool = false);
extern tree fold_non_dependent_expr (tree, tsubst_flags_t = tf_warning_or_error);
extern tree fold_simple (tree);
extern bool is_sub_constant_expr (tree);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index da98414..315b0d6 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -1017,6 +1017,7 @@ maybe_warn_nodiscard (tree expr, impl_conv_void implicit)
if (implicit != ICV_CAST && fn
&& lookup_attribute ("nodiscard", DECL_ATTRIBUTES (fn)))
{
+ auto_diagnostic_group d;
if (warning_at (loc, OPT_Wunused_result,
"ignoring return value of %qD, "
"declared with attribute nodiscard", fn))
@@ -1025,6 +1026,7 @@ maybe_warn_nodiscard (tree expr, impl_conv_void implicit)
else if (implicit != ICV_CAST
&& lookup_attribute ("nodiscard", TYPE_ATTRIBUTES (rettype)))
{
+ auto_diagnostic_group d;
if (warning_at (loc, OPT_Wunused_result,
"ignoring returned value of type %qT, "
"declared with attribute nodiscard", rettype))
@@ -1043,6 +1045,7 @@ maybe_warn_nodiscard (tree expr, impl_conv_void implicit)
result is used, so handle that case here. */
if (fn)
{
+ auto_diagnostic_group d;
if (warning_at (loc, OPT_Wunused_result,
"ignoring return value of %qD, "
"declared with attribute warn_unused_result",
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index df81aa3..8426c72 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -2021,6 +2021,12 @@ cxx_pretty_printer::statement (tree t)
pp_cxx_ws_string (this, "for");
pp_space (this);
pp_cxx_left_paren (this);
+ if (RANGE_FOR_INIT_STMT (t))
+ {
+ statement (RANGE_FOR_INIT_STMT (t));
+ pp_needs_newline (this) = false;
+ pp_cxx_whitespace (this);
+ }
statement (RANGE_FOR_DECL (t));
pp_space (this);
pp_needs_newline (this) = false;
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 1206ddb..2d9d56e 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimplify.h"
#include "asan.h"
#include "gcc-rich-location.h"
+#include "langhooks.h"
/* Possible cases of bad specifiers type used by bad_specifiers. */
enum bad_spec_place {
@@ -69,7 +70,7 @@ static void push_local_name (tree);
static tree grok_reference_init (tree, tree, tree, int);
static tree grokvardecl (tree, tree, tree, const cp_decl_specifier_seq *,
int, int, int, bool, int, tree);
-static int check_static_variable_definition (tree, tree);
+static void check_static_variable_definition (tree, tree);
static void record_unknown_type (tree, const char *);
static tree builtin_function_1 (tree, tree, bool);
static int member_function_or_else (tree, tree, enum overload_flags);
@@ -967,30 +968,12 @@ decls_match (tree newdecl, tree olddecl, bool record_versions /* = true */)
if (same_type_p (TREE_TYPE (f1), r2))
{
if (!prototype_p (f2) && DECL_EXTERN_C_P (olddecl)
- && (DECL_BUILT_IN (olddecl)
-#ifdef SYSTEM_IMPLICIT_EXTERN_C
- || (DECL_IN_SYSTEM_HEADER (newdecl) && !DECL_CLASS_SCOPE_P (newdecl))
- || (DECL_IN_SYSTEM_HEADER (olddecl) && !DECL_CLASS_SCOPE_P (olddecl))
-#endif
- ))
+ && fndecl_built_in_p (olddecl))
{
types_match = self_promoting_args_p (p1);
if (p1 == void_list_node)
TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
}
-#ifdef SYSTEM_IMPLICIT_EXTERN_C
- else if (!prototype_p (f1)
- && (DECL_EXTERN_C_P (olddecl)
- && DECL_IN_SYSTEM_HEADER (olddecl)
- && !DECL_CLASS_SCOPE_P (olddecl))
- && (DECL_EXTERN_C_P (newdecl)
- && DECL_IN_SYSTEM_HEADER (newdecl)
- && !DECL_CLASS_SCOPE_P (newdecl)))
- {
- types_match = self_promoting_args_p (p2);
- TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
- }
-#endif
else
types_match =
compparms (p1, p2)
@@ -1132,6 +1115,7 @@ warn_extern_redeclared_static (tree newdecl, tree olddecl)
&& DECL_ARTIFICIAL (olddecl))
return;
+ auto_diagnostic_group d;
if (permerror (DECL_SOURCE_LOCATION (newdecl),
"%qD was declared %<extern%> and later %<static%>", newdecl))
inform (DECL_SOURCE_LOCATION (olddecl),
@@ -1175,6 +1159,7 @@ check_redeclaration_exception_specification (tree new_decl,
= G_("declaration of %qF has a different exception specifier");
bool complained = true;
location_t new_loc = DECL_SOURCE_LOCATION (new_decl);
+ auto_diagnostic_group d;
if (DECL_IN_SYSTEM_HEADER (old_decl))
complained = pedwarn (new_loc, OPT_Wsystem_headers, msg, new_decl);
else if (!flag_exceptions)
@@ -1205,7 +1190,7 @@ validate_constexpr_redeclaration (tree old_decl, tree new_decl)
return true;
if (TREE_CODE (old_decl) == FUNCTION_DECL)
{
- if (DECL_BUILT_IN (old_decl))
+ if (fndecl_built_in_p (old_decl))
{
/* Hide a built-in declaration. */
DECL_DECLARED_CONSTEXPR_P (old_decl)
@@ -1280,6 +1265,39 @@ check_redeclaration_no_default_args (tree decl)
}
}
+/* NEWDECL is a redeclaration of a function or function template OLDDECL,
+ in any case represented as FUNCTION_DECLs (the DECL_TEMPLATE_RESULTs of
+ the TEMPLATE_DECLs in case of function templates). This function is used
+ to enforce the final part of C++17 11.3.6/4, about a single declaration:
+ "If a friend declaration specifies a default argument expression, that
+ declaration shall be a definition and shall be the only declaration of
+ the function or function template in the translation unit." */
+
+static void
+check_no_redeclaration_friend_default_args (tree olddecl, tree newdecl,
+ bool olddecl_hidden_friend_p)
+{
+ if (!olddecl_hidden_friend_p && !DECL_FRIEND_P (newdecl))
+ return;
+
+ tree t1 = FUNCTION_FIRST_USER_PARMTYPE (olddecl);
+ tree t2 = FUNCTION_FIRST_USER_PARMTYPE (newdecl);
+
+ for (; t1 && t1 != void_list_node;
+ t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
+ if ((olddecl_hidden_friend_p && TREE_PURPOSE (t1))
+ || (DECL_FRIEND_P (newdecl) && TREE_PURPOSE (t2)))
+ {
+ auto_diagnostic_group d;
+ if (permerror (DECL_SOURCE_LOCATION (newdecl),
+ "friend declaration of %q#D specifies default "
+ "arguments and isn't the only declaration", newdecl))
+ inform (DECL_SOURCE_LOCATION (olddecl),
+ "previous declaration of %q#D", olddecl);
+ return;
+ }
+}
+
/* Merge tree bits that correspond to attributes noreturn, nothrow,
const, malloc, and pure from NEWDECL with those of OLDDECL. */
@@ -1318,6 +1336,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
{
unsigned olddecl_uid = DECL_UID (olddecl);
int olddecl_friend = 0, types_match = 0, hidden_friend = 0;
+ int olddecl_hidden_friend = 0;
int new_defines_function = 0;
tree new_template_info;
location_t olddecl_loc = DECL_SOURCE_LOCATION (olddecl);
@@ -1405,7 +1424,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
{
warning_at (newdecl_loc,
OPT_Wshadow,
- DECL_BUILT_IN (olddecl)
+ fndecl_built_in_p (olddecl)
? G_("shadowing built-in function %q#D")
: G_("shadowing library function %q#D"), olddecl);
/* Discard the old built-in function. */
@@ -1413,7 +1432,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
}
/* If the built-in is not ansi, then programs can override
it even globally without an error. */
- else if (! DECL_BUILT_IN (olddecl))
+ else if (! fndecl_built_in_p (olddecl))
warning_at (newdecl_loc, 0,
"library function %q#D redeclared as non-function %q#D",
olddecl, newdecl);
@@ -1500,7 +1519,7 @@ next_arg:;
/* Don't really override olddecl for __* prefixed builtins
except for __[^b]*_chk, the compiler might be using those
explicitly. */
- if (DECL_BUILT_IN (olddecl))
+ if (fndecl_built_in_p (olddecl))
{
tree id = DECL_NAME (olddecl);
const char *name = IDENTIFIER_POINTER (id);
@@ -1521,6 +1540,7 @@ next_arg:;
"declaration %q#D", newdecl, olddecl);
return error_mark_node;
}
+ auto_diagnostic_group d;
if (permerror (newdecl_loc,
"new declaration %q#D ambiguates built-in"
" declaration %q#D", newdecl, olddecl)
@@ -1540,9 +1560,9 @@ next_arg:;
"declaration %q#D", newdecl, olddecl);
else
warning (OPT_Wshadow,
- DECL_BUILT_IN (olddecl)
- ? G_("shadowing built-in function %q#D")
- : G_("shadowing library function %q#D"), olddecl);
+ fndecl_built_in_p (olddecl)
+ ? G_("shadowing built-in function %q#D")
+ : G_("shadowing library function %q#D"), olddecl);
}
else
/* Discard the old built-in function. */
@@ -1767,6 +1787,7 @@ next_arg:;
const char *errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg)
{
+ auto_diagnostic_group d;
error_at (newdecl_loc, errmsg, newdecl);
if (DECL_NAME (olddecl) != NULL_TREE)
inform (olddecl_loc,
@@ -1781,6 +1802,7 @@ next_arg:;
&& prototype_p (TREE_TYPE (newdecl)))
{
/* Prototype decl follows defn w/o prototype. */
+ auto_diagnostic_group d;
if (warning_at (newdecl_loc, 0,
"prototype specified for %q#D", newdecl))
inform (olddecl_loc,
@@ -1822,6 +1844,7 @@ next_arg:;
}
else
{
+ auto_diagnostic_group d;
error_at (newdecl_loc,
"conflicting declaration of %q#D with %qL linkage",
newdecl, DECL_LANGUAGE (newdecl));
@@ -1859,6 +1882,7 @@ next_arg:;
if (simple_cst_equal (TREE_PURPOSE (t1),
TREE_PURPOSE (t2)) == 1)
{
+ auto_diagnostic_group d;
if (permerror (newdecl_loc,
"default argument given for parameter "
"%d of %q#D", i, newdecl))
@@ -1868,6 +1892,7 @@ next_arg:;
}
else
{
+ auto_diagnostic_group d;
error_at (newdecl_loc,
"default argument given for parameter %d "
"of %q#D", i, newdecl);
@@ -1876,6 +1901,13 @@ next_arg:;
olddecl);
}
}
+
+ /* C++17 11.3.6/4: "If a friend declaration specifies a default
+ argument expression, that declaration... shall be the only
+ declaration of the function or function template in the
+ translation unit." */
+ check_no_redeclaration_friend_default_args
+ (olddecl, newdecl, DECL_HIDDEN_FRIEND_P (olddecl));
}
}
}
@@ -1936,6 +1968,7 @@ next_arg:;
&& (! DECL_TEMPLATE_SPECIALIZATION (newdecl)
|| DECL_TEMPLATE_SPECIALIZATION (olddecl)))
{
+ auto_diagnostic_group d;
if (warning_at (newdecl_loc,
OPT_Wredundant_decls,
"redundant redeclaration of %qD in same scope",
@@ -1949,6 +1982,7 @@ next_arg:;
{
if (DECL_DELETED_FN (newdecl))
{
+ auto_diagnostic_group d;
error_at (newdecl_loc, "deleted definition of %qD", newdecl);
inform (olddecl_loc,
"previous declaration of %qD", olddecl);
@@ -1982,6 +2016,7 @@ next_arg:;
if (DECL_DECLARES_FUNCTION_P (olddecl) && DECL_DECLARES_FUNCTION_P (newdecl))
{
olddecl_friend = DECL_FRIEND_P (olddecl);
+ olddecl_hidden_friend = DECL_HIDDEN_FRIEND_P (olddecl);
hidden_friend = (DECL_ANTICIPATED (olddecl)
&& DECL_HIDDEN_FRIEND_P (olddecl)
&& newdecl_is_friend);
@@ -1994,10 +2029,8 @@ next_arg:;
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
- tree old_result;
- tree new_result;
- old_result = DECL_TEMPLATE_RESULT (olddecl);
- new_result = DECL_TEMPLATE_RESULT (newdecl);
+ tree old_result = DECL_TEMPLATE_RESULT (olddecl);
+ tree new_result = DECL_TEMPLATE_RESULT (newdecl);
TREE_TYPE (olddecl) = TREE_TYPE (old_result);
DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
= chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
@@ -2008,11 +2041,19 @@ next_arg:;
if (DECL_FUNCTION_TEMPLATE_P (newdecl))
{
- /* Per C++11 8.3.6/4, default arguments cannot be added in later
- declarations of a function template. */
if (DECL_SOURCE_LOCATION (newdecl)
!= DECL_SOURCE_LOCATION (olddecl))
- check_redeclaration_no_default_args (newdecl);
+ {
+ /* Per C++11 8.3.6/4, default arguments cannot be added in
+ later declarations of a function template. */
+ check_redeclaration_no_default_args (newdecl);
+ /* C++17 11.3.6/4: "If a friend declaration specifies a default
+ argument expression, that declaration... shall be the only
+ declaration of the function or function template in the
+ translation unit." */
+ check_no_redeclaration_friend_default_args
+ (old_result, new_result, olddecl_hidden_friend);
+ }
check_default_args (newdecl);
@@ -2463,7 +2504,7 @@ next_arg:;
/* If redeclaring a builtin function, it stays built in
if newdecl is a gnu_inline definition, or if newdecl is just
a declaration. */
- if (DECL_BUILT_IN (olddecl)
+ if (fndecl_built_in_p (olddecl)
&& (new_defines_function ? GNU_INLINE_P (newdecl) : types_match))
{
DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
@@ -2519,6 +2560,7 @@ next_arg:;
&& DECL_VISIBILITY_SPECIFIED (newdecl)
&& DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
{
+ auto_diagnostic_group d;
if (warning_at (newdecl_loc, OPT_Wattributes,
"%qD: visibility attribute ignored because it "
"conflicts with previous declaration", newdecl))
@@ -2938,12 +2980,15 @@ redeclaration_error_message (tree newdecl, tree olddecl)
{
DECL_EXTERNAL (newdecl) = 1;
/* For now, only warn with explicit -Wdeprecated. */
- if (global_options_set.x_warn_deprecated
- && warning_at (DECL_SOURCE_LOCATION (newdecl), OPT_Wdeprecated,
- "redundant redeclaration of %<constexpr%> static "
- "data member %qD", newdecl))
- inform (DECL_SOURCE_LOCATION (olddecl),
- "previous declaration of %qD", olddecl);
+ if (global_options_set.x_warn_deprecated)
+ {
+ auto_diagnostic_group d;
+ if (warning_at (DECL_SOURCE_LOCATION (newdecl), OPT_Wdeprecated,
+ "redundant redeclaration of %<constexpr%> "
+ "static data member %qD", newdecl))
+ inform (DECL_SOURCE_LOCATION (olddecl),
+ "previous declaration of %qD", olddecl);
+ }
return NULL;
}
@@ -3143,7 +3188,8 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
if (!identified)
{
complained = identify_goto (decl, input_location, locus,
- DK_PERMERROR);
+ problem > 1
+ ? DK_ERROR : DK_PERMERROR);
identified = 1;
}
if (complained)
@@ -3598,6 +3644,8 @@ finish_case_label (location_t loc, tree low_value, tree high_value)
return error_mark_node;
type = SWITCH_STMT_TYPE (switch_stack->switch_stmt);
+ if (type == error_mark_node)
+ return error_mark_node;
low_value = case_conversion (type, low_value);
high_value = case_conversion (type, high_value);
@@ -4125,6 +4173,13 @@ cxx_init_decl_processing (void)
c_common_nodes_and_builtins ();
+ tree bool_ftype = build_function_type_list (boolean_type_node, NULL_TREE);
+ tree decl
+ = add_builtin_function ("__builtin_is_constant_evaluated",
+ bool_ftype, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
+ BUILT_IN_FRONTEND, NULL, NULL_TREE);
+ set_call_expr_flags (decl, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
+
integer_two_node = build_int_cst (NULL_TREE, 2);
/* Guess at the initial static decls size. */
@@ -4697,6 +4752,7 @@ warn_misplaced_attr_for_class_type (source_location location,
{
gcc_assert (OVERLOAD_TYPE_P (class_type));
+ auto_diagnostic_group d;
if (warning_at (location, OPT_Wattributes,
"attribute ignored in declaration "
"of %q#T", class_type))
@@ -5527,11 +5583,13 @@ layout_var_decl (tree decl)
void
maybe_commonize_var (tree decl)
{
+ /* Don't mess with __FUNCTION__ and similar. */
+ if (DECL_ARTIFICIAL (decl))
+ return;
+
/* Static data in a function with comdat linkage also has comdat
linkage. */
if ((TREE_STATIC (decl)
- /* Don't mess with __FUNCTION__. */
- && ! DECL_ARTIFICIAL (decl)
&& DECL_FUNCTION_SCOPE_P (decl)
&& vague_linkage_p (DECL_CONTEXT (decl)))
|| (TREE_PUBLIC (decl) && DECL_INLINE_VAR_P (decl)))
@@ -6422,6 +6480,16 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
init_code = store_init_value (decl, init, cleanups, flags);
+ if (DECL_INITIAL (decl)
+ && TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR
+ && !vec_safe_is_empty (CONSTRUCTOR_ELTS (DECL_INITIAL (decl))))
+ {
+ tree elt = CONSTRUCTOR_ELTS (DECL_INITIAL (decl))->last ().value;
+ if (TREE_CODE (TREE_TYPE (elt)) == ARRAY_TYPE
+ && TYPE_SIZE (TREE_TYPE (elt)) == NULL_TREE)
+ cp_complete_array_type (&TREE_TYPE (elt), elt, false);
+ }
+
if (pedantic && TREE_CODE (type) == ARRAY_TYPE
&& DECL_INITIAL (decl)
&& TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
@@ -6505,7 +6573,7 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
else
{
if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
+ && fndecl_built_in_p (decl, BUILT_IN_NORMAL))
set_builtin_user_assembler_name (decl, asmspec);
set_user_assembler_name (decl, asmspec);
}
@@ -6708,6 +6776,10 @@ initialize_artificial_var (tree decl, vec<constructor_elt, va_gc> *v)
gcc_assert (TREE_CODE (init) == CONSTRUCTOR);
DECL_INITIAL (decl) = init;
DECL_INITIALIZED_P (decl) = 1;
+ /* Mark the decl as constexpr so that we can access its content
+ at compile time. */
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true;
+ DECL_DECLARED_CONSTEXPR_P (decl) = true;
determine_visibility (decl);
layout_var_decl (decl);
maybe_commonize_var (decl);
@@ -8780,6 +8852,21 @@ grokfndecl (tree ctype,
}
}
+ /* C++17 11.3.6/4: "If a friend declaration specifies a default argument
+ expression, that declaration shall be a definition..." */
+ if (friendp && !funcdef_flag)
+ {
+ for (tree t = FUNCTION_FIRST_USER_PARMTYPE (decl);
+ t && t != void_list_node; t = TREE_CHAIN (t))
+ if (TREE_PURPOSE (t))
+ {
+ permerror (DECL_SOURCE_LOCATION (decl),
+ "friend declaration of %qD specifies default "
+ "arguments and isn't a definition", decl);
+ break;
+ }
+ }
+
/* If this decl has namespace scope, set that up. */
if (in_namespace)
set_decl_namespace (decl, in_namespace, friendp);
@@ -9410,25 +9497,24 @@ build_ptrmem_type (tree class_type, tree member_type)
/* DECL is a VAR_DECL defined in-class, whose TYPE is also given.
Check to see that the definition is valid. Issue appropriate error
- messages. Return 1 if the definition is particularly bad, or 0
- otherwise. */
+ messages. */
-static int
+static void
check_static_variable_definition (tree decl, tree type)
{
/* Avoid redundant diagnostics on out-of-class definitions. */
if (!current_class_type || !TYPE_BEING_DEFINED (current_class_type))
- return 0;
+ ;
/* Can't check yet if we don't know the type. */
- if (dependent_type_p (type))
- return 0;
+ else if (dependent_type_p (type))
+ ;
/* If DECL is declared constexpr, we'll do the appropriate checks
in check_initializer. Similarly for inline static data members. */
- if (DECL_P (decl)
+ else if (DECL_P (decl)
&& (DECL_DECLARED_CONSTEXPR_P (decl)
|| undeduced_auto_decl (decl)
|| DECL_VAR_DECLARED_INLINE_P (decl)))
- return 0;
+ ;
else if (cxx_dialect >= cxx11 && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
{
if (!COMPLETE_TYPE_P (type))
@@ -9443,23 +9529,18 @@ check_static_variable_definition (tree decl, tree type)
error_at (DECL_SOURCE_LOCATION (decl),
"in-class initialization of static data member %q#D of "
"non-literal type", decl);
- return 1;
}
-
/* Motion 10 at San Diego: If a static const integral data member is
initialized with an integral constant expression, the initializer
may appear either in the declaration (within the class), or in
the definition, but not both. If it appears in the class, the
member is a member constant. The file-scope definition is always
required. */
- if (!ARITHMETIC_TYPE_P (type) && TREE_CODE (type) != ENUMERAL_TYPE)
- {
- error_at (DECL_SOURCE_LOCATION (decl),
- "invalid in-class initialization of static data member "
- "of non-integral type %qT",
- type);
- return 1;
- }
+ else if (!ARITHMETIC_TYPE_P (type) && TREE_CODE (type) != ENUMERAL_TYPE)
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "invalid in-class initialization of static data member "
+ "of non-integral type %qT",
+ type);
else if (!CP_TYPE_CONST_P (type))
error_at (DECL_SOURCE_LOCATION (decl),
"ISO C++ forbids in-class initialization of non-const "
@@ -9469,8 +9550,6 @@ check_static_variable_definition (tree decl, tree type)
pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic,
"ISO C++ forbids initialization of member constant "
"%qD of non-integral type %qT", decl, type);
-
- return 0;
}
/* *expr_p is part of the TYPE_SIZE of a variably-sized array. If any
@@ -9598,7 +9677,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
{
tree folded = cp_fully_fold (size);
if (TREE_CODE (folded) == INTEGER_CST)
- pedwarn (location_of (size), OPT_Wpedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"size of array is not an integral constant-expression");
/* Use the folded result for VLAs, too; it will have resolved
SIZEOF_EXPR. */
@@ -9768,7 +9847,10 @@ create_array_type_for_decl (tree name, tree type, tree size)
type-specifier, the program is ill-formed. */
if (type_uses_auto (type))
{
- error ("%qD declared as array of %qT", name, type);
+ if (name)
+ error ("%qD declared as array of %qT", name, type);
+ else
+ error ("creating array of %qT", type);
return error_mark_node;
}
@@ -10621,14 +10703,14 @@ grokdeclarator (const cp_declarator *declarator,
if (signed_p && unsigned_p)
{
gcc_rich_location richloc (declspecs->locations[ds_signed]);
- richloc.add_range (declspecs->locations[ds_unsigned], false);
+ richloc.add_range (declspecs->locations[ds_unsigned]);
error_at (&richloc,
"%<signed%> and %<unsigned%> specified together");
}
else if (long_p && short_p)
{
gcc_rich_location richloc (declspecs->locations[ds_long]);
- richloc.add_range (declspecs->locations[ds_short], false);
+ richloc.add_range (declspecs->locations[ds_short]);
error_at (&richloc, "%<long%> and %<short%> specified together");
}
else if (TREE_CODE (type) != INTEGER_TYPE
@@ -10772,18 +10854,19 @@ grokdeclarator (const cp_declarator *declarator,
if (staticp == 2)
{
gcc_rich_location richloc (declspecs->locations[ds_virtual]);
- richloc.add_range (declspecs->locations[ds_storage_class], false);
+ richloc.add_range (declspecs->locations[ds_storage_class]);
error_at (&richloc, "member %qD cannot be declared both %<virtual%> "
"and %<static%>", dname);
storage_class = sc_none;
staticp = 0;
}
- if (constexpr_p)
+ if (constexpr_p && cxx_dialect < cxx2a)
{
gcc_rich_location richloc (declspecs->locations[ds_virtual]);
- richloc.add_range (declspecs->locations[ds_constexpr], false);
- error_at (&richloc, "member %qD cannot be declared both %<virtual%> "
- "and %<constexpr%>", dname);
+ richloc.add_range (declspecs->locations[ds_constexpr]);
+ pedwarn (&richloc, OPT_Wpedantic, "member %qD can be declared both "
+ "%<virtual%> and %<constexpr%> only in -std=c++2a or "
+ "-std=gnu++2a", dname);
}
}
friendp = decl_spec_seq_has_spec_p (declspecs, ds_friend);
@@ -11130,7 +11213,10 @@ grokdeclarator (const cp_declarator *declarator,
/* Handle a late-specified return type. */
tree late_return_type = declarator->u.function.late_return_type;
- if (funcdecl_p)
+ if (funcdecl_p
+ /* This is the case e.g. for
+ using T = auto () -> int. */
+ || inner_declarator == NULL)
{
if (tree auto_node = type_uses_auto (type))
{
@@ -11162,6 +11248,16 @@ grokdeclarator (const cp_declarator *declarator,
name, type);
return error_mark_node;
}
+ else if (is_auto (type) && AUTO_IS_DECLTYPE (type))
+ {
+ if (funcdecl_p)
+ error ("%qs function with trailing return type has "
+ "%<decltype(auto)%> as its type rather than "
+ "plain %<auto%>", name);
+ else
+ error ("invalid use of %<decltype(auto)%>");
+ return error_mark_node;
+ }
tree tmpl = CLASS_PLACEHOLDER_TEMPLATE (auto_node);
if (!tmpl)
if (tree late_auto = type_uses_auto (late_return_type))
@@ -11319,7 +11415,7 @@ grokdeclarator (const cp_declarator *declarator,
{
/* Cannot be both friend and virtual. */
gcc_rich_location richloc (declspecs->locations[ds_virtual]);
- richloc.add_range (declspecs->locations[ds_friend], false);
+ richloc.add_range (declspecs->locations[ds_friend]);
error_at (&richloc, "virtual functions cannot be friends");
friendp = 0;
}
@@ -13448,7 +13544,7 @@ grok_op_properties (tree decl, bool complain)
/* Warn about conversion operators that will never be used. */
if (IDENTIFIER_CONV_OP_P (name)
&& ! DECL_TEMPLATE_INFO (decl)
- && warn_conversion)
+ && warn_class_conversion)
{
tree t = TREE_TYPE (name);
int ref = TYPE_REF_P (t);
@@ -13457,31 +13553,29 @@ grok_op_properties (tree decl, bool complain)
t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
if (VOID_TYPE_P (t))
- warning_at (loc, OPT_Wconversion,
- ref
- ? G_("conversion to a reference to void "
- "will never use a type conversion operator")
- : G_("conversion to void "
- "will never use a type conversion operator"));
+ warning_at (loc, OPT_Wclass_conversion, "converting %qT to %<void%> "
+ "will never use a type conversion operator", class_type);
else if (class_type)
{
- if (t == class_type)
- warning_at (loc, OPT_Wconversion,
+ if (same_type_ignoring_top_level_qualifiers_p (t, class_type))
+ warning_at (loc, OPT_Wclass_conversion,
ref
- ? G_("conversion to a reference to the same type "
+ ? G_("converting %qT to a reference to the same type "
"will never use a type conversion operator")
- : G_("conversion to the same type "
- "will never use a type conversion operator"));
+ : G_("converting %qT to the same type "
+ "will never use a type conversion operator"),
+ class_type);
/* Don't force t to be complete here. */
else if (MAYBE_CLASS_TYPE_P (t)
&& COMPLETE_TYPE_P (t)
&& DERIVED_FROM_P (t, class_type))
- warning_at (loc, OPT_Wconversion,
+ warning_at (loc, OPT_Wclass_conversion,
ref
- ? G_("conversion to a reference to a base class "
- "will never use a type conversion operator")
- : G_("conversion to a base class "
- "will never use a type conversion operator"));
+ ? G_("converting %qT to a reference to a base class "
+ "%qT will never use a type conversion operator")
+ : G_("converting %qT to a base class %qT "
+ "will never use a type conversion operator"),
+ class_type, t);
}
}
@@ -15567,6 +15661,18 @@ begin_destructor_body (void)
tree stmt = cp_build_modify_expr (input_location, vtbl_ptr,
NOP_EXPR, vtbl,
tf_warning_or_error);
+ /* If the vptr is shared with some virtual nearly empty base,
+ don't clear it if not in charge, the dtor of the virtual
+ nearly empty base will do that later. */
+ if (CLASSTYPE_VBASECLASSES (current_class_type)
+ && CLASSTYPE_PRIMARY_BINFO (current_class_type)
+ && BINFO_VIRTUAL_P
+ (CLASSTYPE_PRIMARY_BINFO (current_class_type)))
+ {
+ stmt = convert_to_void (stmt, ICV_STATEMENT,
+ tf_warning_or_error);
+ stmt = build_if_in_charge (stmt);
+ }
finish_decl_cleanup (NULL_TREE, stmt);
}
else
@@ -15710,6 +15816,22 @@ maybe_save_function_definition (tree fun)
register_constexpr_fundef (fun, DECL_SAVED_TREE (fun));
}
+/* Attempt to add a fix-it hint to RICHLOC suggesting the insertion
+ of "return *this;" immediately before its location, using FNDECL's
+ first statement (if any) to give the indentation, if appropriate. */
+
+static void
+add_return_star_this_fixit (gcc_rich_location *richloc, tree fndecl)
+{
+ location_t indent = UNKNOWN_LOCATION;
+ tree stmts = expr_first (DECL_SAVED_TREE (fndecl));
+ if (stmts)
+ indent = EXPR_LOCATION (stmts);
+ richloc->add_fixit_insert_formatted ("return *this;",
+ richloc->get_loc (),
+ indent);
+}
+
/* Finish up a function declaration and compile that function
all the way to assembler language output. The free the storage
for the function definition. INLINE_P is TRUE if we just
@@ -15903,8 +16025,21 @@ finish_function (bool inline_p)
&& !DECL_DESTRUCTOR_P (fndecl)
&& targetm.warn_func_return (fndecl))
{
- warning (OPT_Wreturn_type,
- "no return statement in function returning non-void");
+ gcc_rich_location richloc (input_location);
+ /* Potentially add a "return *this;" fix-it hint for
+ assignment operators. */
+ if (IDENTIFIER_ASSIGN_OP_P (DECL_NAME (fndecl)))
+ {
+ tree valtype = TREE_TYPE (DECL_RESULT (fndecl));
+ if (TREE_CODE (valtype) == REFERENCE_TYPE
+ && same_type_ignoring_top_level_qualifiers_p
+ (TREE_TYPE (valtype), TREE_TYPE (current_class_ref)))
+ if (global_dc->option_enabled (OPT_Wreturn_type,
+ global_dc->option_state))
+ add_return_star_this_fixit (&richloc, fndecl);
+ }
+ warning_at (&richloc, OPT_Wreturn_type,
+ "no return statement in function returning non-void");
TREE_NO_WARNING (fndecl) = 1;
}
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index d67ced0..a5ad0ee 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -764,6 +764,7 @@ finish_static_data_member_decl (tree decl,
t = CP_TYPE_CONTEXT (t))
if (TYPE_UNNAMED_P (t))
{
+ auto_diagnostic_group d;
if (permerror (DECL_SOURCE_LOCATION (decl),
"static data member %qD in unnamed class", decl))
inform (DECL_SOURCE_LOCATION (TYPE_NAME (t)),
@@ -4287,6 +4288,7 @@ no_linkage_error (tree decl)
else if (TYPE_UNNAMED_P (t))
{
bool d = false;
+ auto_diagnostic_group grp;
if (cxx_dialect >= cxx11)
d = permerror (DECL_SOURCE_LOCATION (decl), "%q#D, declared using "
"unnamed type, is used but never defined", decl);
@@ -5208,6 +5210,7 @@ cp_warn_deprecated_use (tree decl, tsubst_flags_t complain)
&& DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
&& copy_fn_p (decl))
{
+ auto_diagnostic_group d;
/* Don't warn about system library classes (c++/86342). */
if (!DECL_IN_SYSTEM_HEADER (decl))
warned = warning (OPT_Wdeprecated_copy,
diff --git a/gcc/cp/dump.c b/gcc/cp/dump.c
index 9c1e5fc..d9b868b 100644
--- a/gcc/cp/dump.c
+++ b/gcc/cp/dump.c
@@ -301,6 +301,7 @@ cp_dump_tree (void* dump_info, tree t)
case RANGE_FOR_STMT:
dump_stmt (di, t);
+ dump_child ("init", RANGE_FOR_INIT_STMT (t));
dump_child ("decl", RANGE_FOR_DECL (t));
dump_child ("expr", RANGE_FOR_EXPR (t));
dump_child ("body", RANGE_FOR_BODY (t));
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 7a644fd..601f6d2 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
#include "c-family/c-objc.h"
#include "ubsan.h"
#include "internal-fn.h"
+#include "gcc-rich-location.h"
#define pp_separate_with_comma(PP) pp_cxx_separate_with (PP, ',')
#define pp_separate_with_semicolon(PP) pp_cxx_separate_with (PP, ';')
@@ -3287,8 +3288,13 @@ void
cxx_print_error_function (diagnostic_context *context, const char *file,
diagnostic_info *diagnostic)
{
+ char *prefix;
+ if (file)
+ prefix = xstrdup (file);
+ else
+ prefix = NULL;
lhd_print_error_function (context, file, diagnostic);
- pp_set_prefix (context->printer, file);
+ pp_set_prefix (context->printer, prefix);
maybe_print_instantiation_context (context);
}
@@ -3316,7 +3322,7 @@ cp_print_error_function (diagnostic_context *context,
return;
if (diagnostic_last_function_changed (context, diagnostic))
{
- const char *old_prefix = context->printer->prefix;
+ char *old_prefix = pp_take_prefix (context->printer);
const char *file = LOCATION_FILE (diagnostic_location (diagnostic));
tree abstract_origin = diagnostic_abstract_origin (diagnostic);
char *new_prefix = (file && abstract_origin == NULL)
@@ -4091,7 +4097,7 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec,
return true;
case 'K':
t = va_arg (*text->args_ptr, tree);
- percent_K_format (text, t);
+ percent_K_format (text, EXPR_LOCATION (t), TREE_BLOCK (t));
return true;
case 'L': result = language_to_string (next_lang); break;
case 'O': result = op_to_string (false, next_tcode); break;
@@ -4113,7 +4119,7 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec,
pp_string (pp, result);
if (set_locus && t != NULL)
- text->set_location (0, location_of (t), true);
+ text->set_location (0, location_of (t), SHOW_RANGE_WITH_CARET);
return true;
#undef next_tree
#undef next_tcode
@@ -4264,13 +4270,42 @@ qualified_name_lookup_error (tree scope, tree name,
}
else if (scope != global_namespace)
{
+ auto_diagnostic_group d;
error_at (location, "%qD is not a member of %qD", name, scope);
if (!suggest_alternative_in_explicit_scope (location, name, scope))
suggest_alternatives_for (location, name, false);
}
else
{
+ auto_diagnostic_group d;
error_at (location, "%<::%D%> has not been declared", name);
suggest_alternatives_for (location, name, true);
}
}
+
+/* C++-specific implementation of range_label::get_text () vfunc for
+ range_label_for_type_mismatch.
+
+ Compare with print_template_differences above. */
+
+label_text
+range_label_for_type_mismatch::get_text (unsigned /*range_idx*/) const
+{
+ if (m_labelled_type == NULL_TREE)
+ return label_text (NULL, false);
+
+ const bool verbose = false;
+ const bool show_color = false;
+
+ const char *result;
+ if (m_other_type
+ && comparable_template_types_p (m_labelled_type, m_other_type))
+ result = type_to_string_with_compare (m_labelled_type, m_other_type,
+ verbose, show_color);
+ else
+ result = type_to_string (m_labelled_type, verbose, true, NULL, show_color);
+
+ /* Both of the above return GC-allocated buffers, so the caller mustn't
+ free them. */
+ return label_text (const_cast <char *> (result), false);
+}
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index f85ae04..3449b59 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -676,12 +676,9 @@ build_throw (tree exp)
/* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes
treated as an rvalue for the purposes of overload resolution
to favor move constructors over copy constructors. */
- if (/* Must be a local, automatic variable. */
- VAR_P (exp)
- && DECL_CONTEXT (exp) == current_function_decl
- && ! TREE_STATIC (exp)
+ if (treat_lvalue_as_rvalue_p (exp, /*parm_ok*/false)
/* The variable must not have the `volatile' qualifier. */
- && !(cp_type_quals (TREE_TYPE (exp)) & TYPE_QUAL_VOLATILE))
+ && !CP_TYPE_VOLATILE_P (TREE_TYPE (exp)))
{
tree moved = move (exp);
exp_vec = make_tree_vector_single (moved);
@@ -1190,7 +1187,7 @@ type_throw_all_p (const_tree type)
constant-expression of EXPR. COMPLAIN is as for tsubst. */
tree
-build_noexcept_spec (tree expr, int complain)
+build_noexcept_spec (tree expr, tsubst_flags_t complain)
{
/* This isn't part of the signature, so don't bother trying to evaluate
it until instantiation. */
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c
index 2c9c12f..ce85a80 100644
--- a/gcc/cp/friend.c
+++ b/gcc/cp/friend.c
@@ -304,6 +304,7 @@ make_friend_class (tree type, tree friend_type, bool complain)
if (TYPE_TEMPLATE_INFO (friend_type)
&& !PRIMARY_TEMPLATE_P (TYPE_TI_TEMPLATE (friend_type)))
{
+ auto_diagnostic_group d;
error ("%qT is not a template", friend_type);
inform (location_of (friend_type), "previous declaration here");
if (TYPE_CLASS_SCOPE_P (friend_type)
@@ -384,6 +385,7 @@ make_friend_class (tree type, tree friend_type, bool complain)
}
if (template_member_p && !DECL_CLASS_TEMPLATE_P (decl))
{
+ auto_diagnostic_group d;
error ("%qT is not a member class template of %qT",
name, ctype);
inform (DECL_SOURCE_LOCATION (decl),
@@ -393,6 +395,7 @@ make_friend_class (tree type, tree friend_type, bool complain)
if (!template_member_p && (TREE_CODE (decl) != TYPE_DECL
|| !CLASS_TYPE_P (TREE_TYPE (decl))))
{
+ auto_diagnostic_group d;
error ("%qT is not a nested class of %qT",
name, ctype);
inform (DECL_SOURCE_LOCATION (decl),
@@ -636,6 +639,7 @@ do_friend (tree ctype, tree declarator, tree decl,
static int explained;
bool warned;
+ auto_diagnostic_group d;
warned = warning (OPT_Wnon_template_friend, "friend declaration "
"%q#D declares a non-template function", decl);
if (! explained && warned)
diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c
index 443a174..8c81e09 100644
--- a/gcc/cp/g++spec.c
+++ b/gcc/cp/g++spec.c
@@ -184,6 +184,7 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
break;
case OPT_c:
+ case OPT_r:
case OPT_S:
case OPT_E:
case OPT_M:
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 94f8fdd..15046b4 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -915,6 +915,7 @@ perform_member_init (tree member, tree init)
{
/* TYPE_NEEDS_CONSTRUCTING can be set just because we have a
vtable; still give this diagnostic. */
+ auto_diagnostic_group d;
if (permerror (DECL_SOURCE_LOCATION (current_function_decl),
"uninitialized const member in %q#T", type))
inform (DECL_SOURCE_LOCATION (member),
@@ -932,6 +933,7 @@ perform_member_init (tree member, tree init)
/* member traversal: note it leaves init NULL */
if (TYPE_REF_P (type))
{
+ auto_diagnostic_group d;
if (permerror (DECL_SOURCE_LOCATION (current_function_decl),
"uninitialized reference member in %q#T", type))
inform (DECL_SOURCE_LOCATION (member),
@@ -939,6 +941,7 @@ perform_member_init (tree member, tree init)
}
else if (CP_TYPE_CONST_P (type))
{
+ auto_diagnostic_group d;
if (permerror (DECL_SOURCE_LOCATION (current_function_decl),
"uninitialized const member in %q#T", type))
inform (DECL_SOURCE_LOCATION (member),
@@ -3255,6 +3258,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
|| CP_DECL_CONTEXT (alloc_fn) == global_namespace)
&& !aligned_allocation_fn_p (alloc_fn))
{
+ auto_diagnostic_group d;
if (warning (OPT_Waligned_new_, "%<new%> of type %qT with extended "
"alignment %d", elt_type, TYPE_ALIGN_UNIT (elt_type)))
{
@@ -3831,16 +3835,19 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
if (!COMPLETE_TYPE_P (type))
{
- if ((complain & tf_warning)
- && warning (OPT_Wdelete_incomplete,
- "possible problem detected in invocation of "
- "delete [] operator:"))
- {
- cxx_incomplete_type_diagnostic (base, type, DK_WARNING);
- inform (input_location, "neither the destructor nor the "
- "class-specific operator delete [] will be called, "
- "even if they are declared when the class is defined");
- }
+ if (complain & tf_warning)
+ {
+ auto_diagnostic_group d;
+ if (warning (OPT_Wdelete_incomplete,
+ "possible problem detected in invocation of "
+ "delete [] operator:"))
+ {
+ cxx_incomplete_type_diagnostic (base, type, DK_WARNING);
+ inform (input_location, "neither the destructor nor the "
+ "class-specific operator delete [] will be called, "
+ "even if they are declared when the class is defined");
+ }
+ }
/* This size won't actually be used. */
size_exp = size_one_node;
goto no_destructor;
@@ -4712,16 +4719,19 @@ build_delete (tree otype, tree addr, special_function_kind auto_delete,
complete_type (type);
if (!COMPLETE_TYPE_P (type))
{
- if ((complain & tf_warning)
- && warning (OPT_Wdelete_incomplete,
- "possible problem detected in invocation of "
- "delete operator:"))
+ if (complain & tf_warning)
{
- cxx_incomplete_type_diagnostic (addr, type, DK_WARNING);
- inform (input_location,
- "neither the destructor nor the class-specific "
- "operator delete will be called, even if they are "
- "declared when the class is defined");
+ auto_diagnostic_group d;
+ if (warning (OPT_Wdelete_incomplete,
+ "possible problem detected in invocation of "
+ "delete operator:"))
+ {
+ cxx_incomplete_type_diagnostic (addr, type, DK_WARNING);
+ inform (input_location,
+ "neither the destructor nor the class-specific "
+ "operator delete will be called, even if they "
+ "are declared when the class is defined");
+ }
}
}
else if (deleting && warn_delnonvdtor
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 54fc3ee..297327f 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -695,14 +695,10 @@ tree
add_default_capture (tree lambda_stack, tree id, tree initializer)
{
bool this_capture_p = (id == this_identifier);
-
tree var = NULL_TREE;
-
tree saved_class_type = current_class_type;
- tree node;
-
- for (node = lambda_stack;
+ for (tree node = lambda_stack;
node;
node = TREE_CHAIN (node))
{
@@ -720,6 +716,19 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
== CPLD_REFERENCE)),
/*explicit_init_p=*/false);
initializer = convert_from_reference (var);
+
+ /* Warn about deprecated implicit capture of this via [=]. */
+ if (cxx_dialect >= cxx2a
+ && this_capture_p
+ && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) == CPLD_COPY
+ && !in_system_header_at (LAMBDA_EXPR_LOCATION (lambda)))
+ {
+ if (warning_at (LAMBDA_EXPR_LOCATION (lambda), OPT_Wdeprecated,
+ "implicit capture of %qE via %<[=]%> is deprecated "
+ "in C++20", this_identifier))
+ inform (LAMBDA_EXPR_LOCATION (lambda), "add explicit %<this%> or "
+ "%<*this%> capture");
+ }
}
current_class_type = saved_class_type;
@@ -1510,8 +1519,8 @@ prune_lambda_captures (tree body)
tree cap = *capp;
if (tree var = var_to_maybe_prune (cap))
{
- tree *use = *const_vars.get (var);
- if (TREE_CODE (*use) == DECL_EXPR)
+ tree **use = const_vars.get (var);
+ if (use && TREE_CODE (**use) == DECL_EXPR)
{
/* All uses of this capture were folded away, leaving only the
proxy declaration. */
@@ -1526,7 +1535,7 @@ prune_lambda_captures (tree body)
*fieldp = DECL_CHAIN (*fieldp);
/* And remove the capture proxy declaration. */
- *use = void_node;
+ **use = void_node;
continue;
}
}
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index bd5d507..47b99c3 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -499,6 +499,7 @@ unqualified_name_lookup_error (tree name, location_t loc)
{
if (!objc_diagnose_private_ivar (name))
{
+ auto_diagnostic_group d;
error_at (loc, "%qD was not declared in this scope", name);
suggest_alternatives_for (loc, name, true);
}
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 0b208a8d..5379b4d 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1144,11 +1144,11 @@ static tree
constructible_expr (tree to, tree from)
{
tree expr;
+ cp_unevaluated cp_uneval_guard;
if (CLASS_TYPE_P (to))
{
tree ctype = to;
vec<tree, va_gc> *args = NULL;
- cp_unevaluated cp_uneval_guard;
if (!TYPE_REF_P (to))
to = cp_build_reference_type (to, /*rval*/false);
tree ob = build_stub_object (to);
@@ -2421,7 +2421,7 @@ lazily_declare_fn (special_function_kind sfk, tree type)
/* Add it to the class */
bool added = add_method (type, fn, false);
- gcc_assert (added);
+ gcc_assert (added || errorcount);
/* Add it to TYPE_FIELDS. */
if (sfk == sfk_destructor
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 3aafb0f..c56bfe5 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -558,11 +558,14 @@ name_lookup::search_namespace (tree scope)
/* Look in exactly namespace. */
bool found = search_namespace_only (scope);
-
- /* Recursively look in its inline children. */
- if (vec<tree, va_gc> *inlinees = DECL_NAMESPACE_INLINEES (scope))
- for (unsigned ix = inlinees->length (); ix--;)
- found |= search_namespace ((*inlinees)[ix]);
+
+ /* Don't look into inline children, if we're looking for an
+ anonymous name -- it must be in the current scope, if anywhere. */
+ if (name)
+ /* Recursively look in its inline children. */
+ if (vec<tree, va_gc> *inlinees = DECL_NAMESPACE_INLINEES (scope))
+ for (unsigned ix = inlinees->length (); ix--;)
+ found |= search_namespace ((*inlinees)[ix]);
if (found)
mark_found (scope);
@@ -2556,6 +2559,7 @@ check_extern_c_conflict (tree decl)
if (mismatch)
{
+ auto_diagnostic_group d;
pedwarn (input_location, 0,
"conflicting C language linkage declaration %q#D", decl);
inform (DECL_SOURCE_LOCATION (old),
@@ -2604,6 +2608,15 @@ c_linkage_bindings (tree name)
return NULL_TREE;
}
+/* Subroutine of check_local_shadow. */
+
+static void
+inform_shadowed (tree shadowed)
+{
+ inform (DECL_SOURCE_LOCATION (shadowed),
+ "shadowed declaration is here");
+}
+
/* DECL is being declared at a local scope. Emit suitable shadow
warnings. */
@@ -2631,7 +2644,6 @@ check_local_shadow (tree decl)
old_scope = binding->scope;
}
- tree shadowed = NULL_TREE;
if (old
&& (TREE_CODE (old) == PARM_DECL
|| VAR_P (old)
@@ -2640,13 +2652,29 @@ check_local_shadow (tree decl)
|| TREE_CODE (decl) == TYPE_DECL)))
&& DECL_FUNCTION_SCOPE_P (old)
&& (!DECL_ARTIFICIAL (decl)
+ || is_capture_proxy (decl)
|| DECL_IMPLICIT_TYPEDEF_P (decl)
|| (VAR_P (decl) && DECL_ANON_UNION_VAR_P (decl))))
{
/* DECL shadows a local thing possibly of interest. */
+ /* DR 2211: check that captures and parameters
+ do not have the same name. */
+ if (is_capture_proxy (decl))
+ {
+ if (current_lambda_expr ()
+ && DECL_CONTEXT (old) == lambda_function (current_lambda_expr ())
+ && TREE_CODE (old) == PARM_DECL
+ && DECL_NAME (decl) != this_identifier)
+ {
+ error_at (DECL_SOURCE_LOCATION (old),
+ "lambda parameter %qD "
+ "previously declared as a capture", old);
+ }
+ return;
+ }
/* Don't complain if it's from an enclosing function. */
- if (DECL_CONTEXT (old) == current_function_decl
+ else if (DECL_CONTEXT (old) == current_function_decl
&& TREE_CODE (decl) != PARM_DECL
&& TREE_CODE (old) == PARM_DECL)
{
@@ -2686,6 +2714,7 @@ check_local_shadow (tree decl)
&& old_scope == current_binding_level->level_chain
&& (old_scope->kind == sk_cond || old_scope->kind == sk_for))
{
+ auto_diagnostic_group d;
error ("redeclaration of %q#D", decl);
inform (DECL_SOURCE_LOCATION (old),
"%q#D previously declared here", old);
@@ -2708,6 +2737,7 @@ check_local_shadow (tree decl)
|| current_binding_level->level_chain->kind == sk_catch)
&& in_function_try_handler))
{
+ auto_diagnostic_group d;
if (permerror (input_location, "redeclaration of %q#D", decl))
inform (DECL_SOURCE_LOCATION (old),
"%q#D previously declared here", old);
@@ -2734,6 +2764,13 @@ check_local_shadow (tree decl)
&& (same_type_p (TREE_TYPE (old), TREE_TYPE (decl))
|| (!dependent_type_p (TREE_TYPE (decl))
&& !dependent_type_p (TREE_TYPE (old))
+ /* If the new decl uses auto, we don't yet know
+ its type (the old type cannot be using auto
+ at this point, without also being
+ dependent). This is an indication we're
+ (now) doing the shadow checking too
+ early. */
+ && !type_uses_auto (TREE_TYPE (decl))
&& can_convert (TREE_TYPE (old), TREE_TYPE (decl),
tf_none))))
warning_code = OPT_Wshadow_compatible_local;
@@ -2748,11 +2785,9 @@ check_local_shadow (tree decl)
else
msg = "declaration of %qD shadows a previous local";
+ auto_diagnostic_group d;
if (warning_at (input_location, warning_code, msg, decl))
- {
- shadowed = old;
- goto inform_shadowed;
- }
+ inform_shadowed (old);
return;
}
@@ -2777,14 +2812,12 @@ check_local_shadow (tree decl)
|| TYPE_PTRFN_P (TREE_TYPE (decl))
|| TYPE_PTRMEMFUNC_P (TREE_TYPE (decl)))
{
+ auto_diagnostic_group d;
if (warning_at (input_location, OPT_Wshadow,
"declaration of %qD shadows a member of %qT",
decl, current_nonlambda_class_type ())
&& DECL_P (member))
- {
- shadowed = member;
- goto inform_shadowed;
- }
+ inform_shadowed (member);
}
return;
}
@@ -2799,20 +2832,15 @@ check_local_shadow (tree decl)
&& !instantiating_current_function_p ())
/* XXX shadow warnings in outer-more namespaces */
{
+ auto_diagnostic_group d;
if (warning_at (input_location, OPT_Wshadow,
"declaration of %qD shadows a global declaration",
decl))
- {
- shadowed = old;
- goto inform_shadowed;
- }
+ inform_shadowed (old);
return;
}
return;
-
- inform_shadowed:
- inform (DECL_SOURCE_LOCATION (shadowed), "shadowed declaration is here");
}
/* DECL is being pushed inside function CTX. Set its context, if
@@ -2938,6 +2966,7 @@ set_local_extern_decl_linkage (tree decl, bool shadowed)
&& !comptypes (TREE_TYPE (decl), TREE_TYPE (other),
COMPARE_REDECLARATION)))
{
+ auto_diagnostic_group d;
if (permerror (DECL_SOURCE_LOCATION (decl),
"local external declaration %q#D", decl))
inform (DECL_SOURCE_LOCATION (other),
@@ -5611,7 +5640,7 @@ maybe_suggest_missing_std_header (location_t location, tree name)
if (cxx_dialect >= header_hint->min_dialect)
{
const char *header = header_hint->header;
- maybe_add_include_fixit (&richloc, header);
+ maybe_add_include_fixit (&richloc, header, true);
inform (&richloc,
"%<std::%s%> is defined in header %qs;"
" did you forget to %<#include %s%>?",
@@ -5772,7 +5801,7 @@ consider_binding_level (tree name, best_match <tree, const char *> &bm,
/* Skip anticipated decls of builtin functions. */
if (TREE_CODE (d) == FUNCTION_DECL
- && DECL_BUILT_IN (d)
+ && fndecl_built_in_p (d)
&& DECL_ANTICIPATED (d))
continue;
@@ -5938,10 +5967,10 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind, location_t loc)
/* If we have an exact match for a macro name, then either the
macro was used with the wrong argument count, or the macro
has been used before it was defined. */
- cpp_hashnode *macro = bmm.blithely_get_best_candidate ();
- if (macro && (macro->flags & NODE_BUILTIN) == 0)
- return name_hint (NULL,
- macro_use_before_def::maybe_make (loc, macro));
+ if (cpp_hashnode *macro = bmm.blithely_get_best_candidate ())
+ if (cpp_user_macro_p (macro))
+ return name_hint (NULL,
+ macro_use_before_def::maybe_make (loc, macro));
}
/* Try the "starts_decl_specifier_p" keywords to detect
@@ -7255,7 +7284,7 @@ cp_emit_debug_info_for_using (tree t, tree context)
of a builtin function. */
if (TREE_CODE (t) == FUNCTION_DECL
&& DECL_EXTERNAL (t)
- && DECL_BUILT_IN (t))
+ && fndecl_built_in_p (t))
return;
/* Do not supply context to imported_module_or_decl, if
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index 0e9b84e..3923a5f 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -46,6 +46,8 @@ update_cloned_parm (tree parm, tree cloned_parm, bool first)
/* We may have taken its address. */
TREE_ADDRESSABLE (cloned_parm) = TREE_ADDRESSABLE (parm);
+ DECL_BY_REFERENCE (cloned_parm) = DECL_BY_REFERENCE (parm);
+
/* The definition might have different constness. */
TREE_READONLY (cloned_parm) = TREE_READONLY (parm);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 93c812f..6e68f2c 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -3280,6 +3280,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
to specify an argument list. Emit a useful error message. */
if (DECL_TYPE_TEMPLATE_P (decl))
{
+ auto_diagnostic_group d;
error_at (location,
"invalid use of template-name %qE without an argument list",
decl);
@@ -3296,6 +3297,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
else if (!parser->scope)
{
/* Issue an error message. */
+ auto_diagnostic_group d;
name_hint hint;
if (TREE_CODE (id) == IDENTIFIER_NODE)
hint = lookup_name_fuzzy (id, FUZZY_LOOKUP_TYPENAME, location);
@@ -3370,6 +3372,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
{
if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
{
+ auto_diagnostic_group d;
if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
error_at (location_of (id),
"%qE in namespace %qE does not name a template type",
@@ -3392,6 +3395,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
&& constructor_name_p (id, parser->scope))
{
/* A<T>::A<T>() */
+ auto_diagnostic_group d;
error_at (location, "%<%T::%E%> names the constructor, not"
" the type", parser->scope, id);
if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
@@ -3401,8 +3405,10 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
else if (TYPE_P (parser->scope)
&& dependent_scope_p (parser->scope))
{
+ gcc_rich_location richloc (location);
+ richloc.add_fixit_insert_before ("typename ");
if (TREE_CODE (parser->scope) == TYPENAME_TYPE)
- error_at (location,
+ error_at (&richloc,
"need %<typename%> before %<%T::%D::%E%> because "
"%<%T::%D%> is a dependent scope",
TYPE_CONTEXT (parser->scope),
@@ -3411,12 +3417,13 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
TYPE_CONTEXT (parser->scope),
TYPENAME_TYPE_FULLNAME (parser->scope));
else
- error_at (location, "need %<typename%> before %<%T::%E%> because "
+ error_at (&richloc, "need %<typename%> before %<%T::%E%> because "
"%qT is a dependent scope",
parser->scope, id, parser->scope);
}
else if (TYPE_P (parser->scope))
{
+ auto_diagnostic_group d;
if (!COMPLETE_TYPE_P (parser->scope))
cxx_incomplete_type_error (location_of (id), NULL_TREE,
parser->scope);
@@ -4128,7 +4135,7 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
else if (curr_type != CPP_STRING)
{
rich_location rich_loc (line_table, tok->location);
- rich_loc.add_range (last_tok_loc, false);
+ rich_loc.add_range (last_tok_loc);
error_at (&rich_loc,
"unsupported non-standard concatenation "
"of string literals");
@@ -10280,6 +10287,9 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
{
cp_lexer_consume_token (parser->lexer);
first = false;
+
+ if (!(at_function_scope_p () || parsing_nsdmi ()))
+ error ("non-local lambda expression cannot have a capture-default");
}
while (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_SQUARE))
@@ -15232,11 +15242,15 @@ cp_parser_introduction_list (cp_parser *parser)
if (is_pack)
cp_lexer_consume_token (parser->lexer);
+ tree identifier = cp_parser_identifier (parser);
+ if (identifier == error_mark_node)
+ break;
+
/* Build placeholder. */
tree parm = build_nt (WILDCARD_DECL);
DECL_SOURCE_LOCATION (parm)
= cp_lexer_peek_token (parser->lexer)->location;
- DECL_NAME (parm) = cp_parser_identifier (parser);
+ DECL_NAME (parm) = identifier;
WILDCARD_PACK_P (parm) = is_pack;
vec_safe_push (introduction_vec, parm);
@@ -17747,7 +17761,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
|| cp_parser_is_keyword (token, RID_STRUCT))
{
gcc_rich_location richloc (token->location);
- richloc.add_range (input_location, false);
+ richloc.add_range (input_location);
richloc.add_fixit_remove ();
pedwarn (&richloc, 0, "elaborated-type-specifier for "
"a scoped enum must not use the %qD keyword",
@@ -18615,6 +18629,7 @@ cp_parser_namespace_name (cp_parser* parser)
{
if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
{
+ auto_diagnostic_group d;
error_at (token->location, "%qD is not a namespace-name", identifier);
if (namespace_decl == error_mark_node
&& parser->scope && TREE_CODE (parser->scope) == NAMESPACE_DECL)
@@ -21363,16 +21378,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
}
else if (token->type == CPP_CLOSE_PAREN)
/* There are no parameters. */
- {
-#ifdef SYSTEM_IMPLICIT_EXTERN_C
- if (in_system_header_at (input_location)
- && current_class_type == NULL
- && current_lang_name == lang_name_c)
- return NULL_TREE;
- else
-#endif
- return void_list_node;
- }
+ return void_list_node;
/* Check for `(void)', too, which is a special case. */
else if (token->keyword == RID_VOID
&& (cp_lexer_peek_nth_token (parser->lexer, 2)->type
@@ -21722,7 +21728,8 @@ cp_parser_parameter_declaration (cp_parser *parser,
parameter was introduced during cp_parser_parameter_declaration,
change any implicit parameters introduced into packs. */
if (parser->implicit_template_parms
- && (token->type == CPP_ELLIPSIS
+ && ((token->type == CPP_ELLIPSIS
+ && declarator_can_be_parameter_pack (declarator))
|| (declarator && declarator->parameter_pack_p)))
{
int latest_template_parm_idx = TREE_VEC_LENGTH
@@ -22387,7 +22394,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
"%<.%s%> designator used multiple times in "
"the same initializer list",
IDENTIFIER_POINTER (designator));
- (*v)[i].index = NULL_TREE;
+ (*v)[i].index = error_mark_node;
}
else
IDENTIFIER_MARKED (designator) = 1;
@@ -27166,18 +27173,18 @@ cp_parser_template_introduction (cp_parser* parser, bool member_p)
matching identifiers. */
tree introduction_list = cp_parser_introduction_list (parser);
+ /* Look for closing brace for introduction. */
+ if (!braces.require_close (parser))
+ return true;
+
/* The introduction-list shall not be empty. */
int nargs = TREE_VEC_LENGTH (introduction_list);
if (nargs == 0)
{
- error ("empty introduction-list");
+ /* In cp_parser_introduction_list we have already issued an error. */
return true;
}
- /* Look for closing brace for introduction. */
- if (!braces.require_close (parser))
- return true;
-
if (tmpl_decl == error_mark_node)
{
cp_parser_name_lookup_error (parser, concept_name, tmpl_decl, NLE_NULL,
@@ -28380,7 +28387,7 @@ set_and_check_decl_spec_loc (cp_decl_specifier_seq *decl_specs,
gcc_rich_location richloc (location);
if (gnu != decl_specs->gnu_thread_keyword_p)
{
- richloc.add_range (decl_specs->locations[ds_thread], false);
+ richloc.add_range (decl_specs->locations[ds_thread]);
error_at (&richloc,
"both %<__thread%> and %<thread_local%> specified");
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2780504..b8b6545 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -800,6 +800,7 @@ check_specialization_namespace (tree tmpl)
return true;
else
{
+ auto_diagnostic_group d;
if (permerror (input_location,
"specialization of %qD in different namespace", tmpl))
inform (DECL_SOURCE_LOCATION (tmpl),
@@ -2592,6 +2593,7 @@ check_template_variable (tree decl)
}
if (template_header_count > wanted)
{
+ auto_diagnostic_group d;
bool warned = pedwarn (DECL_SOURCE_LOCATION (decl), 0,
"too many template headers for %qD "
"(should be %d)",
@@ -2724,6 +2726,7 @@ warn_spec_missing_attributes (tree tmpl, tree spec, tree attrlist)
if (!nattrs)
return;
+ auto_diagnostic_group d;
if (warning_at (DECL_SOURCE_LOCATION (spec), OPT_Wmissing_attributes,
"explicit specialization %q#D may be missing attributes",
spec))
@@ -3070,6 +3073,7 @@ check_explicit_specialization (tree declarator,
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_HIDDEN_FRIEND_P (tmpl))
{
+ auto_diagnostic_group d;
if (pedwarn (DECL_SOURCE_LOCATION (decl), 0,
"friend declaration %qD is not visible to "
"explicit specialization", tmpl))
@@ -4891,6 +4895,7 @@ process_partial_specialization (tree decl)
&& TMPL_ARGS_DEPTH (specargs) == 1
&& !get_partial_spec_bindings (maintmpl, maintmpl, specargs))
{
+ auto_diagnostic_group d;
if (permerror (input_location, "partial specialization %qD is not "
"more specialized than", decl))
inform (DECL_SOURCE_LOCATION (maintmpl), "primary template %qD",
@@ -6682,7 +6687,9 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
template-parameter. */
expr = build_converted_constant_expr (type, expr, complain);
if (expr == error_mark_node)
- return error_mark_node;
+ /* Make sure we return NULL_TREE only if we have really issued
+ an error, as described above. */
+ return (complain & tf_error) ? NULL_TREE : error_mark_node;
expr = maybe_constant_value (expr);
expr = convert_from_reference (expr);
}
@@ -9352,6 +9359,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
error ("template constraint failure");
diagnose_constraints (input_location, gen_tmpl, arglist);
}
@@ -9710,6 +9718,7 @@ finish_template_variable (tree var, tsubst_flags_t complain)
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
error ("use of invalid variable template %qE", var);
diagnose_constraints (location_of (var), templ, arglist);
}
@@ -16740,7 +16749,17 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
else
{
int const_init = false;
+ unsigned int cnt = 0;
+ tree first = NULL_TREE, ndecl = error_mark_node;
maybe_push_decl (decl);
+
+ if (VAR_P (decl)
+ && DECL_DECOMPOSITION_P (decl)
+ && TREE_TYPE (pattern_decl) != error_mark_node)
+ ndecl = tsubst_decomp_names (decl, pattern_decl, args,
+ complain, in_decl, &first,
+ &cnt);
+
if (VAR_P (decl)
&& DECL_PRETTY_FUNCTION_P (decl))
{
@@ -16756,23 +16775,14 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
if (VAR_P (decl))
const_init = (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P
(pattern_decl));
- if (VAR_P (decl)
- && DECL_DECOMPOSITION_P (decl)
- && TREE_TYPE (pattern_decl) != error_mark_node)
- {
- unsigned int cnt;
- tree first;
- tree ndecl
- = tsubst_decomp_names (decl, pattern_decl, args,
- complain, in_decl, &first, &cnt);
- if (ndecl != error_mark_node)
- cp_maybe_mangle_decomp (ndecl, first, cnt);
- cp_finish_decl (decl, init, const_init, NULL_TREE, 0);
- if (ndecl != error_mark_node)
- cp_finish_decomp (ndecl, first, cnt);
- }
- else
- cp_finish_decl (decl, init, const_init, NULL_TREE, 0);
+
+ if (ndecl != error_mark_node)
+ cp_maybe_mangle_decomp (ndecl, first, cnt);
+
+ cp_finish_decl (decl, init, const_init, NULL_TREE, 0);
+
+ if (ndecl != error_mark_node)
+ cp_finish_decomp (ndecl, first, cnt);
}
}
}
@@ -16805,6 +16815,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
stmt = (processing_template_decl
? begin_range_for_stmt (NULL_TREE, NULL_TREE)
: begin_for_stmt (NULL_TREE, NULL_TREE));
+ RECUR (RANGE_FOR_INIT_STMT (t));
decl = RANGE_FOR_DECL (t);
decl = tsubst (decl, args, complain, in_decl);
maybe_push_decl (decl);
@@ -16822,6 +16833,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
RANGE_FOR_IVDEP (stmt) = RANGE_FOR_IVDEP (t);
RANGE_FOR_UNROLL (stmt) = RANGE_FOR_UNROLL (t);
finish_range_for_decl (stmt, decl, expr);
+ if (decomp_first && decl != error_mark_node)
+ cp_finish_decomp (decl, decomp_first, decomp_cnt);
}
else
{
@@ -26067,7 +26080,7 @@ listify (tree arg)
if (!std_init_list || !DECL_CLASS_TEMPLATE_P (std_init_list))
{
gcc_rich_location richloc (input_location);
- maybe_add_include_fixit (&richloc, "<initializer_list>");
+ maybe_add_include_fixit (&richloc, "<initializer_list>", false);
error_at (&richloc,
"deducing from brace-enclosed initializer list"
" requires %<#include <initializer_list>%>");
@@ -26108,7 +26121,7 @@ struct auto_hash : default_hash_traits<tree>
inline hashval_t
auto_hash::hash (tree t)
{
- if (tree c = PLACEHOLDER_TYPE_CONSTRAINTS (t))
+ if (tree c = NON_ERROR (PLACEHOLDER_TYPE_CONSTRAINTS (t)))
/* Matching constrained-type-specifiers denote the same template
parameter, so hash the constraint. */
return hash_placeholder_constraint (c);
@@ -26867,7 +26880,7 @@ do_auto_deduction (tree type, tree init, tree auto_node,
/* Check any placeholder constraints against the deduced type. */
if (flag_concepts && !processing_template_decl)
- if (tree constr = PLACEHOLDER_TYPE_CONSTRAINTS (auto_node))
+ if (tree constr = NON_ERROR (PLACEHOLDER_TYPE_CONSTRAINTS (auto_node)))
{
/* Use the deduced type to check the associated constraints. If we
have a partial-concept-id, rebuild the argument list so that
@@ -26885,6 +26898,7 @@ do_auto_deduction (tree type, tree init, tree auto_node,
{
if (complain & tf_warning_or_error)
{
+ auto_diagnostic_group d;
switch (context)
{
case adc_unspecified:
@@ -27537,6 +27551,8 @@ declare_integer_pack (void)
NULL_TREE, ECF_CONST);
DECL_DECLARED_CONSTEXPR_P (ipfn) = true;
DECL_BUILT_IN_CLASS (ipfn) = BUILT_IN_FRONTEND;
+ DECL_FUNCTION_CODE (ipfn)
+ = (enum built_in_function) (int) CP_BUILT_IN_INTEGER_PACK;
}
/* Set up the hash tables for template instantiations. */
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 6692fb7..94a9219 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -317,7 +317,7 @@ typeid_ok_p (void)
if (!COMPLETE_TYPE_P (const_type_info_type_node))
{
gcc_rich_location richloc (input_location);
- maybe_add_include_fixit (&richloc, "<typeinfo>");
+ maybe_add_include_fixit (&richloc, "<typeinfo>", false);
error_at (&richloc,
"must %<#include <typeinfo>%> before using"
" %<typeid%>");
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index c2860b0..d700fe3 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -1911,6 +1911,7 @@ check_final_overrider (tree overrider, tree basefn)
/* GNU extension, allow trivial pointer conversions such as
converting to void *, or qualification conversion. */
{
+ auto_diagnostic_group d;
if (pedwarn (DECL_SOURCE_LOCATION (overrider), 0,
"invalid covariant return type for %q#D", overrider))
inform (DECL_SOURCE_LOCATION (basefn),
@@ -1927,12 +1928,14 @@ check_final_overrider (tree overrider, tree basefn)
{
if (fail == 1)
{
+ auto_diagnostic_group d;
error ("invalid covariant return type for %q+#D", overrider);
inform (DECL_SOURCE_LOCATION (basefn),
"overridden function is %q#D", basefn);
}
else
{
+ auto_diagnostic_group d;
error ("conflicting return type specified for %q+#D", overrider);
inform (DECL_SOURCE_LOCATION (basefn),
"overridden function is %q#D", basefn);
@@ -1949,6 +1952,7 @@ check_final_overrider (tree overrider, tree basefn)
if (!comp_except_specs (base_throw, over_throw, ce_derived))
{
+ auto_diagnostic_group d;
error ("looser throw specifier for %q+#F", overrider);
inform (DECL_SOURCE_LOCATION (basefn),
"overridden function is %q#F", basefn);
@@ -1962,6 +1966,7 @@ check_final_overrider (tree overrider, tree basefn)
&& !tx_safe_fn_type_p (base_type)
&& !tx_safe_fn_type_p (over_type))
{
+ auto_diagnostic_group d;
error ("conflicting type attributes specified for %q+#D", overrider);
inform (DECL_SOURCE_LOCATION (basefn),
"overridden function is %q#D", basefn);
@@ -1978,6 +1983,7 @@ check_final_overrider (tree overrider, tree basefn)
&& !lookup_attribute ("transaction_safe_dynamic",
DECL_ATTRIBUTES (basefn)))
{
+ auto_diagnostic_group d;
error_at (DECL_SOURCE_LOCATION (overrider),
"%qD declared %<transaction_safe_dynamic%>", overrider);
inform (DECL_SOURCE_LOCATION (basefn),
@@ -1988,6 +1994,7 @@ check_final_overrider (tree overrider, tree basefn)
{
if (DECL_DELETED_FN (overrider))
{
+ auto_diagnostic_group d;
error ("deleted function %q+D overriding non-deleted function",
overrider);
inform (DECL_SOURCE_LOCATION (basefn),
@@ -1996,6 +2003,7 @@ check_final_overrider (tree overrider, tree basefn)
}
else
{
+ auto_diagnostic_group d;
error ("non-deleted function %q+D overriding deleted function",
overrider);
inform (DECL_SOURCE_LOCATION (basefn),
@@ -2005,6 +2013,7 @@ check_final_overrider (tree overrider, tree basefn)
}
if (DECL_FINAL_P (basefn))
{
+ auto_diagnostic_group d;
error ("virtual function %q+D overriding final function", overrider);
inform (DECL_SOURCE_LOCATION (basefn),
"overridden function is %qD", basefn);
@@ -2089,6 +2098,7 @@ look_for_overrides_r (tree type, tree fndecl)
{
/* A static member function cannot match an inherited
virtual member function. */
+ auto_diagnostic_group d;
error ("%q+#D cannot be declared", fndecl);
error (" since %q+#D declared in base class", fn);
}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index bfdca50..bf3c63a 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1101,8 +1101,8 @@ begin_range_for_stmt (tree scope, tree init)
{
begin_maybe_infinite_loop (boolean_false_node);
- tree r = build_stmt (input_location, RANGE_FOR_STMT,
- NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE);
+ tree r = build_stmt (input_location, RANGE_FOR_STMT, NULL_TREE, NULL_TREE,
+ NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE);
if (scope == NULL_TREE)
{
@@ -1110,22 +1110,23 @@ begin_range_for_stmt (tree scope, tree init)
scope = begin_for_scope (&init);
}
- /* RANGE_FOR_STMTs do not use nor save the init tree, so we
- pop it now. */
- if (init)
- pop_stmt_list (init);
+ /* Since C++20, RANGE_FOR_STMTs can use the init tree, so save it. */
+ RANGE_FOR_INIT_STMT (r) = init;
RANGE_FOR_SCOPE (r) = scope;
return r;
}
/* Finish the head of a range-based for statement, which may
- be given by RANGE_FOR_STMT. DECL must be the declaration
+ be given by RANGE_FOR_STMT. DECL must be the declaration
and EXPR must be the loop expression. */
void
finish_range_for_decl (tree range_for_stmt, tree decl, tree expr)
{
+ if (processing_template_decl)
+ RANGE_FOR_INIT_STMT (range_for_stmt)
+ = pop_stmt_list (RANGE_FOR_INIT_STMT (range_for_stmt));
RANGE_FOR_DECL (range_for_stmt) = decl;
RANGE_FOR_EXPR (range_for_stmt) = expr;
add_stmt (range_for_stmt);
@@ -1532,7 +1533,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
effectively const. */
|| (CLASS_TYPE_P (TREE_TYPE (operand))
&& C_TYPE_FIELDS_READONLY (TREE_TYPE (operand)))))
- cxx_readonly_error (operand, lv_asm);
+ cxx_readonly_error (input_location, operand, lv_asm);
tree *op = &operand;
while (TREE_CODE (*op) == COMPOUND_EXPR)
@@ -2546,8 +2547,7 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
if ((complain & tf_warning)
&& TREE_CODE (fn) == FUNCTION_DECL
- && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (fn) == BUILT_IN_MEMSET
+ && fndecl_built_in_p (fn, BUILT_IN_MEMSET)
&& vec_safe_length (*args) == 3
&& !any_type_dependent_arguments_p (*args))
{
@@ -6878,7 +6878,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
handle_map_references:
if (!remove
&& !processing_template_decl
- && (ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP
+ && ort != C_ORT_DECLARE_SIMD
&& TYPE_REF_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
{
t = OMP_CLAUSE_DECL (c);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 7e2a77b..c6f216d 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -415,10 +415,17 @@ cp_stabilize_reference (tree ref)
bool
builtin_valid_in_constant_expr_p (const_tree decl)
{
- if (!(TREE_CODE (decl) == FUNCTION_DECL
- && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL))
- /* Not a built-in. */
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ /* Not a function. */
return false;
+ if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL)
+ {
+ if (fndecl_built_in_p (decl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
+ BUILT_IN_FRONTEND))
+ return true;
+ /* Not a built-in. */
+ return false;
+ }
switch (DECL_FUNCTION_CODE (decl))
{
/* These always have constant results like the corresponding
@@ -4023,6 +4030,7 @@ maybe_warn_parm_abi (tree t, location_t loc)
&& classtype_has_non_deleted_move_ctor (t))
{
bool w;
+ auto_diagnostic_group d;
if (flag_abi_version > 12)
w = warning_at (loc, OPT_Wabi, "-fabi-version=13 (GCC 8.2) fixes the "
"calling convention for %qT, which was accidentally "
@@ -4035,6 +4043,7 @@ maybe_warn_parm_abi (tree t, location_t loc)
return;
}
+ auto_diagnostic_group d;
if (warning_at (loc, OPT_Wabi, "the calling convention for %qT changes in "
"-fabi-version=13 (GCC 8.2)", t))
inform (location_of (t), " because all of its copy and move "
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 1335da5..e993220 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -63,6 +63,8 @@ static tree lookup_destructor (tree, tree, tree, tsubst_flags_t);
static void error_args_num (location_t, tree, bool);
static int convert_arguments (tree, vec<tree, va_gc> **, tree, int,
tsubst_flags_t);
+static bool is_std_move_p (tree);
+static bool is_std_forward_p (tree);
/* Do `exp = require_complete_type (exp);' to make sure exp
does not have an incomplete type. (That includes void types.)
@@ -1691,6 +1693,7 @@ cxx_sizeof_expr (tree e, tsubst_flags_t complain)
&& DECL_ARRAY_PARAMETER_P (e)
&& (complain & tf_warning))
{
+ auto_diagnostic_group d;
if (warning (OPT_Wsizeof_array_argument, "%<sizeof%> on array function "
"parameter %qE will return size of %qT", e, TREE_TYPE (e)))
inform (DECL_SOURCE_LOCATION (e), "declared here");
@@ -2208,6 +2211,8 @@ string_conv_p (const_tree totype, const_tree exp, int warn)
&& !same_type_p (t, wchar_type_node))
return 0;
+ location_t loc = EXPR_LOC_OR_LOC (exp, input_location);
+
STRIP_ANY_LOCATION_WRAPPER (exp);
if (TREE_CODE (exp) == STRING_CST)
@@ -2230,13 +2235,13 @@ string_conv_p (const_tree totype, const_tree exp, int warn)
if (warn)
{
if (cxx_dialect >= cxx11)
- pedwarn (input_location, OPT_Wwrite_strings,
+ pedwarn (loc, OPT_Wwrite_strings,
"ISO C++ forbids converting a string constant to %qT",
totype);
else
- warning (OPT_Wwrite_strings,
- "deprecated conversion from string constant to %qT",
- totype);
+ warning_at (loc, OPT_Wwrite_strings,
+ "deprecated conversion from string constant to %qT",
+ totype);
}
return 1;
@@ -3697,6 +3702,7 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params,
&& (complain & tf_error)
&& !constraints_satisfied_p (function))
{
+ auto_diagnostic_group d;
error ("cannot call function %qD", function);
location_t loc = DECL_SOURCE_LOCATION (function);
diagnose_constraints (loc, function, NULL_TREE);
@@ -4465,13 +4471,16 @@ cp_build_binary_op (location_t location,
&& DECL_ARRAY_PARAMETER_P (first_arg)
&& warn_sizeof_array_argument)
&& (complain & tf_warning))
- if (warning_at (location, OPT_Wsizeof_pointer_div,
- "division %<sizeof (%T) / sizeof (%T)%> does "
- "not compute the number of array elements",
+ {
+ auto_diagnostic_group d;
+ if (warning_at (location, OPT_Wsizeof_pointer_div,
+ "division %<sizeof (%T) / sizeof (%T)%> does "
+ "not compute the number of array elements",
type0, type1))
- if (DECL_P (first_arg))
- inform (DECL_SOURCE_LOCATION (first_arg),
- "first %<sizeof%> operand was declared here");
+ if (DECL_P (first_arg))
+ inform (DECL_SOURCE_LOCATION (first_arg),
+ "first %<sizeof%> operand was declared here");
+ }
}
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
@@ -4764,12 +4773,15 @@ cp_build_binary_op (location_t location,
else
result_type = type0;
- if (char_type_p (TREE_TYPE (orig_op1))
- && warning (OPT_Wpointer_compare,
- "comparison between pointer and zero character "
- "constant"))
- inform (input_location,
- "did you mean to dereference the pointer?");
+ if (char_type_p (TREE_TYPE (orig_op1)))
+ {
+ auto_diagnostic_group d;
+ if (warning (OPT_Wpointer_compare,
+ "comparison between pointer and zero character "
+ "constant"))
+ inform (input_location,
+ "did you mean to dereference the pointer?");
+ }
warn_for_null_address (location, op0, complain);
}
else if (((code1 == POINTER_TYPE || TYPE_PTRDATAMEM_P (type1))
@@ -4784,12 +4796,15 @@ cp_build_binary_op (location_t location,
else
result_type = type1;
- if (char_type_p (TREE_TYPE (orig_op0))
- && warning (OPT_Wpointer_compare,
- "comparison between pointer and zero character "
- "constant"))
- inform (input_location,
- "did you mean to dereference the pointer?");
+ if (char_type_p (TREE_TYPE (orig_op0)))
+ {
+ auto_diagnostic_group d;
+ if (warning (OPT_Wpointer_compare,
+ "comparison between pointer and zero character "
+ "constant"))
+ inform (input_location,
+ "did you mean to dereference the pointer?");
+ }
warn_for_null_address (location, op1, complain);
}
else if ((code0 == POINTER_TYPE && code1 == POINTER_TYPE)
@@ -6215,9 +6230,10 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
|| TREE_READONLY (arg))
{
if (complain & tf_error)
- cxx_readonly_error (arg, ((code == PREINCREMENT_EXPR
- || code == POSTINCREMENT_EXPR)
- ? lv_increment : lv_decrement));
+ cxx_readonly_error (location, arg,
+ ((code == PREINCREMENT_EXPR
+ || code == POSTINCREMENT_EXPR)
+ ? lv_increment : lv_decrement));
else
return error_mark_node;
}
@@ -8146,7 +8162,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
&& C_TYPE_FIELDS_READONLY (lhstype))))
{
if (complain & tf_error)
- cxx_readonly_error (lhs, lv_assign);
+ cxx_readonly_error (loc, lhs, lv_assign);
return error_mark_node;
}
@@ -8804,13 +8820,9 @@ convert_for_assignment (tree type, tree rhs,
parmnum, complain, flags);
}
else if (fndecl)
- {
- error_at (cp_expr_loc_or_loc (rhs, input_location),
- "cannot convert %qH to %qI",
- rhstype, type);
- inform (get_fndecl_argument_location (fndecl, parmnum),
- " initializing argument %P of %qD", parmnum, fndecl);
- }
+ complain_about_bad_argument (cp_expr_location (rhs),
+ rhstype, type,
+ fndecl, parmnum);
else
switch (errtype)
{
@@ -9047,6 +9059,15 @@ maybe_warn_about_returning_address_of_local (tree retval)
STRIP_NOPS (whats_returned);
}
+ /* As a special case, we handle a call to std::move or std::forward. */
+ if (TREE_CODE (whats_returned) == CALL_EXPR
+ && (is_std_move_p (whats_returned)
+ || is_std_forward_p (whats_returned)))
+ {
+ tree arg = CALL_EXPR_ARG (whats_returned, 0);
+ return maybe_warn_about_returning_address_of_local (arg);
+ }
+
if (TREE_CODE (whats_returned) != ADDR_EXPR)
return false;
whats_returned = TREE_OPERAND (whats_returned, 0);
@@ -9076,6 +9097,7 @@ maybe_warn_about_returning_address_of_local (tree retval)
|| TREE_PUBLIC (whats_returned)))
{
bool w = false;
+ auto_diagnostic_group d;
if (TYPE_REF_P (valtype))
w = warning_at (loc, OPT_Wreturn_local_addr,
"reference to local variable %qD returned",
@@ -9102,6 +9124,148 @@ maybe_warn_about_returning_address_of_local (tree retval)
return false;
}
+/* Returns true if DECL is in the std namespace. */
+
+static bool
+decl_in_std_namespace_p (tree decl)
+{
+ return (decl != NULL_TREE
+ && DECL_NAMESPACE_STD_P (decl_namespace_context (decl)));
+}
+
+/* Returns true if FN, a CALL_EXPR, is a call to std::forward. */
+
+static bool
+is_std_forward_p (tree fn)
+{
+ /* std::forward only takes one argument. */
+ if (call_expr_nargs (fn) != 1)
+ return false;
+
+ tree fndecl = cp_get_callee_fndecl_nofold (fn);
+ if (!decl_in_std_namespace_p (fndecl))
+ return false;
+
+ tree name = DECL_NAME (fndecl);
+ return name && id_equal (name, "forward");
+}
+
+/* Returns true if FN, a CALL_EXPR, is a call to std::move. */
+
+static bool
+is_std_move_p (tree fn)
+{
+ /* std::move only takes one argument. */
+ if (call_expr_nargs (fn) != 1)
+ return false;
+
+ tree fndecl = cp_get_callee_fndecl_nofold (fn);
+ if (!decl_in_std_namespace_p (fndecl))
+ return false;
+
+ tree name = DECL_NAME (fndecl);
+ return name && id_equal (name, "move");
+}
+
+/* Returns true if RETVAL is a good candidate for the NRVO as per
+ [class.copy.elision]. FUNCTYPE is the type the function is declared
+ to return. */
+
+static bool
+can_do_nrvo_p (tree retval, tree functype)
+{
+ tree result = DECL_RESULT (current_function_decl);
+ return (retval != NULL_TREE
+ && !processing_template_decl
+ /* Must be a local, automatic variable. */
+ && VAR_P (retval)
+ && DECL_CONTEXT (retval) == current_function_decl
+ && !TREE_STATIC (retval)
+ /* And not a lambda or anonymous union proxy. */
+ && !DECL_HAS_VALUE_EXPR_P (retval)
+ && (DECL_ALIGN (retval) <= DECL_ALIGN (result))
+ /* The cv-unqualified type of the returned value must be the
+ same as the cv-unqualified return type of the
+ function. */
+ && same_type_p ((TYPE_MAIN_VARIANT (TREE_TYPE (retval))),
+ (TYPE_MAIN_VARIANT (functype)))
+ /* And the returned value must be non-volatile. */
+ && !TYPE_VOLATILE (TREE_TYPE (retval)));
+}
+
+/* Returns true if we should treat RETVAL, an expression being returned,
+ as if it were designated by an rvalue. See [class.copy.elision].
+ PARM_P is true if a function parameter is OK in this context. */
+
+bool
+treat_lvalue_as_rvalue_p (tree retval, bool parm_ok)
+{
+ return ((cxx_dialect != cxx98)
+ && ((VAR_P (retval) && !DECL_HAS_VALUE_EXPR_P (retval))
+ || (parm_ok && TREE_CODE (retval) == PARM_DECL))
+ && DECL_CONTEXT (retval) == current_function_decl
+ && !TREE_STATIC (retval));
+}
+
+/* Warn about wrong usage of std::move in a return statement. RETVAL
+ is the expression we are returning; FUNCTYPE is the type the function
+ is declared to return. */
+
+static void
+maybe_warn_pessimizing_move (tree retval, tree functype)
+{
+ if (!(warn_pessimizing_move || warn_redundant_move))
+ return;
+
+ location_t loc = cp_expr_loc_or_loc (retval, input_location);
+
+ /* C++98 doesn't know move. */
+ if (cxx_dialect < cxx11)
+ return;
+
+ /* Wait until instantiation time, since we can't gauge if we should do
+ the NRVO until then. */
+ if (processing_template_decl)
+ return;
+
+ /* This is only interesting for class types. */
+ if (!CLASS_TYPE_P (functype))
+ return;
+
+ /* We're looking for *std::move<T&> (&arg). */
+ if (REFERENCE_REF_P (retval)
+ && TREE_CODE (TREE_OPERAND (retval, 0)) == CALL_EXPR)
+ {
+ tree fn = TREE_OPERAND (retval, 0);
+ if (is_std_move_p (fn))
+ {
+ tree arg = CALL_EXPR_ARG (fn, 0);
+ STRIP_NOPS (arg);
+ if (TREE_CODE (arg) == ADDR_EXPR)
+ arg = TREE_OPERAND (arg, 0);
+ arg = convert_from_reference (arg);
+ /* Warn if we could do copy elision were it not for the move. */
+ if (can_do_nrvo_p (arg, functype))
+ {
+ auto_diagnostic_group d;
+ if (warning_at (loc, OPT_Wpessimizing_move,
+ "moving a local object in a return statement "
+ "prevents copy elision"))
+ inform (loc, "remove %<std::move%> call");
+ }
+ /* Warn if the move is redundant. It is redundant when we would
+ do maybe-rvalue overload resolution even without std::move. */
+ else if (treat_lvalue_as_rvalue_p (arg, /*parm_ok*/true))
+ {
+ auto_diagnostic_group d;
+ if (warning_at (loc, OPT_Wredundant_move,
+ "redundant move in return statement"))
+ inform (loc, "remove %<std::move%> call");
+ }
+ }
+ }
+}
+
/* Check that returning RETVAL from the current function is valid.
Return an expression explicitly showing all conversions required to
change RETVAL into the function return type, and to assign it to
@@ -9119,7 +9283,6 @@ check_return_expr (tree retval, bool *no_warning)
the declared type is incomplete. */
tree functype;
int fn_returns_value_p;
- bool named_return_value_okay_p;
*no_warning = false;
@@ -9331,24 +9494,7 @@ check_return_expr (tree retval, bool *no_warning)
See finish_function and finalize_nrv for the rest of this optimization. */
- named_return_value_okay_p =
- (retval != NULL_TREE
- && !processing_template_decl
- /* Must be a local, automatic variable. */
- && VAR_P (retval)
- && DECL_CONTEXT (retval) == current_function_decl
- && ! TREE_STATIC (retval)
- /* And not a lambda or anonymous union proxy. */
- && !DECL_HAS_VALUE_EXPR_P (retval)
- && (DECL_ALIGN (retval) <= DECL_ALIGN (result))
- /* The cv-unqualified type of the returned value must be the
- same as the cv-unqualified return type of the
- function. */
- && same_type_p ((TYPE_MAIN_VARIANT (TREE_TYPE (retval))),
- (TYPE_MAIN_VARIANT (functype)))
- /* And the returned value must be non-volatile. */
- && ! TYPE_VOLATILE (TREE_TYPE (retval)));
-
+ bool named_return_value_okay_p = can_do_nrvo_p (retval, functype);
if (fn_returns_value_p && flag_elide_constructors)
{
if (named_return_value_okay_p
@@ -9364,6 +9510,9 @@ check_return_expr (tree retval, bool *no_warning)
if (!retval)
return NULL_TREE;
+ if (!named_return_value_okay_p)
+ maybe_warn_pessimizing_move (retval, functype);
+
/* Do any required conversions. */
if (retval == result || DECL_CONSTRUCTOR_P (current_function_decl))
/* No conversions are required. */
@@ -9391,11 +9540,7 @@ check_return_expr (tree retval, bool *no_warning)
Note that these conditions are similar to, but not as strict as,
the conditions for the named return value optimization. */
bool converted = false;
- if ((cxx_dialect != cxx98)
- && ((VAR_P (retval) && !DECL_HAS_VALUE_EXPR_P (retval))
- || TREE_CODE (retval) == PARM_DECL)
- && DECL_CONTEXT (retval) == current_function_decl
- && !TREE_STATIC (retval)
+ if (treat_lvalue_as_rvalue_p (retval, /*parm_ok*/true)
/* This is only interesting for class type. */
&& CLASS_TYPE_P (functype))
{
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 91aa5a6..fec1db0 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -67,28 +67,28 @@ binfo_or_else (tree base, tree type)
value may not be changed thereafter. */
void
-cxx_readonly_error (tree arg, enum lvalue_use errstring)
+cxx_readonly_error (location_t loc, tree arg, enum lvalue_use errstring)
{
/* This macro is used to emit diagnostics to ensure that all format
strings are complete sentences, visible to gettext and checked at
compile time. */
-#define ERROR_FOR_ASSIGNMENT(AS, ASM, IN, DE, ARG) \
+#define ERROR_FOR_ASSIGNMENT(LOC, AS, ASM, IN, DE, ARG) \
do { \
switch (errstring) \
{ \
case lv_assign: \
- error(AS, ARG); \
+ error_at (LOC, AS, ARG); \
break; \
case lv_asm: \
- error(ASM, ARG); \
+ error_at (LOC, ASM, ARG); \
break; \
case lv_increment: \
- error (IN, ARG); \
+ error_at (LOC, IN, ARG); \
break; \
- case lv_decrement: \
- error (DE, ARG); \
+ case lv_decrement: \
+ error_at (LOC, DE, ARG); \
break; \
default: \
gcc_unreachable (); \
@@ -101,32 +101,25 @@ cxx_readonly_error (tree arg, enum lvalue_use errstring)
&& DECL_LANG_SPECIFIC (arg)
&& DECL_IN_AGGR_P (arg)
&& !TREE_STATIC (arg))
- ERROR_FOR_ASSIGNMENT (G_("assignment of "
- "constant field %qD"),
- G_("constant field %qD "
- "used as %<asm%> output"),
- G_("increment of "
- "constant field %qD"),
- G_("decrement of "
- "constant field %qD"),
+ ERROR_FOR_ASSIGNMENT (loc,
+ G_("assignment of constant field %qD"),
+ G_("constant field %qD used as %<asm%> output"),
+ G_("increment of constant field %qD"),
+ G_("decrement of constant field %qD"),
arg);
else if (INDIRECT_REF_P (arg)
&& TYPE_REF_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
&& (VAR_P (TREE_OPERAND (arg, 0))
|| TREE_CODE (TREE_OPERAND (arg, 0)) == PARM_DECL))
- ERROR_FOR_ASSIGNMENT (G_("assignment of "
- "read-only reference %qD"),
- G_("read-only reference %qD "
- "used as %<asm%> output"),
- G_("increment of "
- "read-only reference %qD"),
- G_("decrement of "
- "read-only reference %qD"),
- TREE_OPERAND (arg, 0));
+ ERROR_FOR_ASSIGNMENT (loc,
+ G_("assignment of read-only reference %qD"),
+ G_("read-only reference %qD used as %<asm%> output"),
+ G_("increment of read-only reference %qD"),
+ G_("decrement of read-only reference %qD"),
+ TREE_OPERAND (arg, 0));
else
- readonly_error (input_location, arg, errstring);
+ readonly_error (loc, arg, errstring);
}
-
/* Structure that holds information about declarations whose type was
incomplete and we could not check whether it was abstract or not. */
@@ -315,6 +308,7 @@ abstract_virtuals_error_sfinae (tree decl, tree type, abstract_class_use use,
if (!(complain & tf_error))
return 1;
+ auto_diagnostic_group d;
if (decl)
{
if (VAR_P (decl))
@@ -813,6 +807,11 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
/* Digest the specified initializer into an expression. */
value = digest_init_flags (type, init, flags, tf_warning_or_error);
+ if (TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_STRING_FLAG (TREE_TYPE (type))
+ && TREE_CODE (value) == CONSTRUCTOR)
+ value = braced_list_to_string (type, value);
+
value = extend_ref_init_temps (decl, value, cleanups);
/* In C++11 constant expression is a semantic, not syntactic, property.
@@ -837,7 +836,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
value = cxx_constant_init (value, decl);
}
else
- value = maybe_constant_init (value, decl);
+ value = maybe_constant_init (value, decl, true);
if (TREE_CODE (value) == CONSTRUCTOR && cp_has_mutable_p (type))
/* Poison this CONSTRUCTOR so it can't be copied to another
constexpr variable. */
@@ -875,10 +874,12 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
}
-/* Give diagnostic about narrowing conversions within { }. */
+/* Give diagnostic about narrowing conversions within { }, or as part of
+ a converted constant expression. If CONST_ONLY, only check
+ constants. */
bool
-check_narrowing (tree type, tree init, tsubst_flags_t complain)
+check_narrowing (tree type, tree init, tsubst_flags_t complain, bool const_only)
{
tree ftype = unlowered_expr_type (init);
bool ok = true;
@@ -886,7 +887,9 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain)
if (((!warn_narrowing || !(complain & tf_warning))
&& cxx_dialect == cxx98)
- || !ARITHMETIC_TYPE_P (type))
+ || !ARITHMETIC_TYPE_P (type)
+ /* Don't emit bogus warnings with e.g. value-dependent trees. */
+ || instantiation_dependent_expression_p (init))
return ok;
if (BRACE_ENCLOSED_INITIALIZER_P (init)
@@ -902,9 +905,13 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain)
return ok;
}
- init = fold_non_dependent_expr (init, complain);
+ init = maybe_constant_value (init);
+
+ /* If we were asked to only check constants, return early. */
+ if (const_only && !TREE_CONSTANT (init))
+ return ok;
- if (TREE_CODE (type) == INTEGER_TYPE
+ if (CP_INTEGRAL_TYPE_P (type)
&& TREE_CODE (ftype) == REAL_TYPE)
ok = false;
else if (INTEGRAL_OR_ENUMERATION_TYPE_P (ftype)
@@ -967,7 +974,7 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain)
{
if (complain & tf_warning)
warning_at (loc, OPT_Wnarrowing, "narrowing conversion of %qE "
- "from %qH to %qI inside { } is ill-formed in C++11",
+ "from %qH to %qI is ill-formed in C++11",
init, ftype, type);
ok = true;
}
@@ -975,10 +982,10 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain)
{
if (complain & tf_warning_or_error)
{
+ auto_diagnostic_group d;
if ((!almost_ok || pedantic)
&& pedwarn (loc, OPT_Wnarrowing,
- "narrowing conversion of %qE "
- "from %qH to %qI inside { }",
+ "narrowing conversion of %qE from %qH to %qI",
init, ftype, type)
&& almost_ok)
inform (loc, " the expression has a constant value but is not "
@@ -991,8 +998,8 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain)
int savederrorcount = errorcount;
global_dc->pedantic_errors = 1;
pedwarn (loc, OPT_Wnarrowing,
- "narrowing conversion of %qE from %qH to %qI "
- "inside { }", init, ftype, type);
+ "narrowing conversion of %qE from %qH to %qI ",
+ init, ftype, type);
if (errorcount == savederrorcount)
ok = true;
global_dc->pedantic_errors = flag_pedantic_errors;
@@ -1105,8 +1112,13 @@ digest_init_r (tree type, tree init, int nested, int flags,
counted in the length of the constant, but in C++ this would
be invalid. */
if (size < TREE_STRING_LENGTH (init))
- permerror (loc, "initializer-string for array "
- "of chars is too long");
+ {
+ permerror (loc, "initializer-string for array "
+ "of chars is too long");
+
+ init = build_string (size, TREE_STRING_POINTER (init));
+ TREE_TYPE (init) = type;
+ }
}
return init;
}
@@ -2203,7 +2215,7 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
know what we're doing. */
tree
-add_exception_specifier (tree list, tree spec, int complain)
+add_exception_specifier (tree list, tree spec, tsubst_flags_t complain)
{
bool ok;
tree core = spec;
diff --git a/gcc/cppbuiltin.c b/gcc/cppbuiltin.c
index de8cd33..7591229 100644
--- a/gcc/cppbuiltin.c
+++ b/gcc/cppbuiltin.c
@@ -25,7 +25,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "version.h"
#include "flags.h"
-#include "cpp-id-data.h"
+#include "cpplib.h"
#include "cppbuiltin.h"
@@ -110,9 +110,6 @@ define_builtin_macros_for_compilation_flags (cpp_reader *pfile)
cpp_define_formatted (pfile, "__FINITE_MATH_ONLY__=%d",
flag_finite_math_only);
-
- if (flag_check_pointer_bounds)
- cpp_define (pfile, "__CHKP__");
}
diff --git a/gcc/cse.c b/gcc/cse.c
index 4e94152..3d7888b 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -559,6 +559,7 @@ static struct table_elt *insert_with_costs (rtx, struct table_elt *, unsigned,
static struct table_elt *insert (rtx, struct table_elt *, unsigned,
machine_mode);
static void merge_equiv_classes (struct table_elt *, struct table_elt *);
+static void invalidate_reg (rtx, bool);
static void invalidate (rtx, machine_mode);
static void remove_invalid_refs (unsigned int);
static void remove_invalid_subreg_refs (unsigned int, poly_uint64,
@@ -1818,7 +1819,85 @@ check_dependence (const_rtx x, rtx exp, machine_mode mode, rtx addr)
}
return false;
}
-
+
+/* Remove from the hash table, or mark as invalid, all expressions whose
+ values could be altered by storing in register X.
+
+ CLOBBER_HIGH is set if X was part of a CLOBBER_HIGH expression. */
+
+static void
+invalidate_reg (rtx x, bool clobber_high)
+{
+ gcc_assert (GET_CODE (x) == REG);
+
+ /* If X is a register, dependencies on its contents are recorded
+ through the qty number mechanism. Just change the qty number of
+ the register, mark it as invalid for expressions that refer to it,
+ and remove it itself. */
+ unsigned int regno = REGNO (x);
+ unsigned int hash = HASH (x, GET_MODE (x));
+
+ /* Remove REGNO from any quantity list it might be on and indicate
+ that its value might have changed. If it is a pseudo, remove its
+ entry from the hash table.
+
+ For a hard register, we do the first two actions above for any
+ additional hard registers corresponding to X. Then, if any of these
+ registers are in the table, we must remove any REG entries that
+ overlap these registers. */
+
+ delete_reg_equiv (regno);
+ REG_TICK (regno)++;
+ SUBREG_TICKED (regno) = -1;
+
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ {
+ gcc_assert (!clobber_high);
+ remove_pseudo_from_table (x, hash);
+ }
+ else
+ {
+ HOST_WIDE_INT in_table = TEST_HARD_REG_BIT (hard_regs_in_table, regno);
+ unsigned int endregno = END_REGNO (x);
+ unsigned int rn;
+ struct table_elt *p, *next;
+
+ CLEAR_HARD_REG_BIT (hard_regs_in_table, regno);
+
+ for (rn = regno + 1; rn < endregno; rn++)
+ {
+ in_table |= TEST_HARD_REG_BIT (hard_regs_in_table, rn);
+ CLEAR_HARD_REG_BIT (hard_regs_in_table, rn);
+ delete_reg_equiv (rn);
+ REG_TICK (rn)++;
+ SUBREG_TICKED (rn) = -1;
+ }
+
+ if (in_table)
+ for (hash = 0; hash < HASH_SIZE; hash++)
+ for (p = table[hash]; p; p = next)
+ {
+ next = p->next_same_hash;
+
+ if (!REG_P (p->exp) || REGNO (p->exp) >= FIRST_PSEUDO_REGISTER)
+ continue;
+
+ if (clobber_high)
+ {
+ if (reg_is_clobbered_by_clobber_high (p->exp, x))
+ remove_from_table (p, hash);
+ }
+ else
+ {
+ unsigned int tregno = REGNO (p->exp);
+ unsigned int tendregno = END_REGNO (p->exp);
+ if (tendregno > regno && tregno < endregno)
+ remove_from_table (p, hash);
+ }
+ }
+ }
+}
+
/* Remove from the hash table, or mark as invalid, all expressions whose
values could be altered by storing in X. X is a register, a subreg, or
a memory reference with nonvarying address (because, when a memory
@@ -1841,65 +1920,7 @@ invalidate (rtx x, machine_mode full_mode)
switch (GET_CODE (x))
{
case REG:
- {
- /* If X is a register, dependencies on its contents are recorded
- through the qty number mechanism. Just change the qty number of
- the register, mark it as invalid for expressions that refer to it,
- and remove it itself. */
- unsigned int regno = REGNO (x);
- unsigned int hash = HASH (x, GET_MODE (x));
-
- /* Remove REGNO from any quantity list it might be on and indicate
- that its value might have changed. If it is a pseudo, remove its
- entry from the hash table.
-
- For a hard register, we do the first two actions above for any
- additional hard registers corresponding to X. Then, if any of these
- registers are in the table, we must remove any REG entries that
- overlap these registers. */
-
- delete_reg_equiv (regno);
- REG_TICK (regno)++;
- SUBREG_TICKED (regno) = -1;
-
- if (regno >= FIRST_PSEUDO_REGISTER)
- remove_pseudo_from_table (x, hash);
- else
- {
- HOST_WIDE_INT in_table
- = TEST_HARD_REG_BIT (hard_regs_in_table, regno);
- unsigned int endregno = END_REGNO (x);
- unsigned int tregno, tendregno, rn;
- struct table_elt *p, *next;
-
- CLEAR_HARD_REG_BIT (hard_regs_in_table, regno);
-
- for (rn = regno + 1; rn < endregno; rn++)
- {
- in_table |= TEST_HARD_REG_BIT (hard_regs_in_table, rn);
- CLEAR_HARD_REG_BIT (hard_regs_in_table, rn);
- delete_reg_equiv (rn);
- REG_TICK (rn)++;
- SUBREG_TICKED (rn) = -1;
- }
-
- if (in_table)
- for (hash = 0; hash < HASH_SIZE; hash++)
- for (p = table[hash]; p; p = next)
- {
- next = p->next_same_hash;
-
- if (!REG_P (p->exp)
- || REGNO (p->exp) >= FIRST_PSEUDO_REGISTER)
- continue;
-
- tregno = REGNO (p->exp);
- tendregno = END_REGNO (p->exp);
- if (tendregno > regno && tregno < endregno)
- remove_from_table (p, hash);
- }
- }
- }
+ invalidate_reg (x, false);
return;
case SUBREG:
@@ -4399,6 +4420,8 @@ canonicalize_insn (rtx_insn *insn, struct set **psets, int n_sets)
if (MEM_P (XEXP (x, 0)))
canon_reg (XEXP (x, 0), insn);
}
+ else if (GET_CODE (x) == CLOBBER_HIGH)
+ gcc_assert (REG_P (XEXP (x, 0)));
else if (GET_CODE (x) == USE
&& ! (REG_P (XEXP (x, 0))
&& REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER))
@@ -4430,6 +4453,8 @@ canonicalize_insn (rtx_insn *insn, struct set **psets, int n_sets)
if (MEM_P (XEXP (y, 0)))
canon_reg (XEXP (y, 0), insn);
}
+ else if (GET_CODE (y) == CLOBBER_HIGH)
+ gcc_assert (REG_P (XEXP (y, 0)));
else if (GET_CODE (y) == USE
&& ! (REG_P (XEXP (y, 0))
&& REGNO (XEXP (y, 0)) < FIRST_PSEUDO_REGISTER))
@@ -6130,6 +6155,12 @@ invalidate_from_clobbers (rtx_insn *insn)
invalidate (XEXP (ref, 0), GET_MODE (ref));
}
}
+ if (GET_CODE (x) == CLOBBER_HIGH)
+ {
+ rtx ref = XEXP (x, 0);
+ gcc_assert (REG_P (ref));
+ invalidate_reg (ref, true);
+ }
else if (GET_CODE (x) == PARALLEL)
{
int i;
@@ -6146,6 +6177,12 @@ invalidate_from_clobbers (rtx_insn *insn)
|| GET_CODE (ref) == ZERO_EXTRACT)
invalidate (XEXP (ref, 0), GET_MODE (ref));
}
+ else if (GET_CODE (y) == CLOBBER_HIGH)
+ {
+ rtx ref = XEXP (y, 0);
+ gcc_assert (REG_P (ref));
+ invalidate_reg (ref, true);
+ }
}
}
}
@@ -6163,8 +6200,17 @@ invalidate_from_sets_and_clobbers (rtx_insn *insn)
if (CALL_P (insn))
{
for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
- if (GET_CODE (XEXP (tem, 0)) == CLOBBER)
- invalidate (SET_DEST (XEXP (tem, 0)), VOIDmode);
+ {
+ rtx temx = XEXP (tem, 0);
+ if (GET_CODE (temx) == CLOBBER)
+ invalidate (SET_DEST (temx), VOIDmode);
+ else if (GET_CODE (temx) == CLOBBER_HIGH)
+ {
+ rtx temref = XEXP (temx, 0);
+ gcc_assert (REG_P (temref));
+ invalidate_reg (temref, true);
+ }
+ }
}
/* Ensure we invalidate the destination register of a CALL insn.
@@ -6191,6 +6237,12 @@ invalidate_from_sets_and_clobbers (rtx_insn *insn)
|| GET_CODE (clobbered) == ZERO_EXTRACT)
invalidate (XEXP (clobbered, 0), GET_MODE (clobbered));
}
+ else if (GET_CODE (y) == CLOBBER_HIGH)
+ {
+ rtx ref = XEXP (y, 0);
+ gcc_assert (REG_P (ref));
+ invalidate_reg (ref, true);
+ }
else if (GET_CODE (y) == SET && GET_CODE (SET_SRC (y)) == CALL)
invalidate (SET_DEST (y), VOIDmode);
}
@@ -6850,6 +6902,10 @@ count_reg_usage (rtx x, int *counts, rtx dest, int incr)
count_reg_usage (XEXP (XEXP (x, 0), 0), counts, NULL_RTX, incr);
return;
+ case CLOBBER_HIGH:
+ gcc_assert (REG_P ((XEXP (x, 0))));
+ return;
+
case SET:
/* Unless we are setting a REG, count everything in SET_DEST. */
if (!REG_P (SET_DEST (x)))
@@ -6902,7 +6958,8 @@ count_reg_usage (rtx x, int *counts, rtx dest, int incr)
|| (REG_NOTE_KIND (x) != REG_NONNEG && GET_CODE (XEXP (x,0)) == USE)
/* FUNCTION_USAGE expression lists may include (CLOBBER (mem /u)),
involving registers in the address. */
- || GET_CODE (XEXP (x, 0)) == CLOBBER)
+ || GET_CODE (XEXP (x, 0)) == CLOBBER
+ || GET_CODE (XEXP (x, 0)) == CLOBBER_HIGH)
count_reg_usage (XEXP (x, 0), counts, NULL_RTX, incr);
count_reg_usage (XEXP (x, 1), counts, NULL_RTX, incr);
@@ -6986,7 +7043,9 @@ insn_live_p (rtx_insn *insn, int *counts)
if (set_live_p (elt, insn, counts))
return true;
}
- else if (GET_CODE (elt) != CLOBBER && GET_CODE (elt) != USE)
+ else if (GET_CODE (elt) != CLOBBER
+ && GET_CODE (elt) != CLOBBER_HIGH
+ && GET_CODE (elt) != USE)
return true;
}
return false;
diff --git a/gcc/cselib.c b/gcc/cselib.c
index 5a978c1..6d3a407 100644
--- a/gcc/cselib.c
+++ b/gcc/cselib.c
@@ -54,7 +54,8 @@ static unsigned int cselib_hash_rtx (rtx, int, machine_mode);
static cselib_val *new_cselib_val (unsigned int, machine_mode, rtx);
static void add_mem_for_addr (cselib_val *, cselib_val *, rtx);
static cselib_val *cselib_lookup_mem (rtx, int);
-static void cselib_invalidate_regno (unsigned int, machine_mode);
+static void cselib_invalidate_regno (unsigned int, machine_mode,
+ const_rtx = NULL);
static void cselib_invalidate_mem (rtx);
static void cselib_record_set (rtx, cselib_val *, cselib_val *);
static void cselib_record_sets (rtx_insn *);
@@ -1661,6 +1662,7 @@ cselib_expand_value_rtx_1 (rtx orig, struct expand_value_data *evd,
/* SCRATCH must be shared because they represent distinct values. */
return orig;
case CLOBBER:
+ case CLOBBER_HIGH:
if (REG_P (XEXP (orig, 0)) && HARD_REGISTER_NUM_P (REGNO (XEXP (orig, 0))))
return orig;
break;
@@ -2163,7 +2165,8 @@ cselib_lookup (rtx x, machine_mode mode,
invalidating call clobbered registers across a call. */
static void
-cselib_invalidate_regno (unsigned int regno, machine_mode mode)
+cselib_invalidate_regno (unsigned int regno, machine_mode mode,
+ const_rtx setter)
{
unsigned int endregno;
unsigned int i;
@@ -2186,6 +2189,9 @@ cselib_invalidate_regno (unsigned int regno, machine_mode mode)
i = regno - max_value_regs;
endregno = end_hard_regno (mode, regno);
+
+ if (setter && GET_CODE (setter) == CLOBBER_HIGH)
+ gcc_assert (endregno == regno + 1);
}
else
{
@@ -2218,6 +2224,19 @@ cselib_invalidate_regno (unsigned int regno, machine_mode mode)
continue;
}
+ /* Ignore if clobber high and the register isn't clobbered. */
+ if (setter && GET_CODE (setter) == CLOBBER_HIGH)
+ {
+ gcc_assert (endregno == regno + 1);
+ const_rtx x = XEXP (setter, 0);
+ if (!reg_is_clobbered_by_clobber_high (i, GET_MODE (v->val_rtx),
+ x))
+ {
+ l = &(*l)->next;
+ continue;
+ }
+ }
+
/* We have an overlap. */
if (*l == REG_VALUES (i))
{
@@ -2352,10 +2371,10 @@ cselib_invalidate_mem (rtx mem_rtx)
*vp = &dummy_val;
}
-/* Invalidate DEST, which is being assigned to or clobbered. */
+/* Invalidate DEST, which is being assigned to or clobbered by SETTER. */
void
-cselib_invalidate_rtx (rtx dest)
+cselib_invalidate_rtx (rtx dest, const_rtx setter)
{
while (GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == ZERO_EXTRACT
@@ -2363,7 +2382,7 @@ cselib_invalidate_rtx (rtx dest)
dest = XEXP (dest, 0);
if (REG_P (dest))
- cselib_invalidate_regno (REGNO (dest), GET_MODE (dest));
+ cselib_invalidate_regno (REGNO (dest), GET_MODE (dest), setter);
else if (MEM_P (dest))
cselib_invalidate_mem (dest);
}
@@ -2371,10 +2390,10 @@ cselib_invalidate_rtx (rtx dest)
/* A wrapper for cselib_invalidate_rtx to be called via note_stores. */
static void
-cselib_invalidate_rtx_note_stores (rtx dest, const_rtx ignore ATTRIBUTE_UNUSED,
+cselib_invalidate_rtx_note_stores (rtx dest, const_rtx setter,
void *data ATTRIBUTE_UNUSED)
{
- cselib_invalidate_rtx (dest);
+ cselib_invalidate_rtx (dest, setter);
}
/* Record the result of a SET instruction. DEST is being set; the source
@@ -2775,9 +2794,12 @@ cselib_process_insn (rtx_insn *insn)
if (CALL_P (insn))
{
for (x = CALL_INSN_FUNCTION_USAGE (insn); x; x = XEXP (x, 1))
- if (GET_CODE (XEXP (x, 0)) == CLOBBER)
- cselib_invalidate_rtx (XEXP (XEXP (x, 0), 0));
- /* Flush evertything on setjmp. */
+ {
+ gcc_assert (GET_CODE (XEXP (x, 0)) != CLOBBER_HIGH);
+ if (GET_CODE (XEXP (x, 0)) == CLOBBER)
+ cselib_invalidate_rtx (XEXP (XEXP (x, 0), 0));
+ }
+ /* Flush everything on setjmp. */
if (cselib_preserve_constants
&& find_reg_note (insn, REG_SETJMP, NULL))
{
diff --git a/gcc/cselib.h b/gcc/cselib.h
index be6feaf..0005ad3 100644
--- a/gcc/cselib.h
+++ b/gcc/cselib.h
@@ -92,7 +92,7 @@ extern bool cselib_dummy_expand_value_rtx_cb (rtx, bitmap, int,
cselib_expand_callback, void *);
extern rtx cselib_subst_to_values (rtx, machine_mode);
extern rtx cselib_subst_to_values_from_insn (rtx, machine_mode, rtx_insn *);
-extern void cselib_invalidate_rtx (rtx);
+extern void cselib_invalidate_rtx (rtx, const_rtx = NULL);
extern void cselib_reset_table (unsigned int);
extern unsigned int cselib_get_next_uid (void);
diff --git a/gcc/dce.c b/gcc/dce.c
index e4d442c..7fc3fd2 100644
--- a/gcc/dce.c
+++ b/gcc/dce.c
@@ -145,6 +145,7 @@ deletable_insn_p (rtx_insn *insn, bool fast, bitmap arg_stores)
return false;
case CLOBBER:
+ case CLOBBER_HIGH:
if (fast)
{
/* A CLOBBER of a dead pseudo register serves no purpose.
@@ -213,7 +214,10 @@ static void
mark_nonreg_stores_1 (rtx dest, const_rtx pattern, void *data)
{
if (GET_CODE (pattern) != CLOBBER && !REG_P (dest))
- mark_insn ((rtx_insn *) data, true);
+ {
+ gcc_checking_assert (GET_CODE (pattern) != CLOBBER_HIGH);
+ mark_insn ((rtx_insn *) data, true);
+ }
}
@@ -224,7 +228,10 @@ static void
mark_nonreg_stores_2 (rtx dest, const_rtx pattern, void *data)
{
if (GET_CODE (pattern) != CLOBBER && !REG_P (dest))
- mark_insn ((rtx_insn *) data, false);
+ {
+ gcc_checking_assert (GET_CODE (pattern) != CLOBBER_HIGH);
+ mark_insn ((rtx_insn *) data, false);
+ }
}
diff --git a/gcc/debug.h b/gcc/debug.h
index 126e56e..3f78d06 100644
--- a/gcc/debug.h
+++ b/gcc/debug.h
@@ -256,4 +256,19 @@ extern bool dwarf2out_default_as_locview_support (void);
extern const struct gcc_debug_hooks *
dump_go_spec_init (const char *, const struct gcc_debug_hooks *);
+/* Instance discriminator mapping table. See final.c. */
+typedef hash_map<const_tree, int> decl_to_instance_map_t;
+extern decl_to_instance_map_t *decl_to_instance_map;
+
+/* Allocate decl_to_instance_map with COUNT slots to begin wtih, if it
+ * hasn't been allocated yet. */
+
+static inline decl_to_instance_map_t *
+maybe_create_decl_to_instance_map (int count = 13)
+{
+ if (!decl_to_instance_map)
+ decl_to_instance_map = new decl_to_instance_map_t (count);
+ return decl_to_instance_map;
+}
+
#endif /* !GCC_DEBUG_H */
diff --git a/gcc/defaults.h b/gcc/defaults.h
index 78a08a3..9035b33 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -1282,6 +1282,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define TARGET_PECOFF 0
#endif
+#ifndef TARGET_COFF
+#define TARGET_COFF 0
+#endif
+
#ifndef EH_RETURN_HANDLER_RTX
#define EH_RETURN_HANDLER_RTX NULL
#endif
diff --git a/gcc/df-problems.c b/gcc/df-problems.c
index 3d73bc5..7ccb57c 100644
--- a/gcc/df-problems.c
+++ b/gcc/df-problems.c
@@ -3205,7 +3205,7 @@ df_remove_dead_eq_notes (rtx_insn *insn, bitmap live)
bool deleted = false;
FOR_EACH_INSN_EQ_USE (use, insn)
- if (DF_REF_REGNO (use) > FIRST_PSEUDO_REGISTER
+ if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER
&& DF_REF_LOC (use)
&& (DF_REF_FLAGS (use) & DF_REF_IN_NOTE)
&& !bitmap_bit_p (live, DF_REF_REGNO (use))
diff --git a/gcc/df-scan.c b/gcc/df-scan.c
index cbb08fc..0b119f2 100644
--- a/gcc/df-scan.c
+++ b/gcc/df-scan.c
@@ -2778,6 +2778,7 @@ df_find_hard_reg_defs (rtx x, HARD_REG_SET *defs)
break;
case CLOBBER:
+ case CLOBBER_HIGH:
df_find_hard_reg_defs_1 (XEXP (x, 0), defs);
break;
@@ -2837,6 +2838,10 @@ df_uses_record (struct df_collection_rec *collection_rec,
/* If we're clobbering a REG then we have a def so ignore. */
return;
+ case CLOBBER_HIGH:
+ gcc_assert (REG_P (XEXP (x, 0)));
+ return;
+
case MEM:
df_uses_record (collection_rec,
&XEXP (x, 0), DF_REF_REG_MEM_LOAD,
@@ -3133,6 +3138,7 @@ df_get_call_refs (struct df_collection_rec *collection_rec,
for (note = CALL_INSN_FUNCTION_USAGE (insn_info->insn); note;
note = XEXP (note, 1))
{
+ gcc_assert (GET_CODE (XEXP (note, 0)) != CLOBBER_HIGH);
if (GET_CODE (XEXP (note, 0)) == USE)
df_uses_record (collection_rec, &XEXP (XEXP (note, 0), 0),
DF_REF_REG_USE, bb, insn_info, flags);
diff --git a/gcc/diagnostic-core.h b/gcc/diagnostic-core.h
index aa5807e..80ff395 100644
--- a/gcc/diagnostic-core.h
+++ b/gcc/diagnostic-core.h
@@ -36,6 +36,15 @@ typedef enum
DK_POP
} diagnostic_t;
+/* RAII-style class for grouping related diagnostics. */
+
+class auto_diagnostic_group
+{
+ public:
+ auto_diagnostic_group ();
+ ~auto_diagnostic_group ();
+};
+
extern const char *progname;
extern const char *trim_filename (const char *);
@@ -87,6 +96,7 @@ extern bool permerror (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
extern bool permerror (rich_location *, const char *,
...) ATTRIBUTE_GCC_DIAG(2,3);
extern void sorry (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
+extern void sorry_at (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
extern void inform (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
extern void inform (rich_location *, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
extern void inform_n (location_t, unsigned HOST_WIDE_INT, const char *,
diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c
index f188ee9..7dfb0a0 100644
--- a/gcc/diagnostic-show-locus.c
+++ b/gcc/diagnostic-show-locus.c
@@ -126,16 +126,20 @@ class layout_range
public:
layout_range (const expanded_location *start_exploc,
const expanded_location *finish_exploc,
- bool show_caret_p,
- const expanded_location *caret_exploc);
+ enum range_display_kind range_display_kind,
+ const expanded_location *caret_exploc,
+ unsigned original_idx,
+ const range_label *label);
bool contains_point (linenum_type row, int column) const;
bool intersects_line_p (linenum_type row) const;
layout_point m_start;
layout_point m_finish;
- bool m_show_caret_p;
+ enum range_display_kind m_range_display_kind;
layout_point m_caret;
+ unsigned m_original_idx;
+ const range_label *m_label;
};
/* A struct for use by layout::print_source_line for telling
@@ -234,11 +238,13 @@ class layout
diagnostic_t diagnostic_kind);
bool maybe_add_location_range (const location_range *loc_range,
+ unsigned original_idx,
bool restrict_to_current_line_spans);
int get_num_line_spans () const { return m_line_spans.length (); }
const line_span *get_line_span (int idx) const { return &m_line_spans[idx]; }
+ void print_gap_in_line_numbering ();
bool print_heading_for_line_span_index_p (int line_span_idx) const;
expanded_location get_expanded_location (const line_span *) const;
@@ -251,7 +257,9 @@ class layout
void print_source_line (linenum_type row, const char *line, int line_width,
line_bounds *lbounds_out);
bool should_print_annotation_line_p (linenum_type row) const;
+ void start_annotation_line (char margin_char = ' ') const;
void print_annotation_line (linenum_type row, const line_bounds lbounds);
+ void print_any_labels (linenum_type row);
void print_trailing_fixits (linenum_type row);
bool annotation_line_showed_range_p (linenum_type line, int start_column,
@@ -276,7 +284,7 @@ class layout
int last_non_ws);
void
- move_to_column (int *column, int dest_column);
+ move_to_column (int *column, int dest_column, bool add_left_margin);
private:
diagnostic_context *m_context;
@@ -286,9 +294,12 @@ class layout
expanded_location m_exploc;
colorizer m_colorizer;
bool m_colorize_source_p;
+ bool m_show_labels_p;
+ bool m_show_line_numbers_p;
auto_vec <layout_range> m_layout_ranges;
auto_vec <const fixit_hint *> m_fixit_hints;
auto_vec <line_span> m_line_spans;
+ int m_linenum_width;
int m_x_offset;
};
@@ -404,12 +415,16 @@ colorizer::get_color_by_name (const char *name)
layout_range::layout_range (const expanded_location *start_exploc,
const expanded_location *finish_exploc,
- bool show_caret_p,
- const expanded_location *caret_exploc)
+ enum range_display_kind range_display_kind,
+ const expanded_location *caret_exploc,
+ unsigned original_idx,
+ const range_label *label)
: m_start (*start_exploc),
m_finish (*finish_exploc),
- m_show_caret_p (show_caret_p),
- m_caret (*caret_exploc)
+ m_range_display_kind (range_display_kind),
+ m_caret (*caret_exploc),
+ m_original_idx (original_idx),
+ m_label (label)
{
}
@@ -535,8 +550,8 @@ make_range (int start_line, int start_col, int end_line, int end_col)
= {"test.c", start_line, start_col, NULL, false};
const expanded_location finish_exploc
= {"test.c", end_line, end_col, NULL, false};
- return layout_range (&start_exploc, &finish_exploc, false,
- &start_exploc);
+ return layout_range (&start_exploc, &finish_exploc, SHOW_RANGE_WITHOUT_CARET,
+ &start_exploc, 0, NULL);
}
/* Selftests for layout_range::contains_point and
@@ -805,6 +820,56 @@ fixit_cmp (const void *p_a, const void *p_b)
return hint_a->get_start_loc () - hint_b->get_start_loc ();
}
+/* Get the number of digits in the decimal representation
+ of VALUE. */
+
+static int
+num_digits (int value)
+{
+ /* Perhaps simpler to use log10 for this, but doing it this way avoids
+ using floating point. */
+ gcc_assert (value >= 0);
+
+ if (value == 0)
+ return 1;
+
+ int digits = 0;
+ while (value > 0)
+ {
+ digits++;
+ value /= 10;
+ }
+ return digits;
+}
+
+
+#if CHECKING_P
+
+/* Selftest for num_digits. */
+
+static void
+test_num_digits ()
+{
+ ASSERT_EQ (1, num_digits (0));
+ ASSERT_EQ (1, num_digits (9));
+ ASSERT_EQ (2, num_digits (10));
+ ASSERT_EQ (2, num_digits (99));
+ ASSERT_EQ (3, num_digits (100));
+ ASSERT_EQ (3, num_digits (999));
+ ASSERT_EQ (4, num_digits (1000));
+ ASSERT_EQ (4, num_digits (9999));
+ ASSERT_EQ (5, num_digits (10000));
+ ASSERT_EQ (5, num_digits (99999));
+ ASSERT_EQ (6, num_digits (100000));
+ ASSERT_EQ (6, num_digits (999999));
+ ASSERT_EQ (7, num_digits (1000000));
+ ASSERT_EQ (7, num_digits (9999999));
+ ASSERT_EQ (8, num_digits (10000000));
+ ASSERT_EQ (8, num_digits (99999999));
+}
+
+#endif /* #if CHECKING_P */
+
/* Implementation of class layout. */
/* Constructor for class layout.
@@ -826,9 +891,12 @@ layout::layout (diagnostic_context * context,
m_exploc (richloc->get_expanded_location (0)),
m_colorizer (context, diagnostic_kind),
m_colorize_source_p (context->colorize_source_p),
+ m_show_labels_p (context->show_labels_p),
+ m_show_line_numbers_p (context->show_line_numbers_p),
m_layout_ranges (richloc->get_num_locations ()),
m_fixit_hints (richloc->get_num_fixit_hints ()),
m_line_spans (1 + richloc->get_num_locations ()),
+ m_linenum_width (0),
m_x_offset (0)
{
for (unsigned int idx = 0; idx < richloc->get_num_locations (); idx++)
@@ -836,7 +904,7 @@ layout::layout (diagnostic_context * context,
/* This diagnostic printer can only cope with "sufficiently sane" ranges.
Ignore any ranges that are awkward to handle. */
const location_range *loc_range = richloc->get_range (idx);
- maybe_add_location_range (loc_range, false);
+ maybe_add_location_range (loc_range, idx, false);
}
/* Populate m_fixit_hints, filtering to only those that are in the
@@ -854,6 +922,17 @@ layout::layout (diagnostic_context * context,
/* Populate m_line_spans. */
calculate_line_spans ();
+ /* Determine m_linenum_width. */
+ gcc_assert (m_line_spans.length () > 0);
+ const line_span *last_span = &m_line_spans[m_line_spans.length () - 1];
+ int highest_line = last_span->m_last_line;
+ if (highest_line < 0)
+ highest_line = 0;
+ m_linenum_width = num_digits (highest_line);
+ /* If we're showing jumps in the line-numbering, allow at least 3 chars. */
+ if (m_line_spans.length () > 1)
+ m_linenum_width = MAX (m_linenum_width, 3);
+
/* Adjust m_x_offset.
Center the primary caret to fit in max_width; all columns
will be adjusted accordingly. */
@@ -863,6 +942,8 @@ layout::layout (diagnostic_context * context,
{
size_t right_margin = CARET_LINE_MARGIN;
size_t column = m_exploc.column;
+ if (m_show_line_numbers_p)
+ column += m_linenum_width + 2;
right_margin = MIN (line.length () - column, right_margin);
right_margin = max_width - right_margin;
if (line.length () >= max_width && column > right_margin)
@@ -877,6 +958,9 @@ layout::layout (diagnostic_context * context,
/* Attempt to add LOC_RANGE to m_layout_ranges, filtering them to
those that we can sanely print.
+ ORIGINAL_IDX is the index of LOC_RANGE within its rich_location,
+ (for use as extrinsic state by label ranges FIXME).
+
If RESTRICT_TO_CURRENT_LINE_SPANS is true, then LOC_RANGE is also
filtered against this layout instance's current line spans: it
will only be added if the location is fully within the lines
@@ -886,6 +970,7 @@ layout::layout (diagnostic_context * context,
bool
layout::maybe_add_location_range (const location_range *loc_range,
+ unsigned original_idx,
bool restrict_to_current_line_spans)
{
gcc_assert (loc_range);
@@ -910,13 +995,13 @@ layout::maybe_add_location_range (const location_range *loc_range,
return false;
if (finish.file != m_exploc.file)
return false;
- if (loc_range->m_show_caret_p)
+ if (loc_range->m_range_display_kind == SHOW_RANGE_WITH_CARET)
if (caret.file != m_exploc.file)
return false;
/* Sanitize the caret location for non-primary ranges. */
if (m_layout_ranges.length () > 0)
- if (loc_range->m_show_caret_p)
+ if (loc_range->m_range_display_kind == SHOW_RANGE_WITH_CARET)
if (!compatible_locations_p (loc_range->m_loc, m_primary_loc))
/* Discard any non-primary ranges that can't be printed
sanely relative to the primary location. */
@@ -924,7 +1009,8 @@ layout::maybe_add_location_range (const location_range *loc_range,
/* Everything is now known to be in the correct source file,
but it may require further sanitization. */
- layout_range ri (&start, &finish, loc_range->m_show_caret_p, &caret);
+ layout_range ri (&start, &finish, loc_range->m_range_display_kind, &caret,
+ original_idx, loc_range->m_label);
/* If we have a range that finishes before it starts (perhaps
from something built via macro expansion), printing the
@@ -960,7 +1046,7 @@ layout::maybe_add_location_range (const location_range *loc_range,
return false;
if (!will_show_line_p (finish.line))
return false;
- if (loc_range->m_show_caret_p)
+ if (loc_range->m_range_display_kind == SHOW_RANGE_WITH_CARET)
if (!will_show_line_p (caret.line))
return false;
}
@@ -986,6 +1072,20 @@ layout::will_show_line_p (linenum_type row) const
return false;
}
+/* Print a line showing a gap in the line numbers, for showing the boundary
+ between two line spans. */
+
+void
+layout::print_gap_in_line_numbering ()
+{
+ gcc_assert (m_show_line_numbers_p);
+
+ for (int i = 0; i < m_linenum_width + 1; i++)
+ pp_character (m_pp, '.');
+
+ pp_newline (m_pp);
+}
+
/* Return true iff we should print a heading when starting the
line span with the given index. */
@@ -1068,7 +1168,16 @@ static line_span
get_line_span_for_fixit_hint (const fixit_hint *hint)
{
gcc_assert (hint);
- return line_span (LOCATION_LINE (hint->get_start_loc ()),
+
+ int start_line = LOCATION_LINE (hint->get_start_loc ());
+
+ /* For line-insertion fix-it hints, add the previous line to the
+ span, to give the user more context on the proposed change. */
+ if (hint->ends_with_newline_p ())
+ if (start_line > 1)
+ start_line--;
+
+ return line_span (start_line,
LOCATION_LINE (hint->get_next_loc ()));
}
@@ -1083,21 +1192,34 @@ get_line_span_for_fixit_hint (const fixit_hint *hint)
This function populates m_line_spans with an ordered, disjoint list of
the line spans of interest.
- For example, if the primary caret location is on line 7, with ranges
- covering lines 5-6 and lines 9-12:
+ Printing a gap between line spans takes one line, so, when printing
+ line numbers, we allow a gap of up to one line between spans when
+ merging, since it makes more sense to print the source line rather than a
+ "gap-in-line-numbering" line. When not printing line numbers, it's
+ better to be more explicit about what's going on, so keeping them as
+ separate spans is preferred.
+
+ For example, if the primary range is on lines 8-10, with secondary ranges
+ covering lines 5-6 and lines 13-15:
004
- 005 |RANGE 0
- 006 |RANGE 0
- 007 |PRIMARY CARET
- 008
- 009 |RANGE 1
- 010 |RANGE 1
- 011 |RANGE 1
- 012 |RANGE 1
- 013
-
- then we want two spans: lines 5-7 and lines 9-12. */
+ 005 |RANGE 1
+ 006 |RANGE 1
+ 007
+ 008 |PRIMARY RANGE
+ 009 |PRIMARY CARET
+ 010 |PRIMARY RANGE
+ 011
+ 012
+ 013 |RANGE 2
+ 014 |RANGE 2
+ 015 |RANGE 2
+ 016
+
+ With line numbering on, we want two spans: lines 5-10 and lines 13-15.
+
+ With line numbering off (with span headers), we want three spans: lines 5-6,
+ lines 8-10, and lines 13-15. */
void
layout::calculate_line_spans ()
@@ -1137,7 +1259,8 @@ layout::calculate_line_spans ()
line_span *current = &m_line_spans[m_line_spans.length () - 1];
const line_span *next = &tmp_spans[i];
gcc_assert (next->m_first_line >= current->m_first_line);
- if (next->m_first_line <= current->m_last_line + 1)
+ const int merger_distance = m_show_line_numbers_p ? 1 : 0;
+ if (next->m_first_line <= current->m_last_line + 1 + merger_distance)
{
/* We can merge them. */
if (next->m_last_line > current->m_last_line)
@@ -1183,7 +1306,15 @@ layout::print_source_line (linenum_type row, const char *line, int line_width,
line_width);
line += m_x_offset;
- pp_space (m_pp);
+ if (m_show_line_numbers_p)
+ {
+ int width = num_digits (row);
+ for (int i = 0; i < m_linenum_width - width; i++)
+ pp_space (m_pp);
+ pp_printf (m_pp, "%i | ", row);
+ }
+ else
+ pp_space (m_pp);
int first_non_ws = INT_MAX;
int last_non_ws = 0;
int column;
@@ -1240,11 +1371,29 @@ layout::should_print_annotation_line_p (linenum_type row) const
layout_range *range;
int i;
FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
- if (range->intersects_line_p (row))
- return true;
+ {
+ if (range->m_range_display_kind == SHOW_LINES_WITHOUT_RANGE)
+ return false;
+ if (range->intersects_line_p (row))
+ return true;
+ }
return false;
}
+/* Begin an annotation line. If m_show_line_numbers_p, print the left
+ margin, which is empty for annotation lines. Otherwise, do nothing. */
+
+void
+layout::start_annotation_line (char margin_char) const
+{
+ if (m_show_line_numbers_p)
+ {
+ for (int i = 0; i < m_linenum_width; i++)
+ pp_character (m_pp, margin_char);
+ pp_string (m_pp, " |");
+ }
+}
+
/* Print a line consisting of the caret/underlines for the given
source line. */
@@ -1254,7 +1403,9 @@ layout::print_annotation_line (linenum_type row, const line_bounds lbounds)
int x_bound = get_x_bound_for_row (row, m_exploc.column,
lbounds.m_last_non_ws);
+ start_annotation_line ();
pp_space (m_pp);
+
for (int column = 1 + m_x_offset; column < x_bound; column++)
{
bool in_range_p;
@@ -1290,6 +1441,180 @@ layout::print_annotation_line (linenum_type row, const line_bounds lbounds)
print_newline ();
}
+/* Implementation detail of layout::print_any_labels.
+
+ A label within the given row of source. */
+
+struct line_label
+{
+ line_label (int state_idx, int column, label_text text)
+ : m_state_idx (state_idx), m_column (column),
+ m_text (text), m_length (strlen (text.m_buffer)),
+ m_label_line (0)
+ {}
+
+ /* Sorting is primarily by column, then by state index. */
+ static int comparator (const void *p1, const void *p2)
+ {
+ const line_label *ll1 = (const line_label *)p1;
+ const line_label *ll2 = (const line_label *)p2;
+ int column_cmp = compare (ll1->m_column, ll2->m_column);
+ if (column_cmp)
+ return column_cmp;
+ return compare (ll1->m_state_idx, ll2->m_state_idx);
+ }
+
+ int m_state_idx;
+ int m_column;
+ label_text m_text;
+ size_t m_length;
+ int m_label_line;
+};
+
+/* Print any labels in this row. */
+void
+layout::print_any_labels (linenum_type row)
+{
+ int i;
+ auto_vec<line_label> labels;
+
+ /* Gather the labels that are to be printed into "labels". */
+ {
+ layout_range *range;
+ FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
+ {
+ /* Most ranges don't have labels, so reject this first. */
+ if (range->m_label == NULL)
+ continue;
+
+ /* The range's caret must be on this line. */
+ if (range->m_caret.m_line != row)
+ continue;
+
+ /* Reject labels that aren't fully visible due to clipping
+ by m_x_offset. */
+ if (range->m_caret.m_column <= m_x_offset)
+ continue;
+
+ label_text text;
+ text = range->m_label->get_text (range->m_original_idx);
+
+ /* Allow for labels that return NULL from their get_text
+ implementation (so e.g. such labels can control their own
+ visibility). */
+ if (text.m_buffer == NULL)
+ continue;
+
+ labels.safe_push (line_label (i, range->m_caret.m_column, text));
+ }
+ }
+
+ /* Bail out if there are no labels on this row. */
+ if (labels.length () == 0)
+ return;
+
+ /* Sort them. */
+ labels.qsort(line_label::comparator);
+
+ /* Figure out how many "label lines" we need, and which
+ one each label is printed in.
+
+ For example, if the labels aren't too densely packed,
+ we can fit them on the same line, giving two "label lines":
+
+ foo + bar
+ ~~~ ~~~
+ | | : label line 0
+ l0 l1 : label line 1
+
+ If they would touch each other or overlap, then we need
+ additional "label lines":
+
+ foo + bar
+ ~~~ ~~~
+ | | : label line 0
+ | label 1 : label line 1
+ label 0 : label line 2
+
+ Place the final label on label line 1, and work backwards, adding
+ label lines as needed.
+
+ If multiple labels are at the same place, put them on separate
+ label lines:
+
+ foo + bar
+ ^ : label line 0
+ | : label line 1
+ label 1 : label line 2
+ label 0 : label line 3. */
+
+ int max_label_line = 1;
+ {
+ int next_column = INT_MAX;
+ line_label *label;
+ FOR_EACH_VEC_ELT_REVERSE (labels, i, label)
+ {
+ /* Would this label "touch" or overlap the next label? */
+ if (label->m_column + label->m_length >= (size_t)next_column)
+ max_label_line++;
+
+ label->m_label_line = max_label_line;
+ next_column = label->m_column;
+ }
+ }
+
+ /* Print the "label lines". For each label within the line, print
+ either a vertical bar ('|') for the labels that are lower down, or the
+ labels themselves once we've reached their line. */
+ {
+ /* Keep track of in which column we last printed a vertical bar.
+ This allows us to suppress duplicate vertical bars for the case
+ where multiple labels are on one column. */
+ int last_vbar = 0;
+ for (int label_line = 0; label_line <= max_label_line; label_line++)
+ {
+ start_annotation_line ();
+ pp_space (m_pp);
+ int column = 1 + m_x_offset;
+ line_label *label;
+ FOR_EACH_VEC_ELT (labels, i, label)
+ {
+ if (label_line > label->m_label_line)
+ /* We've printed all the labels for this label line. */
+ break;
+
+ if (label_line == label->m_label_line)
+ {
+ gcc_assert (column <= label->m_column);
+ move_to_column (&column, label->m_column, true);
+ m_colorizer.set_range (label->m_state_idx);
+ pp_string (m_pp, label->m_text.m_buffer);
+ m_colorizer.set_normal_text ();
+ column += label->m_length;
+ }
+ else if (label->m_column != last_vbar)
+ {
+ gcc_assert (column <= label->m_column);
+ move_to_column (&column, label->m_column, true);
+ m_colorizer.set_range (label->m_state_idx);
+ pp_character (m_pp, '|');
+ m_colorizer.set_normal_text ();
+ last_vbar = column;
+ column++;
+ }
+ }
+ print_newline ();
+ }
+ }
+
+ /* Clean up. */
+ {
+ line_label *label;
+ FOR_EACH_VEC_ELT (labels, i, label)
+ label->m_text.maybe_free ();
+ }
+}
+
/* If there are any fixit hints inserting new lines before source line ROW,
print them.
@@ -1316,6 +1641,7 @@ layout::print_leading_fixits (linenum_type row)
helps them stand out from each other, and from
the surrounding text. */
m_colorizer.set_normal_text ();
+ start_annotation_line ('+');
pp_character (m_pp, '+');
m_colorizer.set_fixit_insert ();
/* Print all but the trailing newline of the fix-it hint.
@@ -1712,6 +2038,9 @@ layout::print_trailing_fixits (linenum_type row)
correction *c;
int column = m_x_offset;
+ if (!corrections.m_corrections.is_empty ())
+ start_annotation_line ();
+
FOR_EACH_VEC_ELT (corrections.m_corrections, i, c)
{
/* For now we assume each fixit hint can only touch one line. */
@@ -1719,7 +2048,7 @@ layout::print_trailing_fixits (linenum_type row)
{
/* This assumes the insertion just affects one line. */
int start_column = c->m_printed_columns.start;
- move_to_column (&column, start_column);
+ move_to_column (&column, start_column, true);
m_colorizer.set_fixit_insert ();
pp_string (m_pp, c->m_text);
m_colorizer.set_normal_text ();
@@ -1737,7 +2066,7 @@ layout::print_trailing_fixits (linenum_type row)
finish_column)
|| c->m_len == 0)
{
- move_to_column (&column, start_column);
+ move_to_column (&column, start_column, true);
m_colorizer.set_fixit_delete ();
for (; column <= finish_column; column++)
pp_character (m_pp, '-');
@@ -1748,7 +2077,7 @@ layout::print_trailing_fixits (linenum_type row)
a new line) if we have actual replacement text. */
if (c->m_len > 0)
{
- move_to_column (&column, start_column);
+ move_to_column (&column, start_column, true);
m_colorizer.set_fixit_insert ();
pp_string (m_pp, c->m_text);
m_colorizer.set_normal_text ();
@@ -1758,7 +2087,7 @@ layout::print_trailing_fixits (linenum_type row)
}
/* Add a trailing newline, if necessary. */
- move_to_column (&column, 0);
+ move_to_column (&column, 0, false);
}
/* Disable any colorization and emit a newline. */
@@ -1786,13 +2115,18 @@ layout::get_state_at_point (/* Inputs. */
int i;
FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
{
+ if (range->m_range_display_kind == SHOW_LINES_WITHOUT_RANGE)
+ /* Bail out early, so that such ranges don't affect underlining or
+ source colorization. */
+ continue;
+
if (range->contains_point (row, column))
{
out_state->range_idx = i;
/* Are we at the range's caret? is it visible? */
out_state->draw_caret_p = false;
- if (range->m_show_caret_p
+ if (range->m_range_display_kind == SHOW_RANGE_WITH_CARET
&& row == range->m_caret.m_line
&& column == range->m_caret.m_column)
out_state->draw_caret_p = true;
@@ -1855,15 +2189,18 @@ layout::get_x_bound_for_row (linenum_type row, int caret_column,
/* Given *COLUMN as an x-coordinate, print spaces to position
successive output at DEST_COLUMN, printing a newline if necessary,
- and updating *COLUMN. */
+ and updating *COLUMN. If ADD_LEFT_MARGIN, then print the (empty)
+ left margin after any newline. */
void
-layout::move_to_column (int *column, int dest_column)
+layout::move_to_column (int *column, int dest_column, bool add_left_margin)
{
/* Start a new line if we need to. */
if (*column > dest_column)
{
print_newline ();
+ if (add_left_margin)
+ start_annotation_line ();
*column = m_x_offset;
}
@@ -1883,6 +2220,7 @@ layout::show_ruler (int max_column) const
/* Hundreds. */
if (max_column > 99)
{
+ start_annotation_line ();
pp_space (m_pp);
for (int column = 1 + m_x_offset; column <= max_column; column++)
if (column % 10 == 0)
@@ -1893,6 +2231,7 @@ layout::show_ruler (int max_column) const
}
/* Tens. */
+ start_annotation_line ();
pp_space (m_pp);
for (int column = 1 + m_x_offset; column <= max_column; column++)
if (column % 10 == 0)
@@ -1902,6 +2241,7 @@ layout::show_ruler (int max_column) const
pp_newline (m_pp);
/* Units. */
+ start_annotation_line ();
pp_space (m_pp);
for (int column = 1 + m_x_offset; column <= max_column; column++)
pp_character (m_pp, '0' + (column % 10));
@@ -1924,6 +2264,8 @@ layout::print_line (linenum_type row)
print_source_line (row, line.get_buffer (), line.length (), &lbounds);
if (should_print_annotation_line_p (row))
print_annotation_line (row, lbounds);
+ if (m_show_labels_p)
+ print_any_labels (row);
print_trailing_fixits (row);
}
@@ -1943,11 +2285,11 @@ gcc_rich_location::add_location_if_nearby (location_t loc)
layout layout (global_dc, this, DK_ERROR);
location_range loc_range;
loc_range.m_loc = loc;
- loc_range.m_show_caret_p = false;
- if (!layout.maybe_add_location_range (&loc_range, true))
+ loc_range.m_range_display_kind = SHOW_RANGE_WITHOUT_CARET;
+ if (!layout.maybe_add_location_range (&loc_range, 0, true))
return false;
- add_range (loc, false);
+ add_range (loc);
return true;
}
@@ -1978,7 +2320,7 @@ diagnostic_show_locus (diagnostic_context * context,
context->last_location = loc;
- const char *saved_prefix = pp_get_prefix (context->printer);
+ char *saved_prefix = pp_take_prefix (context->printer);
pp_set_prefix (context->printer, NULL);
layout layout (context, richloc, diagnostic_kind);
@@ -1986,10 +2328,22 @@ diagnostic_show_locus (diagnostic_context * context,
line_span_idx++)
{
const line_span *line_span = layout.get_line_span (line_span_idx);
- if (layout.print_heading_for_line_span_index_p (line_span_idx))
+ if (context->show_line_numbers_p)
+ {
+ /* With line numbers, we should show whenever the line-numbering
+ "jumps". */
+ if (line_span_idx > 0)
+ layout.print_gap_in_line_numbering ();
+ }
+ else
{
- expanded_location exploc = layout.get_expanded_location (line_span);
- context->start_span (context, exploc);
+ /* Without line numbers, we print headings for some line spans. */
+ if (layout.print_heading_for_line_span_index_p (line_span_idx))
+ {
+ expanded_location exploc
+ = layout.get_expanded_location (line_span);
+ context->start_span (context, exploc);
+ }
}
linenum_type last_line = line_span->get_last_line ();
for (linenum_type row = line_span->get_first_line ();
@@ -2085,8 +2439,8 @@ test_one_liner_multiple_carets_and_ranges ()
dc.caret_chars[2] = 'C';
rich_location richloc (line_table, foo);
- richloc.add_range (bar, true);
- richloc.add_range (field, true);
+ richloc.add_range (bar, SHOW_RANGE_WITH_CARET);
+ richloc.add_range (field, SHOW_RANGE_WITH_CARET);
diagnostic_show_locus (&dc, &richloc, DK_ERROR);
ASSERT_STREQ ("\n"
" foo = bar.field;\n"
@@ -2207,7 +2561,7 @@ test_one_liner_fixit_replace_equal_secondary_range ()
location_t finish = linemap_position_for_column (line_table, 15);
rich_location richloc (line_table, equals);
location_t field = make_location (start, start, finish);
- richloc.add_range (field, false);
+ richloc.add_range (field);
richloc.add_fixit_replace (field, "m_field");
diagnostic_show_locus (&dc, &richloc, DK_ERROR);
/* The replacement range is indicated in the annotation line,
@@ -2330,6 +2684,157 @@ test_one_liner_many_fixits_2 ()
pp_formatted_text (dc.printer));
}
+/* Test of labeling the ranges within a rich_location. */
+
+static void
+test_one_liner_labels ()
+{
+ location_t foo
+ = make_location (linemap_position_for_column (line_table, 1),
+ linemap_position_for_column (line_table, 1),
+ linemap_position_for_column (line_table, 3));
+ location_t bar
+ = make_location (linemap_position_for_column (line_table, 7),
+ linemap_position_for_column (line_table, 7),
+ linemap_position_for_column (line_table, 9));
+ location_t field
+ = make_location (linemap_position_for_column (line_table, 11),
+ linemap_position_for_column (line_table, 11),
+ linemap_position_for_column (line_table, 15));
+
+ /* Example where all the labels fit on one line. */
+ {
+ text_range_label label0 ("0");
+ text_range_label label1 ("1");
+ text_range_label label2 ("2");
+ gcc_rich_location richloc (foo, &label0);
+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+ richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
+
+ {
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " foo = bar.field;\n"
+ " ^~~ ~~~ ~~~~~\n"
+ " | | |\n"
+ " 0 1 2\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Verify that we can disable label-printing. */
+ {
+ test_diagnostic_context dc;
+ dc.show_labels_p = false;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " foo = bar.field;\n"
+ " ^~~ ~~~ ~~~~~\n",
+ pp_formatted_text (dc.printer));
+ }
+ }
+
+ /* Example where the labels need extra lines. */
+ {
+ text_range_label label0 ("label 0");
+ text_range_label label1 ("label 1");
+ text_range_label label2 ("label 2");
+ gcc_rich_location richloc (foo, &label0);
+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+ richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " foo = bar.field;\n"
+ " ^~~ ~~~ ~~~~~\n"
+ " | | |\n"
+ " | | label 2\n"
+ " | label 1\n"
+ " label 0\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Example of boundary conditions: label 0 and 1 have just enough clearance,
+ but label 1 just touches label 2. */
+ {
+ text_range_label label0 ("aaaaa");
+ text_range_label label1 ("bbbb");
+ text_range_label label2 ("c");
+ gcc_rich_location richloc (foo, &label0);
+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+ richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " foo = bar.field;\n"
+ " ^~~ ~~~ ~~~~~\n"
+ " | | |\n"
+ " | | c\n"
+ " aaaaa bbbb\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Example of out-of-order ranges (thus requiring a sort). */
+ {
+ text_range_label label0 ("0");
+ text_range_label label1 ("1");
+ text_range_label label2 ("2");
+ gcc_rich_location richloc (field, &label0);
+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+ richloc.add_range (foo, SHOW_RANGE_WITHOUT_CARET, &label2);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " foo = bar.field;\n"
+ " ~~~ ~~~ ^~~~~\n"
+ " | | |\n"
+ " 2 1 0\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Ensure we don't ICE if multiple ranges with labels are on
+ the same point. */
+ {
+ text_range_label label0 ("label 0");
+ text_range_label label1 ("label 1");
+ text_range_label label2 ("label 2");
+ gcc_rich_location richloc (bar, &label0);
+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label2);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " foo = bar.field;\n"
+ " ^~~\n"
+ " |\n"
+ " label 2\n"
+ " label 1\n"
+ " label 0\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Verify that a NULL result from range_label::get_text is
+ handled gracefully. */
+ {
+ text_range_label label (NULL);
+ gcc_rich_location richloc (bar, &label);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " foo = bar.field;\n"
+ " ^~~\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* TODO: example of formatted printing (needs to be in
+ gcc-rich-location.c due to Makefile.in issues). */
+}
+
/* Run the various one-liner tests. */
static void
@@ -2366,6 +2871,7 @@ test_diagnostic_show_locus_one_liner (const line_table_case &case_)
test_one_liner_fixit_validation_adhoc_locations ();
test_one_liner_many_fixits_1 ();
test_one_liner_many_fixits_2 ();
+ test_one_liner_labels ();
}
/* Verify that gcc_rich_location::add_location_if_nearby works. */
@@ -2508,6 +3014,29 @@ test_diagnostic_show_locus_fixit_lines (const line_table_case &case_)
" =\n",
pp_formatted_text (dc.printer));
}
+
+ /* As above, but verify the behavior of multiple line spans
+ with line-numbering enabled. */
+ {
+ const location_t y
+ = linemap_position_for_line_and_column (line_table, ord_map, 3, 24);
+ const location_t colon
+ = linemap_position_for_line_and_column (line_table, ord_map, 6, 25);
+ rich_location richloc (line_table, colon);
+ richloc.add_fixit_insert_before (y, ".");
+ richloc.add_fixit_replace (colon, "=");
+ test_diagnostic_context dc;
+ dc.show_line_numbers_p = true;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " 3 | y\n"
+ " | .\n"
+ "....\n"
+ " 6 | : 0.0};\n"
+ " | ^\n"
+ " | =\n",
+ pp_formatted_text (dc.printer));
+ }
}
@@ -2977,13 +3506,31 @@ test_fixit_insert_containing_newline (const line_table_case &case_)
{
rich_location richloc (line_table, case_loc);
richloc.add_fixit_insert_before (line_start, " break;\n");
- test_diagnostic_context dc;
- diagnostic_show_locus (&dc, &richloc, DK_ERROR);
- ASSERT_STREQ ("\n"
- "+ break;\n"
- " case 'b':\n"
- " ^~~~~~~~~\n",
- pp_formatted_text (dc.printer));
+
+ /* Without line numbers. */
+ {
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " x = a;\n"
+ "+ break;\n"
+ " case 'b':\n"
+ " ^~~~~~~~~\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* With line numbers. */
+ {
+ test_diagnostic_context dc;
+ dc.show_line_numbers_p = true;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ "2 | x = a;\n"
+ "+ |+ break;\n"
+ "3 | case 'b':\n"
+ " | ^~~~~~~~~\n",
+ pp_formatted_text (dc.printer));
+ }
}
/* Verify that attempts to add text with a newline fail when the
@@ -3040,16 +3587,33 @@ test_fixit_insert_containing_newline_2 (const line_table_case &case_)
if (putchar_finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
return;
- test_diagnostic_context dc;
- diagnostic_show_locus (&dc, &richloc, DK_ERROR);
- ASSERT_STREQ ("\n"
- "FILENAME:1:1:\n"
- "+#include <stdio.h>\n"
- " test (int ch)\n"
- "FILENAME:3:2:\n"
- " putchar (ch);\n"
- " ^~~~~~~\n",
- pp_formatted_text (dc.printer));
+ {
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ "FILENAME:1:1:\n"
+ "+#include <stdio.h>\n"
+ " test (int ch)\n"
+ "FILENAME:3:2:\n"
+ " putchar (ch);\n"
+ " ^~~~~~~\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* With line-numbering, the line spans are close enough to be
+ consolidated, since it makes little sense to skip line 2. */
+ {
+ test_diagnostic_context dc;
+ dc.show_line_numbers_p = true;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ "+ |+#include <stdio.h>\n"
+ "1 | test (int ch)\n"
+ "2 | {\n"
+ "3 | putchar (ch);\n"
+ " | ^~~~~~~\n",
+ pp_formatted_text (dc.printer));
+ }
}
/* Replacement fix-it hint containing a newline.
@@ -3139,12 +3703,58 @@ test_fixit_deletion_affecting_newline (const line_table_case &case_)
pp_formatted_text (dc.printer));
}
+/* Verify that line numbers are correctly printed for the case of
+ a multiline range in which the width of the line numbers changes
+ (e.g. from "9" to "10"). */
+
+static void
+test_line_numbers_multiline_range ()
+{
+ /* Create a tempfile and write some text to it. */
+ pretty_printer pp;
+ for (int i = 0; i < 20; i++)
+ /* .........0000000001111111.
+ .............1234567890123456. */
+ pp_printf (&pp, "this is line %i\n", i + 1);
+ temp_source_file tmp (SELFTEST_LOCATION, ".txt", pp_formatted_text (&pp));
+ line_table_test ltt;
+
+ const line_map_ordinary *ord_map = linemap_check_ordinary
+ (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0));
+ linemap_line_start (line_table, 1, 100);
+
+ /* Create a multi-line location, starting at the "line" of line 9, with
+ a caret on the "is" of line 10, finishing on the "this" line 11. */
+
+ location_t start
+ = linemap_position_for_line_and_column (line_table, ord_map, 9, 9);
+ location_t caret
+ = linemap_position_for_line_and_column (line_table, ord_map, 10, 6);
+ location_t finish
+ = linemap_position_for_line_and_column (line_table, ord_map, 11, 4);
+ location_t loc = make_location (caret, start, finish);
+
+ test_diagnostic_context dc;
+ dc.show_line_numbers_p = true;
+ gcc_rich_location richloc (loc);
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("\n"
+ " 9 | this is line 9\n"
+ " | ~~~~~~\n"
+ "10 | this is line 10\n"
+ " | ~~~~~^~~~~~~~~~\n"
+ "11 | this is line 11\n"
+ " | ~~~~ \n",
+ pp_formatted_text (dc.printer));
+}
+
/* Run all of the selftests within this file. */
void
diagnostic_show_locus_c_tests ()
{
test_line_span ();
+ test_num_digits ();
test_layout_range_for_single_point ();
test_layout_range_for_single_line ();
@@ -3164,6 +3774,8 @@ diagnostic_show_locus_c_tests ()
for_each_line_table_case (test_fixit_insert_containing_newline_2);
for_each_line_table_case (test_fixit_replace_containing_newline);
for_each_line_table_case (test_fixit_deletion_affecting_newline);
+
+ test_line_numbers_multiline_range ();
}
} // namespace selftest
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index e22c17b..8575065 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -175,9 +175,15 @@ diagnostic_initialize (diagnostic_context *context, int n_opts)
context->lock = 0;
context->inhibit_notes_p = false;
context->colorize_source_p = false;
+ context->show_labels_p = false;
+ context->show_line_numbers_p = false;
context->show_ruler_p = false;
context->parseable_fixits_p = false;
context->edit_context_ptr = NULL;
+ context->diagnostic_group_nesting_depth = 0;
+ context->diagnostic_group_emission_count = 0;
+ context->begin_group_cb = NULL;
+ context->end_group_cb = NULL;
}
/* Maybe initialize the color support. We require clients to do this
@@ -587,22 +593,27 @@ diagnostic_report_current_module (diagnostic_context *context, location_t where)
set_last_module (context, map);
if (! MAIN_FILE_P (map))
{
- map = INCLUDED_FROM (line_table, map);
- const char *line_col
- = maybe_line_and_column (LAST_SOURCE_LINE (map),
- context->show_column
- ? LAST_SOURCE_COLUMN (map) : 0);
- pp_verbatim (context->printer,
- "In file included from %r%s%s%R", "locus",
- LINEMAP_FILE (map), line_col);
- while (! MAIN_FILE_P (map))
+ bool first = true;
+ do
{
- map = INCLUDED_FROM (line_table, map);
- line_col = maybe_line_and_column (LAST_SOURCE_LINE (map), 0);
- pp_verbatim (context->printer,
- ",\n from %r%s%s%R", "locus",
- LINEMAP_FILE (map), line_col);
+ where = linemap_included_from (map);
+ map = linemap_included_from_linemap (line_table, map);
+ const char *line_col
+ = maybe_line_and_column (SOURCE_LINE (map, where),
+ first && context->show_column
+ ? SOURCE_COLUMN (map, where) : 0);
+ static const char *const msgs[] =
+ {
+ N_("In file included from"),
+ N_(" from"),
+ };
+ unsigned index = !first;
+ pp_verbatim (context->printer, "%s%s %r%s%s%R",
+ first ? "" : ",\n", _(msgs[index]),
+ "locus", LINEMAP_FILE (map), line_col);
+ first = false;
}
+ while (! MAIN_FILE_P (map));
pp_verbatim (context->printer, ":");
pp_newline (context->printer);
}
@@ -622,9 +633,9 @@ void
default_diagnostic_start_span_fn (diagnostic_context *context,
expanded_location exploc)
{
- pp_set_prefix (context->printer,
- diagnostic_get_location_text (context, exploc));
- pp_string (context->printer, "");
+ char *text = diagnostic_get_location_text (context, exploc);
+ pp_string (context->printer, text);
+ free (text);
pp_newline (context->printer);
}
@@ -979,6 +990,14 @@ diagnostic_report_diagnostic (diagnostic_context *context,
else
++diagnostic_kind_count (context, diagnostic->kind);
+ /* Is this the initial diagnostic within the stack of groups? */
+ if (context->diagnostic_group_emission_count == 0)
+ {
+ if (context->begin_group_cb)
+ context->begin_group_cb (context);
+ }
+ context->diagnostic_group_emission_count++;
+
diagnostic->message.x_data = &diagnostic->x_data;
diagnostic->x_data = NULL;
pp_format (context->printer, &diagnostic->message);
@@ -1063,7 +1082,6 @@ diagnostic_append_note (diagnostic_context *context,
{
diagnostic_info diagnostic;
va_list ap;
- const char *saved_prefix;
rich_location richloc (line_table, location);
va_start (ap, gmsgid);
@@ -1073,7 +1091,7 @@ diagnostic_append_note (diagnostic_context *context,
va_end (ap);
return;
}
- saved_prefix = pp_get_prefix (context->printer);
+ char *saved_prefix = pp_take_prefix (context->printer);
pp_set_prefix (context->printer,
diagnostic_build_prefix (context, &diagnostic));
pp_format (context->printer, &diagnostic.message);
@@ -1140,6 +1158,7 @@ bool
emit_diagnostic (diagnostic_t kind, location_t location, int opt,
const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, location);
@@ -1163,6 +1182,7 @@ emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
void
inform (location_t location, const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, location);
@@ -1176,6 +1196,7 @@ inform (rich_location *richloc, const char *gmsgid, ...)
{
gcc_assert (richloc);
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
diagnostic_impl (richloc, -1, gmsgid, &ap, DK_NOTE);
@@ -1190,6 +1211,7 @@ inform_n (location_t location, unsigned HOST_WIDE_INT n,
{
va_list ap;
va_start (ap, plural_gmsgid);
+ auto_diagnostic_group d;
rich_location richloc (line_table, location);
diagnostic_n_impl (&richloc, -1, n, singular_gmsgid, plural_gmsgid,
&ap, DK_NOTE);
@@ -1202,6 +1224,7 @@ inform_n (location_t location, unsigned HOST_WIDE_INT n,
bool
warning (int opt, const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, input_location);
@@ -1217,6 +1240,7 @@ warning (int opt, const char *gmsgid, ...)
bool
warning_at (location_t location, int opt, const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, location);
@@ -1232,6 +1256,7 @@ warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
{
gcc_assert (richloc);
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
bool ret = diagnostic_impl (richloc, opt, gmsgid, &ap, DK_WARNING);
@@ -1247,6 +1272,7 @@ warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
{
gcc_assert (richloc);
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, plural_gmsgid);
bool ret = diagnostic_n_impl (richloc, opt, n,
@@ -1264,6 +1290,7 @@ bool
warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
const char *singular_gmsgid, const char *plural_gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, plural_gmsgid);
rich_location richloc (line_table, location);
@@ -1290,6 +1317,7 @@ warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
bool
pedwarn (location_t location, int opt, const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, location);
@@ -1305,6 +1333,7 @@ pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
{
gcc_assert (richloc);
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
bool ret = diagnostic_impl (richloc, opt, gmsgid, &ap, DK_PEDWARN);
@@ -1322,6 +1351,7 @@ pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
bool
permerror (location_t location, const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, location);
@@ -1337,6 +1367,7 @@ permerror (rich_location *richloc, const char *gmsgid, ...)
{
gcc_assert (richloc);
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
bool ret = diagnostic_impl (richloc, -1, gmsgid, &ap, DK_PERMERROR);
@@ -1349,6 +1380,7 @@ permerror (rich_location *richloc, const char *gmsgid, ...)
void
error (const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, input_location);
@@ -1362,6 +1394,7 @@ void
error_n (location_t location, unsigned HOST_WIDE_INT n,
const char *singular_gmsgid, const char *plural_gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, plural_gmsgid);
rich_location richloc (line_table, location);
@@ -1374,6 +1407,7 @@ error_n (location_t location, unsigned HOST_WIDE_INT n,
void
error_at (location_t loc, const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, loc);
@@ -1388,6 +1422,7 @@ error_at (rich_location *richloc, const char *gmsgid, ...)
{
gcc_assert (richloc);
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
diagnostic_impl (richloc, -1, gmsgid, &ap, DK_ERROR);
@@ -1400,6 +1435,7 @@ error_at (rich_location *richloc, const char *gmsgid, ...)
void
sorry (const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, input_location);
@@ -1407,6 +1443,18 @@ sorry (const char *gmsgid, ...)
va_end (ap);
}
+/* Same as above, but use location LOC instead of input_location. */
+void
+sorry_at (location_t loc, const char *gmsgid, ...)
+{
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ rich_location richloc (line_table, loc);
+ diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_SORRY);
+ va_end (ap);
+}
+
/* Return true if an error or a "sorry" has been seen. Various
processing is disabled after errors. */
bool
@@ -1421,6 +1469,7 @@ seen_error (void)
void
fatal_error (location_t loc, const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, loc);
@@ -1437,6 +1486,7 @@ fatal_error (location_t loc, const char *gmsgid, ...)
void
internal_error (const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, input_location);
@@ -1452,6 +1502,7 @@ internal_error (const char *gmsgid, ...)
void
internal_error_no_backtrace (const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, input_location);
@@ -1509,6 +1560,33 @@ fancy_abort (const char *file, int line, const char *function)
internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
}
+/* class auto_diagnostic_group. */
+
+/* Constructor: "push" this group into global_dc. */
+
+auto_diagnostic_group::auto_diagnostic_group ()
+{
+ global_dc->diagnostic_group_nesting_depth++;
+}
+
+/* Destructor: "pop" this group from global_dc. */
+
+auto_diagnostic_group::~auto_diagnostic_group ()
+{
+ if (--global_dc->diagnostic_group_nesting_depth == 0)
+ {
+ /* Handle the case where we've popped the final diagnostic group.
+ If any diagnostics were emitted, give the context a chance
+ to do something. */
+ if (global_dc->diagnostic_group_emission_count > 0)
+ {
+ if (global_dc->end_group_cb)
+ global_dc->end_group_cb (global_dc);
+ }
+ global_dc->diagnostic_group_emission_count = 0;
+ }
+}
+
/* Really call the system 'abort'. This has to go right at the end of
this file, so that there are no functions after it that call abort
and get the system abort instead of our macro. */
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index cf3a610..34ea03b 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -204,6 +204,13 @@ struct diagnostic_context
a token, which would look strange). */
bool colorize_source_p;
+ /* When printing source code, should labelled ranges be printed? */
+ bool show_labels_p;
+
+ /* When printing source code, should there be a left-hand margin
+ showing line numbers? */
+ bool show_line_numbers_p;
+
/* Usable by plugins; if true, print a debugging ruler above the
source output. */
bool show_ruler_p;
@@ -215,6 +222,23 @@ struct diagnostic_context
/* If non-NULL, an edit_context to which fix-it hints should be
applied, for generating patches. */
edit_context *edit_context_ptr;
+
+ /* How many diagnostic_group instances are currently alive. */
+ int diagnostic_group_nesting_depth;
+
+ /* How many diagnostics have been emitted since the bottommost
+ diagnostic_group was pushed. */
+ int diagnostic_group_emission_count;
+
+ /* Optional callbacks for handling diagnostic groups. */
+
+ /* If non-NULL, this will be called immediately before the first
+ time a diagnostic is emitted within a stack of groups. */
+ void (*begin_group_cb) (diagnostic_context * context);
+
+ /* If non-NULL, this will be called when a stack of groups is
+ popped if any diagnostics were emitted within that group. */
+ void (*end_group_cb) (diagnostic_context * context);
};
static inline void
diff --git a/gcc/doc/cpp.texi b/gcc/doc/cpp.texi
index 3f7a8fc..efad2c8 100644
--- a/gcc/doc/cpp.texi
+++ b/gcc/doc/cpp.texi
@@ -2381,6 +2381,10 @@ If GCC cannot determine the current date, it will emit a warning message
These macros are defined when the target processor supports atomic compare
and swap operations on operands 1, 2, 4, 8 or 16 bytes in length, respectively.
+@item __HAVE_SPECULATION_SAFE_VALUE
+This macro is defined with the value 1 to show that this version of GCC
+supports @code{__builtin_speculation_safe_value}.
+
@item __GCC_HAVE_DWARF2_CFI_ASM
This macro is defined when the compiler is emitting DWARF CFI directives
to the assembler. When this is defined, it is possible to emit those same
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 63ef39a..7a69655 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -843,8 +843,8 @@ for targets with @code{long long} integer less than 128 bits wide.
@cindex @code{LL} integer suffix
@cindex @code{ULL} integer suffix
-ISO C99 supports data types for integers that are at least 64 bits wide,
-and as an extension GCC supports them in C90 mode and in C++.
+ISO C99 and ISO C++11 support data types for integers that are at least
+64 bits wide, and as an extension GCC supports them in C90 and C++98 modes.
Simply write @code{long long int} for a signed integer, or
@code{unsigned long long int} for an unsigned integer. To make an
integer constant of type @code{long long int}, add the suffix @samp{LL}
@@ -1121,11 +1121,11 @@ are supported by the DWARF debug information format.
@section Hex Floats
@cindex hex floats
-ISO C99 supports floating-point numbers written not only in the usual
-decimal notation, such as @code{1.55e1}, but also numbers such as
+ISO C99 and ISO C++17 support floating-point numbers written not only in
+the usual decimal notation, such as @code{1.55e1}, but also numbers such as
@code{0x1.fp3} written in hexadecimal format. As a GNU extension, GCC
supports this in C90 mode (except in some cases when strictly
-conforming) and in C++. In that format the
+conforming) and in C++98, C++11 and C++14 modes. In that format the
@samp{0x} hex introducer and the @samp{p} or @samp{P} exponent field are
mandatory. The exponent is a decimal number that indicates the power of
2 by which the significant part is multiplied. Thus @samp{0x1.f} is
@@ -2324,6 +2324,7 @@ GCC plugins may provide their own attributes.
* AVR Function Attributes::
* Blackfin Function Attributes::
* CR16 Function Attributes::
+* C-SKY Function Attributes::
* Epiphany Function Attributes::
* H8/300 Function Attributes::
* IA-64 Function Attributes::
@@ -2941,7 +2942,9 @@ that the pointer @var{P} returned by the function cannot alias any
other pointer valid when the function returns, and moreover no
pointers to valid objects occur in any storage addressed by @var{P}.
-Using this attribute can improve optimization. Functions like
+Using this attribute can improve optimization. Compiler predicts
+that a function with the attribute returns non-null in most cases.
+Functions like
@code{malloc} and @code{calloc} have this property because they return
a pointer to uninitialized or zeroed-out storage. However, functions
like @code{realloc} do not have this property, as they can return a
@@ -3154,6 +3157,9 @@ The @code{noreturn} keyword does not affect the exceptional path when that
applies: a @code{noreturn}-marked function may still return to the caller
by throwing an exception or calling @code{longjmp}.
+In order to preserve backtraces, GCC will never turn calls to
+@code{noreturn} functions into tail calls.
+
Do not assume that registers saved by the calling function are
restored before calling the @code{noreturn} function.
@@ -4145,6 +4151,38 @@ function entry and exit sequences suitable for use in an interrupt handler
when this attribute is present.
@end table
+@node C-SKY Function Attributes
+@subsection C-SKY Function Attributes
+
+These function attributes are supported by the C-SKY back end:
+
+@table @code
+@item interrupt
+@itemx isr
+@cindex @code{interrupt} function attribute, C-SKY
+@cindex @code{isr} function attribute, C-SKY
+Use these attributes to indicate that the specified function
+is an interrupt handler.
+The compiler generates function entry and exit sequences suitable for
+use in an interrupt handler when either of these attributes are present.
+
+Use of these options requires the @option{-mistack} command-line option
+to enable support for the necessary interrupt stack instructions. They
+are ignored with a warning otherwise. @xref{C-SKY Options}.
+
+@item naked
+@cindex @code{naked} function attribute, C-SKY
+This attribute allows the compiler to construct the
+requisite function declaration, while allowing the body of the
+function to be assembly code. The specified function will not have
+prologue/epilogue sequences generated by the compiler. Only basic
+@code{asm} statements can safely be included in naked functions
+(@pxref{Basic Asm}). While using extended @code{asm} or a mixture of
+basic @code{asm} and C code may appear to work, they cannot be
+depended upon to work reliably and are not supported.
+@end table
+
+
@node Epiphany Function Attributes
@subsection Epiphany Function Attributes
@@ -10960,6 +10998,7 @@ is called and the @var{flag} argument passed to it.
@findex __builtin_powi
@findex __builtin_powif
@findex __builtin_powil
+@findex __builtin_speculation_safe_value
@findex _Exit
@findex _exit
@findex abort
@@ -11604,6 +11643,96 @@ check its compatibility with @var{size}.
@end deftypefn
+@deftypefn {Built-in Function} @var{type} __builtin_speculation_safe_value (@var{type} val, @var{type} failval)
+
+This built-in function can be used to help mitigate against unsafe
+speculative execution. @var{type} may be any integral type or any
+pointer type.
+
+@enumerate
+@item
+If the CPU is not speculatively executing the code, then @var{val}
+is returned.
+@item
+If the CPU is executing speculatively then either:
+@itemize
+@item
+The function may cause execution to pause until it is known that the
+code is no-longer being executed speculatively (in which case
+@var{val} can be returned, as above); or
+@item
+The function may use target-dependent speculation tracking state to cause
+@var{failval} to be returned when it is known that speculative
+execution has incorrectly predicted a conditional branch operation.
+@end itemize
+@end enumerate
+
+The second argument, @var{failval}, is optional and defaults to zero
+if omitted.
+
+GCC defines the preprocessor macro
+@code{__HAVE_BUILTIN_SPECULATION_SAFE_VALUE} for targets that have been
+updated to support this builtin.
+
+The built-in function can be used where a variable appears to be used in a
+safe way, but the CPU, due to speculative execution may temporarily ignore
+the bounds checks. Consider, for example, the following function:
+
+@smallexample
+int array[500];
+int f (unsigned untrusted_index)
+@{
+ if (untrusted_index < 500)
+ return array[untrusted_index];
+ return 0;
+@}
+@end smallexample
+
+If the function is called repeatedly with @code{untrusted_index} less
+than the limit of 500, then a branch predictor will learn that the
+block of code that returns a value stored in @code{array} will be
+executed. If the function is subsequently called with an
+out-of-range value it will still try to execute that block of code
+first until the CPU determines that the prediction was incorrect
+(the CPU will unwind any incorrect operations at that point).
+However, depending on how the result of the function is used, it might be
+possible to leave traces in the cache that can reveal what was stored
+at the out-of-bounds location. The built-in function can be used to
+provide some protection against leaking data in this way by changing
+the code to:
+
+@smallexample
+int array[500];
+int f (unsigned untrusted_index)
+@{
+ if (untrusted_index < 500)
+ return array[__builtin_speculation_safe_value (untrusted_index)];
+ return 0;
+@}
+@end smallexample
+
+The built-in function will either cause execution to stall until the
+conditional branch has been fully resolved, or it may permit
+speculative execution to continue, but using 0 instead of
+@code{untrusted_value} if that exceeds the limit.
+
+If accessing any memory location is potentially unsafe when speculative
+execution is incorrect, then the code can be rewritten as
+
+@smallexample
+int array[500];
+int f (unsigned untrusted_index)
+@{
+ if (untrusted_index < 500)
+ return *__builtin_speculation_safe_value (&array[untrusted_index], NULL);
+ return 0;
+@}
+@end smallexample
+
+which will cause a @code{NULL} pointer to be used for the unsafe case.
+
+@end deftypefn
+
@deftypefn {Built-in Function} int __builtin_types_compatible_p (@var{type1}, @var{type2})
You can use the built-in function @code{__builtin_types_compatible_p} to
@@ -11863,6 +11992,15 @@ if (__builtin_expect (ptr != NULL, 1))
when testing pointer or floating-point values.
@end deftypefn
+@deftypefn {Built-in Function} long __builtin_expect_with_probability
+(long @var{exp}, long @var{c}, long @var{probability})
+
+The built-in has same semantics as @code{__builtin_expect_with_probability},
+but user can provide expected probability (in percent) for value of @var{exp}.
+Last argument @var{probability} is of float type and valid values
+are in inclusive range 0.0f and 1.0f.
+@end deftypefn
+
@deftypefn {Built-in Function} void __builtin_trap (void)
This function causes the program to exit abnormally. GCC implements
this function by using a target-dependent mechanism (such as
@@ -18383,16 +18521,16 @@ vector __uint128 vec_vsubcuq (vector __uint128, vector __uint128);
__int128 vec_vsubuqm (__int128, __int128);
__uint128 vec_vsubuqm (__uint128, __uint128);
-vector __int128 __builtin_bcdadd (vector __int128, vector __int128);
-int __builtin_bcdadd_lt (vector __int128, vector __int128);
-int __builtin_bcdadd_eq (vector __int128, vector __int128);
-int __builtin_bcdadd_gt (vector __int128, vector __int128);
-int __builtin_bcdadd_ov (vector __int128, vector __int128);
-vector __int128 bcdsub (vector __int128, vector __int128);
-int __builtin_bcdsub_lt (vector __int128, vector __int128);
-int __builtin_bcdsub_eq (vector __int128, vector __int128);
-int __builtin_bcdsub_gt (vector __int128, vector __int128);
-int __builtin_bcdsub_ov (vector __int128, vector __int128);
+vector __int128 __builtin_bcdadd (vector __int128, vector __int128, const int);
+int __builtin_bcdadd_lt (vector __int128, vector __int128, const int);
+int __builtin_bcdadd_eq (vector __int128, vector __int128, const int);
+int __builtin_bcdadd_gt (vector __int128, vector __int128, const int);
+int __builtin_bcdadd_ov (vector __int128, vector __int128, const int);
+vector __int128 __builtin_bcdsub (vector __int128, vector __int128, const int);
+int __builtin_bcdsub_lt (vector __int128, vector __int128, const int);
+int __builtin_bcdsub_eq (vector __int128, vector __int128, const int);
+int __builtin_bcdsub_gt (vector __int128, vector __int128, const int);
+int __builtin_bcdsub_ov (vector __int128, vector __int128, const int);
@end smallexample
@node PowerPC AltiVec Built-in Functions Available on ISA 3.0
@@ -23550,9 +23688,9 @@ deprecated. @xref{Deprecated Features}.
@item Implicit C language
Old C system header files did not contain an @code{extern "C" @{@dots{}@}}
scope to set the language. On such systems, all system header files are
-implicitly scoped inside a C language scope. Also, an empty prototype
-@code{()} is treated as an unspecified number of arguments, rather
-than no arguments, as C++ demands.
+implicitly scoped inside a C language scope. Such headers must
+correctly prototype function argument types, there is no leeway for
+@code{()} to indicate an unspecified set of arguments.
@end table
diff --git a/gcc/doc/gcov-dump.texi b/gcc/doc/gcov-dump.texi
index e526bde..0313358 100644
--- a/gcc/doc/gcov-dump.texi
+++ b/gcc/doc/gcov-dump.texi
@@ -61,7 +61,7 @@ gcov-dump [@option{-v}|@option{--version}]
[@option{-h}|@option{--help}]
[@option{-l}|@option{--long}]
[@option{-p}|@option{--positions}]
- [@option{-w}|@option{--working-sets}] @var{gcovfiles}
+ @var{gcovfiles}
@c man end
@end ignore
@@ -84,10 +84,6 @@ Dump positions of records.
@itemx --version
Display the @command{gcov-dump} version number (on the standard output),
and exit without doing any further processing.
-
-@item -w
-@itemx --working-sets
-Dump working set computed from summary.
@end table
@c man end
diff --git a/gcc/doc/gcov.texi b/gcc/doc/gcov.texi
index dfa86f1..3b1b38a 100644
--- a/gcc/doc/gcov.texi
+++ b/gcc/doc/gcov.texi
@@ -132,6 +132,7 @@ gcov [@option{-v}|@option{--version}] [@option{-h}|@option{--help}]
[@option{-n}|@option{--no-output}]
[@option{-o}|@option{--object-directory} @var{directory|file}]
[@option{-p}|@option{--preserve-paths}]
+ [@option{-q}|@option{--use-hotness-colors}]
[@option{-r}|@option{--relative-only}]
[@option{-s}|@option{--source-prefix} @var{directory}]
[@option{-t}|@option{--stdout}]
@@ -255,7 +256,7 @@ lcount:36,1,0
@item -j
@itemx --human-readable
-Write counts in human readable format (like 24k).
+Write counts in human readable format (like 24.6k).
@item -k
@itemx --use-colors
@@ -264,7 +265,6 @@ Use colors for lines of code that have zero coverage. We use red color for
non-exceptional lines and cyan for exceptional. Same colors are used for
basic blocks with @option{-a} option.
-
@item -l
@itemx --long-file-names
Create long file names for included source files. For example, if the
@@ -305,6 +305,12 @@ removed and unremoveable @file{..}
components renamed to @samp{^}. This is useful if sourcefiles are in several
different directories.
+@item -q
+@itemx --use-hotness-colors
+
+Emit perf-like colored output for hot lines. Legend of the color scale
+is printed at the very beginning of the output file.
+
@item -r
@itemx --relative-only
Only output information about source files with a relative pathname
@@ -340,7 +346,7 @@ Print verbose informations related to basic blocks and arcs.
@item -x
@itemx --hash-filenames
-By default, gcov uses the full pathname of the source files to to create
+By default, gcov uses the full pathname of the source files to create
an output filename. This can lead to long filenames that can overflow
filesystem limits. This option creates names of the form
@file{@var{source-file}##@var{md5}.gcov},
diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi
index a4d0af4..cf4bcf5 100644
--- a/gcc/doc/generic.texi
+++ b/gcc/doc/generic.texi
@@ -2198,7 +2198,7 @@ edge. Rethrowing the exception is represented using @code{RESX_EXPR}.
@tindex OMP_CLAUSE
All the statements starting with @code{OMP_} represent directives and
-clauses used by the OpenMP API @w{@uref{http://www.openmp.org/}}.
+clauses used by the OpenMP API @w{@uref{https://www.openmp.org}}.
@table @code
@item OMP_PARALLEL
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 03eaeed..61ab97e 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -366,7 +366,7 @@ download_prerequisites installs.
@item MPFR Library version 2.4.2 (or later)
Necessary to build GCC@. It can be downloaded from
-@uref{http://www.mpfr.org/}. If an MPFR source distribution is found
+@uref{https://www.mpfr.org}. If an MPFR source distribution is found
in a subdirectory of your GCC sources named @file{mpfr}, it will be
built together with GCC. Alternatively, if MPFR is already installed
but it is not in your default library search path, the
@@ -378,7 +378,7 @@ download_prerequisites installs.
@item MPC Library version 0.8.1 (or later)
Necessary to build GCC@. It can be downloaded from
-@uref{http://www.multiprecision.org/}. If an MPC source distribution
+@uref{http://www.multiprecision.org/mpc/}. If an MPC source distribution
is found in a subdirectory of your GCC sources named @file{mpc}, it
will be built together with GCC. Alternatively, if MPC is already
installed but it is not in your default library search path, the
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 27097d7..abbd9ec 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -229,13 +229,15 @@ in the following sections.
-fext-numeric-literals @gol
-Wabi=@var{n} -Wabi-tag -Wconversion-null -Wctor-dtor-privacy @gol
-Wdelete-non-virtual-dtor -Wdeprecated-copy -Wliteral-suffix @gol
--Wmultiple-inheritance @gol
+-Wmultiple-inheritance -Wno-init-list-lifetime @gol
-Wnamespaces -Wnarrowing @gol
+-Wpessimizing-move -Wredundant-move @gol
-Wnoexcept -Wnoexcept-type -Wclass-memaccess @gol
-Wnon-virtual-dtor -Wreorder -Wregister @gol
-Weffc++ -Wstrict-null-sentinel -Wtemplates @gol
-Wno-non-template-friend -Wold-style-cast @gol
-Woverloaded-virtual -Wno-pmf-conversions @gol
+-Wno-class-conversion -Wno-terminate @gol
-Wsign-promo -Wvirtual-inheritance}
@item Objective-C and Objective-C++ Language Options
@@ -267,6 +269,7 @@ Objective-C and Objective-C++ Dialects}.
-fdiagnostics-show-location=@r{[}once@r{|}every-line@r{]} @gol
-fdiagnostics-color=@r{[}auto@r{|}never@r{|}always@r{]} @gol
-fno-diagnostics-show-option -fno-diagnostics-show-caret @gol
+-fno-diagnostics-show-labels -fno-diagnostics-show-line-numbers @gol
-fdiagnostics-parseable-fixits -fdiagnostics-generate-patch @gol
-fdiagnostics-show-template-tree -fno-elide-type @gol
-fno-show-column}
@@ -275,7 +278,7 @@ Objective-C and Objective-C++ Dialects}.
@xref{Warning Options,,Options to Request or Suppress Warnings}.
@gccoptlist{-fsyntax-only -fmax-errors=@var{n} -Wpedantic @gol
-pedantic-errors @gol
--w -Wextra -Wall -Waddress -Waggregate-return @gol
+-w -Wextra -Wall -Waddress -Waggregate-return -Waligned-new @gol
-Walloc-zero -Walloc-size-larger-than=@var{byte-size}
-Walloca -Walloca-larger-than=@var{byte-size} @gol
-Wno-aggressive-loop-optimizations -Warray-bounds -Warray-bounds=@var{n} @gol
@@ -371,7 +374,7 @@ Objective-C and Objective-C++ Dialects}.
-ginternal-reset-location-views -gno-internal-reset-location-views @gol
-ginline-points -gno-inline-points @gol
-gvms -gxcoff -gxcoff+ -gz@r{[}=@var{type}@r{]} @gol
--gsplit-dwarf @gol
+-gsplit-dwarf -gdescribe-dies -gno-describe-dies @gol
-fdebug-prefix-map=@var{old}=@var{new} -fdebug-types-section @gol
-fno-eliminate-unused-debug-types @gol
-femit-struct-debug-baseonly -femit-struct-debug-reduced @gol
@@ -462,7 +465,7 @@ Objective-C and Objective-C++ Dialects}.
-ftree-loop-ivcanon -ftree-loop-linear -ftree-loop-optimize @gol
-ftree-loop-vectorize @gol
-ftree-parallelize-loops=@var{n} -ftree-pre -ftree-partial-pre -ftree-pta @gol
--ftree-reassoc -ftree-sink -ftree-slsr -ftree-sra @gol
+-ftree-reassoc -ftree-scev-cprop -ftree-sink -ftree-slsr -ftree-sra @gol
-ftree-switch-conversion -ftree-tail-merge @gol
-ftree-ter -ftree-vectorize -ftree-vrp -funconstrained-commons @gol
-funit-at-a-time -funroll-all-loops -funroll-loops @gol
@@ -518,7 +521,7 @@ Objective-C and Objective-C++ Dialects}.
@xref{Link Options,,Options for Linking}.
@gccoptlist{@var{object-file-name} -fuse-ld=@var{linker} -l@var{library} @gol
-nostartfiles -nodefaultlibs -nolibc -nostdlib @gol
--pie -pthread -rdynamic @gol
+-pie -pthread -r -rdynamic @gol
-s -static -static-pie -static-libgcc -static-libstdc++ @gol
-static-libasan -static-libtsan -static-liblsan -static-libubsan @gol
-shared -shared-libgcc -symbolic @gol
@@ -565,6 +568,7 @@ Objective-C and Objective-C++ Dialects}.
-fdisable-rtl-@var{pass-name}=@var{range-list} @gol
-fdisable-tree-@var{pass_name} @gol
-fdisable-tree-@var{pass-name}=@var{range-list} @gol
+-fdump-debug -fdump-earlydebug @gol
-fdump-noaddr -fdump-unnumbered -fdump-unnumbered-links @gol
-fdump-class-hierarchy@r{[}-@var{n}@r{]} @gol
-fdump-final-insns@r{[}=@var{file}@r{]} @gol
@@ -617,7 +621,7 @@ Objective-C and Objective-C++ Dialects}.
-mpc-relative-literal-loads @gol
-msign-return-address=@var{scope} @gol
-march=@var{name} -mcpu=@var{name} -mtune=@var{name} @gol
--moverride=@var{string} -mverbose-cost-dump}
+-moverride=@var{string} -mverbose-cost-dump -mtrack-speculation}
@emph{Adapteva Epiphany Options}
@gccoptlist{-mhalf-reg-file -mprefer-short-insn-regs @gol
@@ -722,6 +726,16 @@ Objective-C and Objective-C++ Dialects}.
-msim -mint32 -mbit-ops
-mdata-model=@var{model}}
+@emph{C-SKY Options}
+@gccoptlist{-march=@var{arch} -mcpu=@var{cpu} @gol
+-mbig-endian -EB -mlittle-endian -EL @gol
+-mhard-float -msoft-float -mfpu=@var{fpu} -mdouble-float -mfdivdu @gol
+-melrw -mistack -mmp -mcp -mcache -msecurity -mtrust @gol
+-mdsp -medsp -mvdsp @gol
+-mdiv -msmart -mhigh-registers -manchor @gol
+-mpushpop -mmultiple-stld -mconstpool -mstack-size -mccrt @gol
+-mbranch-cost=@var{n} -mcse-cc -msched-prolog}
+
@emph{Darwin Options}
@gccoptlist{-all_load -allowable_client -arch -arch_errors_fatal @gol
-arch_only -bind_at_load -bundle -bundle_loader @gol
@@ -1099,7 +1113,6 @@ See RS/6000 and PowerPC Options.
-mblock-compare-inline-loop-limit=@var{num} @gol
-mstring-compare-inline-limit=@var{num} @gol
-misel -mno-isel @gol
--misel=yes -misel=no @gol
-mvrsave -mno-vrsave @gol
-mmulhw -mno-mulhw @gol
-mdlmzb -mno-dlmzb @gol
@@ -1291,7 +1304,7 @@ See RS/6000 and PowerPC Options.
-malign-data=@var{type} -mstack-protector-guard=@var{guard} @gol
-mstack-protector-guard-reg=@var{reg} @gol
-mstack-protector-guard-offset=@var{offset} @gol
--mstack-protector-guard-symbol=@var{symbol} -mmitigate-rop @gol
+-mstack-protector-guard-symbol=@var{symbol} @gol
-mgeneral-regs-only -mcall-ms2sysv-xlogues @gol
-mindirect-branch=@var{choice} -mfunction-return=@var{choice} @gol
-mindirect-branch-register}
@@ -2166,7 +2179,7 @@ can be omitted, to use a target-specific default value.
Enable handling of OpenMP directives @code{#pragma omp} in C/C++ and
@code{!$omp} in Fortran. When @option{-fopenmp} is specified, the
compiler generates parallel code according to the OpenMP Application
-Program Interface v4.5 @w{@uref{http://www.openmp.org/}}. This option
+Program Interface v4.5 @w{@uref{https://www.openmp.org}}. This option
implies @option{-pthread}, and thus is only supported on targets that
have support for @option{-pthread}. @option{-fopenmp} implies
@option{-fopenmp-simd}.
@@ -3056,7 +3069,7 @@ void h() @{ f(g); @}
@end smallexample
@noindent
-In C++14, @code{f} calls calls @code{f<void(*)()>}, but in
+In C++14, @code{f} calls @code{f<void(*)()>}, but in
C++17 it calls @code{f<void(*)()noexcept>}.
@item -Wclass-memaccess @r{(C++ and Objective-C++ only)}
@@ -3120,6 +3133,74 @@ The compiler rearranges the member initializers for @code{i}
and @code{j} to match the declaration order of the members, emitting
a warning to that effect. This warning is enabled by @option{-Wall}.
+@item -Wno-pessimizing-move @r{(C++ and Objective-C++ only)}
+@opindex Wpessimizing-move
+@opindex Wno-pessimizing-move
+This warning warns when a call to @code{std::move} prevents copy
+elision. A typical scenario when copy elision can occur is when returning in
+a function with a class return type, when the expression being returned is the
+name of a non-volatile automatic object, and is not a function parameter, and
+has the same type as the function return type.
+
+@smallexample
+struct T @{
+@dots{}
+@};
+T fn()
+@{
+ T t;
+ @dots{}
+ return std::move (t);
+@}
+@end smallexample
+
+But in this example, the @code{std::move} call prevents copy elision.
+
+This warning is enabled by @option{-Wall}.
+
+@item -Wno-redundant-move @r{(C++ and Objective-C++ only)}
+@opindex Wredundant-move
+@opindex Wno-redundant-move
+This warning warns about redundant calls to @code{std::move}; that is, when
+a move operation would have been performed even without the @code{std::move}
+call. This happens because the compiler is forced to treat the object as if
+it were an rvalue in certain situations such as returning a local variable,
+where copy elision isn't applicable. Consider:
+
+@smallexample
+struct T @{
+@dots{}
+@};
+T fn(T t)
+@{
+ @dots{}
+ return std::move (t);
+@}
+@end smallexample
+
+Here, the @code{std::move} call is redundant. Because G++ implements Core
+Issue 1579, another example is:
+
+@smallexample
+struct T @{ // convertible to U
+@dots{}
+@};
+struct U @{
+@dots{}
+@};
+U fn()
+@{
+ T t;
+ @dots{}
+ return std::move (t);
+@}
+@end smallexample
+In this example, copy elision isn't applicable because the type of the
+expression being returned and the function return type differ, yet G++
+treats the return value as if it were designated by an rvalue.
+
+This warning is enabled by @option{-Wextra}.
+
@item -fext-numeric-literals @r{(C++ and Objective-C++ only)}
@opindex fext-numeric-literals
@opindex fno-ext-numeric-literals
@@ -3286,6 +3367,13 @@ use the STL. One may also use using directives and qualified names.
@opindex Wno-terminate
Disable the warning about a throw-expression that will immediately
result in a call to @code{terminate}.
+
+@item -Wno-class-conversion @r{(C++ and Objective-C++ only)}
+@opindex Wno-class-conversion
+@opindex Wclass-conversion
+Disable the warning about the case when a conversion function converts an
+object to the same type, to a base class of that type, or to void; such
+a conversion function will never be called.
@end table
@node Objective-C and Objective-C++ Dialect Options
@@ -3710,6 +3798,30 @@ the @option{-fmessage-length=n} option is given. When the output is done
to the terminal, the width is limited to the width given by the
@env{COLUMNS} environment variable or, if not set, to the terminal width.
+@item -fno-diagnostics-show-labels
+@opindex fno-diagnostics-show-labels
+@opindex fdiagnostics-show-labels
+By default, when printing source code (via @option{-fdiagnostics-show-caret}),
+diagnostics can label ranges of source code with pertinent information, such
+as the types of expressions:
+
+@smallexample
+ printf ("foo %s bar", long_i + long_j);
+ ~^ ~~~~~~~~~~~~~~~
+ | |
+ char * long int
+@end smallexample
+
+This option suppresses the printing of these labels (in the example above,
+the vertical bars and the ``char *'' and ``long int'' text).
+
+@item -fno-diagnostics-show-line-numbers
+@opindex fno-diagnostics-show-line-numbers
+@opindex fdiagnostics-show-line-numbers
+By default, when printing source code (via @option{-fdiagnostics-show-caret}),
+a left margin is printed, showing line numbers. This option suppresses this
+left margin.
+
@item -fdiagnostics-parseable-fixits
@opindex fdiagnostics-parseable-fixits
Emit fix-it hints in a machine-parseable format, suitable for consumption
@@ -4001,6 +4113,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}.
-Wnonnull-compare @gol
-Wopenmp-simd @gol
-Wparentheses @gol
+-Wpessimizing-move @r{(only for C++)} @gol
-Wpointer-sign @gol
-Wreorder @gol
-Wrestrict @gol
@@ -4049,6 +4162,7 @@ name is still supported, but the newer name is more descriptive.)
-Wold-style-declaration @r{(C only)} @gol
-Woverride-init @gol
-Wsign-compare @r{(C only)} @gol
+-Wredundant-move @r{(only for C++)} @gol
-Wtype-limits @gol
-Wuninitialized @gol
-Wshift-negative-value @r{(in C++03 and in C99 and newer)} @gol
@@ -4587,7 +4701,7 @@ The @option{-Wimplicit-fallthrough=3} warning is enabled by @option{-Wextra}.
@opindex Wif-not-aligned
@opindex Wno-if-not-aligned
Control if warning triggered by the @code{warn_if_not_aligned} attribute
-should be issued. This is is enabled by default.
+should be issued. This is enabled by default.
Use @option{-Wno-if-not-aligned} to disable it.
@item -Wignored-qualifiers @r{(C and C++ only)}
@@ -6174,6 +6288,14 @@ example, warn if an unsigned variable is compared against zero with
@code{<} or @code{>=}. This warning is also enabled by
@option{-Wextra}.
+@item -Wabsolute-value @r{(C and Objective-C only)}
+@opindex Wabsolute-value
+@opindex Wno-absolute-value
+Warn when a wrong absolute value function seems to be used or when it
+does not have any effect because its argument is an unsigned type.
+This warning be suppressed with an explicit type cast and it is also
+enabled by @option{-Wextra}.
+
@include cppwarnopts.texi
@item -Wbad-function-cast @r{(C and Objective-C only)}
@@ -7359,6 +7481,12 @@ the build system to avoid linking files with debug information. To
be useful, this option requires a debugger capable of reading @file{.dwo}
files.
+@item -gdescribe-dies
+@opindex gdescribe-dies
+Add description attributes to some DWARF DIEs that have no name attribute,
+such as artificial variables, external references and call site
+parameter DIEs.
+
@item -gpubnames
@opindex gpubnames
Generate DWARF @code{.debug_pubnames} and @code{.debug_pubtypes} sections.
@@ -7706,6 +7834,7 @@ compilation time.
-ftree-forwprop @gol
-ftree-fre @gol
-ftree-phiprop @gol
+-ftree-scev-cprop @gol
-ftree-sink @gol
-ftree-slsr @gol
-ftree-sra @gol
@@ -9013,6 +9142,15 @@ determining number of iterations requires complicated analysis. Later
optimizations then may determine the number easily. Useful especially
in connection with unrolling.
+@item -ftree-scev-cprop
+@opindex ftree-scev-cprop
+Perform final value replacement. If a variable is modified in a loop
+in such a way that its value when exiting the loop can be determined using
+only its initial value and the number of loop iterations, replace uses of
+the final value by such a computation, provided it is sufficiently cheap.
+This reduces data dependencies and may allow further simplifications.
+Enabled by default at @option{-O} and higher.
+
@item -fivopts
@opindex fivopts
Perform induction variable optimizations (strength reduction, induction
@@ -9210,6 +9348,9 @@ between the heuristics and @code{__builtin_expect} can be complex, and in
some cases, it may be useful to disable the heuristics so that the effects
of @code{__builtin_expect} are easier to understand.
+It is also possible to specify expected probability of the expression
+with @code{__builtin_expect_with_probability} built-in function.
+
The default is @option{-fguess-branch-probability} at levels
@option{-O}, @option{-O2}, @option{-O3}, @option{-Os}.
@@ -9613,7 +9754,7 @@ for LTO, use @command{gcc-ar} and @command{gcc-ranlib} instead of @command{ar}
and @command{ranlib};
to show the symbols of object files with GIMPLE bytecode, use
@command{gcc-nm}. Those commands require that @command{ar}, @command{ranlib}
-and @command{nm} have been compiled with plugin support. At link time, use the the
+and @command{nm} have been compiled with plugin support. At link time, use the
flag @option{-fuse-linker-plugin} to ensure that the library participates in
the LTO optimization process:
@@ -10966,11 +11107,12 @@ parameter sets a limit on the length of the sets that are computed,
which prevents the runaway behavior. Setting a value of 0 for
this parameter allows an unlimited set length.
-@item sccvn-max-scc-size
-Maximum size of a strongly connected component (SCC) during SCCVN
-processing. If this limit is hit, SCCVN processing for the whole
-function is not done and optimizations depending on it are
-disabled. The default maximum SCC size is 10000.
+@item rpo-vn-max-loop-depth
+Maximum loop depth that is value-numbered optimistically. The default
+maximum loop depth is three. When the limit hits the innermost
+@var{rpo-vn-max-loop-depth} loops and the outermost loop in the
+loop nest are value-numbered optimistically and the remaining ones not.
+The default maximum loop depth is seven.
@item sccvn-max-alias-queries-per-access
Maximum number of alias-oracle queries we perform when looking for
@@ -12444,6 +12586,11 @@ x86 Cygwin and MinGW targets. On some targets this option also sets
flags for the preprocessor, so it should be used consistently for both
compilation and linking.
+@item -r
+@opindex r
+Produce a relocatable object as output. This is also known as partial
+linking.
+
@item -rdynamic
@opindex rdynamic
Pass the flag @option{-export-dynamic} to the ELF linker, on targets
@@ -12490,9 +12637,9 @@ of these is when the application wishes to throw and catch exceptions
across different shared libraries. In that case, each of the libraries
as well as the application itself should use the shared @file{libgcc}.
-Therefore, the G++ and driver automatically adds @option{-shared-libgcc}
- whenever you build a shared library or a main executable, because C++
- programs typically use exceptions, so this is the right thing to do.
+Therefore, the G++ driver automatically adds @option{-shared-libgcc}
+whenever you build a shared library or a main executable, because C++
+programs typically use exceptions, so this is the right thing to do.
If, instead, you use the GCC driver to create shared libraries, you may
find that they are not always linked with the shared @file{libgcc}.
@@ -12506,8 +12653,7 @@ propagate through such shared libraries, without incurring relocation
costs at library load time.
However, if a library or main executable is supposed to throw or catch
-exceptions, you must link it using the G++ driver, as appropriate
-for the languages used in the program, or using the option
+exceptions, you must link it using the G++ driver, or using the option
@option{-shared-libgcc}, such that it is linked with the shared
@file{libgcc}.
@@ -13739,6 +13885,16 @@ Just generate RTL for a function instead of compiling it. Usually used
with @option{-fdump-rtl-expand}.
@end table
+@item -fdump-debug
+@opindex fdump-debug
+Dump debugging information generated during the debug
+generation phase.
+
+@item -fdump-earlydebug
+@opindex fdump-earlydebug
+Dump debugging information generated during the early debug
+generation phase.
+
@item -fdump-noaddr
@opindex fdump-noaddr
When doing debugging dumps, suppress address output. This makes it more
@@ -14605,6 +14761,7 @@ platform.
* C6X Options::
* CRIS Options::
* CR16 Options::
+* C-SKY Options::
* Darwin Options::
* DEC Alpha Options::
* FR30 Options::
@@ -14786,6 +14943,14 @@ This option only has an effect if @option{-ffast-math} or
precision of division results to about 16 bits for
single precision and to 32 bits for double precision.
+@item -mtrack-speculation
+@itemx -mno-track-speculation
+Enable or disable generation of additional code to track speculative
+execution through conditional branches. The tracking state can then
+be used by the compiler when expanding calls to
+@code{__builtin_speculation_safe_copy} to permit a more efficient code
+sequence to be generated.
+
@item -march=@var{name}
@opindex march
Specify the name of the target architecture and, optionally, one or
@@ -14832,8 +14997,8 @@ performance of the code. Permissible values for this option are:
@samp{generic}, @samp{cortex-a35}, @samp{cortex-a53}, @samp{cortex-a55},
@samp{cortex-a57}, @samp{cortex-a72}, @samp{cortex-a73}, @samp{cortex-a75},
@samp{cortex-a76}, @samp{exynos-m1}, @samp{falkor}, @samp{qdf24xx},
-@samp{saphira}, @samp{xgene1}, @samp{vulcan}, @samp{thunderx},
-@samp{thunderxt88}, @samp{thunderxt88p1}, @samp{thunderxt81},
+@samp{saphira}, @samp{phecda}, @samp{xgene1}, @samp{vulcan}, @samp{thunderx},
+@samp{thunderxt88}, @samp{thunderxt88p1}, @samp{thunderxt81},@samp{tsv110},
@samp{thunderxt83}, @samp{thunderx2t99}, @samp{cortex-a57.cortex-a53},
@samp{cortex-a72.cortex-a53}, @samp{cortex-a73.cortex-a35},
@samp{cortex-a73.cortex-a53}, @samp{cortex-a75.cortex-a55},
@@ -17721,6 +17886,198 @@ However, @samp{far} is not valid with @option{-mcr16c}, as the
CR16C architecture does not support the far data model.
@end table
+@node C-SKY Options
+@subsection C-SKY Options
+@cindex C-SKY Options
+
+GCC supports these options when compiling for C-SKY V2 processors.
+
+@table @gcctabopt
+
+@item -march=@var{arch}
+@opindex march=
+Specify the C-SKY target architecture. Valid values for @var{arch} are:
+@samp{ck801}, @samp{ck802}, @samp{ck803}, @samp{ck807}, and @samp{ck810}.
+The default is @samp{ck810}.
+
+@item -mcpu=@var{cpu}
+@opindex mcpu=
+Specify the C-SKY target processor. Valid values for @var{cpu} are:
+@samp{ck801}, @samp{ck801t},
+@samp{ck802}, @samp{ck802t}, @samp{ck802j},
+@samp{ck803}, @samp{ck803h}, @samp{ck803t}, @samp{ck803ht},
+@samp{ck803f}, @samp{ck803fh}, @samp{ck803e}, @samp{ck803eh},
+@samp{ck803et}, @samp{ck803eht}, @samp{ck803ef}, @samp{ck803efh},
+@samp{ck803ft}, @samp{ck803eft}, @samp{ck803efht}, @samp{ck803r1},
+@samp{ck803hr1}, @samp{ck803tr1}, @samp{ck803htr1}, @samp{ck803fr1},
+@samp{ck803fhr1}, @samp{ck803er1}, @samp{ck803ehr1}, @samp{ck803etr1},
+@samp{ck803ehtr1}, @samp{ck803efr1}, @samp{ck803efhr1}, @samp{ck803ftr1},
+@samp{ck803eftr1}, @samp{ck803efhtr1},
+@samp{ck803s}, @samp{ck803st}, @samp{ck803se}, @samp{ck803sf},
+@samp{ck803sef}, @samp{ck803seft},
+@samp{ck807e}, @samp{ck807ef}, @samp{ck807}, @samp{ck807f},
+@samp{ck810e}, @samp{ck810et}, @samp{ck810ef}, @samp{ck810eft},
+@samp{ck810}, @samp{ck810v}, @samp{ck810f}, @samp{ck810t}, @samp{ck810fv},
+@samp{ck810tv}, @samp{ck810ft}, and @samp{ck810ftv}.
+
+@item -mbig-endian
+@opindex mbig-endian
+@itemx -EB
+@opindex -EB
+@itemx -mlittle-endian
+@opindex mlittle-endian
+@itemx -EL
+@opindex -EL
+
+Select big- or little-endian code. The default is little-endian.
+
+@item -mhard-float
+@opindex mhard-float
+@itemx -msoft-float
+@opindex msoft-float
+
+Select hardware or software floating-point implementations.
+The default is soft float.
+
+@item -mdouble-float
+@itemx -mno-double-float
+@opindex mdouble-float
+When @option{-mhard-float} is in effect, enable generation of
+double-precision float instructions. This is the default except
+when compiling for CK803.
+
+@item -mfdivdu
+@itemx -mno-fdivdu
+@opindex mfdivdu
+When @option{-mhard-float} is in effect, enable generation of
+@code{frecipd}, @code{fsqrtd}, and @code{fdivd} instructions.
+This is the default except when compiling for CK803.
+
+@item -mfpu=@var{fpu}
+@opindex mfpu=
+Select the floating-point processor. This option can only be used with
+@option{-mhard-float}.
+Values for @var{fpu} are
+@samp{fpv2_sf} (equivalent to @samp{-mno-double-float -mno-fdivdu}),
+@samp{fpv2} (@samp{-mdouble-float -mno-divdu}), and
+@samp{fpv2_divd} (@samp{-mdouble-float -mdivdu}).
+
+@item -melrw
+@itemx -mno-elrw
+@opindex melrw
+Enable the extended @code{lrw} instruction. This option defaults to on
+for CK801 and off otherwise.
+
+@item -mistack
+@itemx -mno-istack
+@opindex mistack
+Enable interrupt stack instructions; the default is off.
+
+The @option{-mistack} option is required to handle the
+@code{interrupt} and @code{isr} function attributes
+(@pxref{C-SKY Function Attributes}).
+
+@item -mmp
+@opindex mmp
+Enable multiprocessor instructions; the default is off.
+
+@item -mcp
+@opindex mcp
+Enable coprocessor instructions; the default is off.
+
+@item -mcache
+@opindex mcache
+Enable coprocessor instructions; the default is off.
+
+@item -msecurity
+@opindex msecurity
+Enable C-SKY security instructions; the default is off.
+
+@item -mtrust
+@opindex mtrust
+Enable C-SKY trust instructions; the default is off.
+
+@item -mdsp
+@opindex mdsp
+@itemx -medsp
+@opindex medsp
+@itemx -mvdsp
+@opindex mvdsp
+Enable C-SKY DSP, Enhanced DSP, or Vector DSP instructions, respectively.
+All of these options default to off.
+
+@item -mdiv
+@itemx -mno-div
+@opindex mdiv
+Generate divide instructions. Default is off.
+
+@item -msmart
+@itemx -mno-smart
+@opindex msmart
+Generate code for Smart Mode, using only registers numbered 0-7 to allow
+use of 16-bit instructions. This option is ignored for CK801 where this
+is the required behavior, and it defaults to on for CK802.
+For other targets, the default is off.
+
+@item -mhigh-registers
+@itemx -mno-high-registers
+@opindex mhigh-registers
+Generate code using the high registers numbered 16-31. This option
+is not supported on CK801, CK802, or CK803, and is enabled by default
+for other processors.
+
+@item -manchor
+@itemx -mno-anchor
+@opindex manchor
+Generate code using global anchor symbol addresses.
+
+@item -mpushpop
+@itemx -mno-pushpop
+@opindex mpushpop
+Generate code using @code{push} and @code{pop} instructions. This option
+defaults to on.
+
+@item -mmultiple-stld
+@itemx -mstm
+@itemx -mno-multiple-stld
+@itemx -mno-stm
+@opindex mmultiple-stld
+Generate code using @code{stm} and @code{ldm} instructions. This option
+isn't supported on CK801 but is enabled by default on other processors.
+
+@item -mconstpool
+@itemx -mno-constpool
+@opindex mconstpool
+Create constant pools in the compiler instead of deferring it to the
+assembler. This option is the default and required for correct code
+generation on CK801 and CK802, and is optional on other processors.
+
+@item -mstack-size
+@item -mno-stack-size
+@opindex mstack-size
+Emit @code{.stack_size} directives for each function in the assembly
+output. This option defaults to off.
+
+@item -mccrt
+@itemx -mno-ccrt
+@opindex mccrt
+Generate code for the C-SKY compiler runtime instead of libgcc. This
+option defaults to off.
+
+@item -mbranch-cost=@var{n}
+@opindex mbranch-cost=
+Set the branch costs to roughly @code{n} instructions. The default is 1.
+
+@item -msched-prolog
+@itemx -mno-sched-prolog
+@opindex msched-prolog
+Permit scheduling of function prologue and epilogue sequences. Using
+this option can result in code that is not compliant with the C-SKY V2 ABI
+prologue requirements and that cannot be debugged or backtraced.
+It is disabled by default.
+
+@end table
+
@node Darwin Options
@subsection Darwin Options
@cindex Darwin options
@@ -20151,7 +20508,7 @@ Use features of, and schedule code for, the given CPU.
Supported values are in the format @samp{v@var{X}.@var{YY}.@var{Z}},
where @var{X} is a major version, @var{YY} is the minor version, and
@var{Z} is compatibility code. Example values are @samp{v3.00.a},
-@samp{v4.00.b}, @samp{v5.00.a}, @samp{v5.00.b}, @samp{v5.00.b}, @samp{v6.00.a}.
+@samp{v4.00.b}, @samp{v5.00.a}, @samp{v5.00.b}, @samp{v6.00.a}.
@item -mxl-soft-mul
@opindex mxl-soft-mul
@@ -21831,7 +22188,7 @@ GP-relative addressing. It is most useful in conjunction with
The @var{regexp} is a POSIX Extended Regular Expression.
This option does not affect the behavior of the @option{-G} option, and
-and the specified sections are in addition to the standard @code{.sdata}
+the specified sections are in addition to the standard @code{.sdata}
and @code{.sbss} small-data sections that are recognized by @option{-mgpopt}.
@item -mr0rel-sec=@var{regexp}
@@ -22134,6 +22491,12 @@ These options are defined for Nvidia PTX:
@opindex m64
Generate code for 32-bit or 64-bit ABI.
+@item -misa=@var{ISA-string}
+@opindex march
+Generate code for given the specified PTX ISA (e.g.@ @samp{sm_35}). ISA
+strings must be lower-case. Valid ISA strings include @samp{sm_30} and
+@samp{sm_35}. The default ISA is sm_30.
+
@item -mmainkernel
@opindex mmainkernel
Link in code for a __main kernel. This is for stand-alone instead of
@@ -23577,10 +23940,6 @@ This is a PowerPC 32-bit SYSV ABI option.
@opindex mno-isel
This switch enables or disables the generation of ISEL instructions.
-@item -misel=@var{yes/no}
-This switch has been deprecated. Use @option{-misel} and
-@option{-mno-isel} instead.
-
@item -mvsx
@itemx -mno-vsx
@opindex mvsx
@@ -24224,12 +24583,10 @@ target-specific.
@item -mstring-compare-inline-limit=@var{num}
@opindex mstring-compare-inline-limit
-Generate at most @var{num} pairs of load instructions to compare the
-string inline. If the difference or end of string is not found at the
+Compare at most @var{num} string bytes with inline code.
+If the difference or end of string is not found at the
end of the inline compare a call to @code{strcmp} or @code{strncmp} will
-take care of the rest of the comparison. The default is 8 pairs of
-loads, which will compare 64 bytes on a 64-bit target and 32 bytes on a
-32-bit target.
+take care of the rest of the comparison. The default is 64 bytes.
@item -G @var{num}
@opindex G
@@ -24849,8 +25206,7 @@ system representing a certain processor type. Possible values for
@samp{z196}/@samp{arch9}, @samp{zEC12}, @samp{z13}/@samp{arch11}, and
@samp{native}.
-The default is @option{-march=z900}. @samp{g5}/@samp{arch3} and
-@samp{g6} are deprecated and will be removed with future releases.
+The default is @option{-march=z900}.
Specifying @samp{native} as cpu type can be used to select the best
architecture option for the host processor.
@@ -27605,11 +27961,11 @@ To use this option, both @option{-ftree-vectorize} and
ABI-compatible library must be specified at link time.
GCC currently emits calls to @code{vmldExp2},
-@code{vmldLn2}, @code{vmldLog102}, @code{vmldLog102}, @code{vmldPow2},
+@code{vmldLn2}, @code{vmldLog102}, @code{vmldPow2},
@code{vmldTanh2}, @code{vmldTan2}, @code{vmldAtan2}, @code{vmldAtanh2},
@code{vmldCbrt2}, @code{vmldSinh2}, @code{vmldSin2}, @code{vmldAsinh2},
@code{vmldAsin2}, @code{vmldCosh2}, @code{vmldCos2}, @code{vmldAcosh2},
-@code{vmldAcos2}, @code{vmlsExp4}, @code{vmlsLn4}, @code{vmlsLog104},
+@code{vmldAcos2}, @code{vmlsExp4}, @code{vmlsLn4},
@code{vmlsLog104}, @code{vmlsPow4}, @code{vmlsTanh4}, @code{vmlsTan4},
@code{vmlsAtan4}, @code{vmlsAtanh4}, @code{vmlsCbrt4}, @code{vmlsSinh4},
@code{vmlsSin4}, @code{vmlsAsinh4}, @code{vmlsAsin4}, @code{vmlsCosh4},
@@ -27968,13 +28324,6 @@ which segment register (@code{%fs} or @code{%gs}) to use as base register
for reading the canary, and from what offset from that base register.
The default for those is as specified in the relevant ABI.
-@item -mmitigate-rop
-@opindex mmitigate-rop
-Try to avoid generating code sequences that contain unintended return
-opcodes, to mitigate against certain forms of attack. At the moment,
-this option is limited in what it can do and should not be relied
-on to provide serious protection.
-
@item -mgeneral-regs-only
@opindex mgeneral-regs-only
Generate code that uses only the general-purpose registers. This
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 734bc76..4801d68 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -115,26 +115,37 @@ A @code{define_insn} is an RTL expression containing four or five operands:
@enumerate
@item
-An optional name. The presence of a name indicates that this instruction
-pattern can perform a certain standard job for the RTL-generation
-pass of the compiler. This pass knows certain names and will use
-the instruction patterns with those names, if the names are defined
-in the machine description.
+An optional name @var{n}. When a name is present, the compiler
+automically generates a C++ function @samp{gen_@var{n}} that takes
+the operands of the instruction as arguments and returns the instruction's
+rtx pattern. The compiler also assigns the instruction a unique code
+@samp{CODE_FOR_@var{n}}, with all such codes belonging to an enum
+called @code{insn_code}.
+
+These names serve one of two purposes. The first is to indicate that the
+instruction performs a certain standard job for the RTL-generation
+pass of the compiler, such as a move, an addition, or a conditional
+jump. The second is to help the target generate certain target-specific
+operations, such as when implementing target-specific intrinsic functions.
+
+It is better to prefix target-specific names with the name of the
+target, to avoid any clash with current or future standard names.
The absence of a name is indicated by writing an empty string
where the name should go. Nameless instruction patterns are never
used for generating RTL code, but they may permit several simpler insns
to be combined later on.
-Names that are not thus known and used in RTL-generation have no
-effect; they are equivalent to no name at all.
-
For the purpose of debugging the compiler, you may also specify a
name beginning with the @samp{*} character. Such a name is used only
for identifying the instruction in RTL dumps; it is equivalent to having
a nameless pattern for all other purposes. Names beginning with the
@samp{*} character are not required to be unique.
+The name may also have the form @samp{@@@var{n}}. This has the same
+effect as a name @samp{@var{n}}, but in addition tells the compiler to
+generate further helper functions; see @ref{Parameterized Names} for details.
+
@item
The @dfn{RTL template}: This is a vector of incomplete RTL expressions
which describe the semantics of the instruction (@pxref{RTL Template}).
@@ -2121,6 +2132,42 @@ Check for 64 bits wide constants for add/sub instructions
Floating point constant that is legal for store immediate
@end table
+@item C-SKY---@file{config/csky/constraints.md}
+@table @code
+
+@item a
+The mini registers r0 - r7.
+
+@item b
+The low registers r0 - r15.
+
+@item c
+C register.
+
+@item y
+HI and LO registers.
+
+@item l
+LO register.
+
+@item h
+HI register.
+
+@item v
+Vector registers.
+
+@item z
+Stack pointer register (SP).
+@end table
+
+@ifset INTERNALS
+The C-SKY back end supports a large set of additional constraints
+that are only useful for instruction selection or splitting rather
+than inline asm, such as constraints representing constant integer
+ranges accepted by particular instruction encodings.
+Refer to the source code for details.
+@end ifset
+
@item Epiphany---@file{config/epiphany/constraints.md}
@table @code
@item U16
@@ -7032,6 +7079,21 @@ should be defined to an instruction that orders both loads and stores
before the instruction with respect to loads and stores after the instruction.
This pattern has no operands.
+@cindex @code{speculation_barrier} instruction pattern
+@item @samp{speculation_barrier}
+If the target can support speculative execution, then this pattern should
+be defined to an instruction that will block subsequent execution until
+any prior speculation conditions has been resolved. The pattern must also
+ensure that the compiler cannot move memory operations past the barrier,
+so it needs to be an UNSPEC_VOLATILE pattern. The pattern has no
+operands.
+
+If this pattern is not defined then the default expansion of
+@code{__builtin_speculation_safe_value} will emit a warning. You can
+suppress this warning by defining this pattern with a final condition
+of @code{0} (zero), which tells the compiler that a speculation
+barrier is not needed for this target.
+
@cindex @code{sync_compare_and_swap@var{mode}} instruction pattern
@item @samp{sync_compare_and_swap@var{mode}}
This pattern, if defined, emits code for an atomic compare-and-swap
@@ -10476,6 +10538,7 @@ facilities to make this process easier.
* Code Iterators:: Doing the same for codes.
* Int Iterators:: Doing the same for integers.
* Subst Iterators:: Generating variations of patterns for define_subst.
+* Parameterized Names:: Specifying iterator values in C++ code.
@end menu
@node Mode Iterators
@@ -10871,4 +10934,101 @@ replaced in the first copy of the original RTL-template.
@var{subst-applied-value} is a value with which subst-attribute would be
replaced in the second copy of the original RTL-template.
+@node Parameterized Names
+@subsection Parameterized Names
+@cindex @samp{@@} in instruction pattern names
+Ports sometimes need to apply iterators using C++ code, in order to
+get the code or RTL pattern for a specific instruction. For example,
+suppose we have the @samp{neon_vq<absneg><mode>} pattern given above:
+
+@smallexample
+(define_int_iterator QABSNEG [UNSPEC_VQABS UNSPEC_VQNEG])
+
+(define_int_attr absneg [(UNSPEC_VQABS "abs") (UNSPEC_VQNEG "neg")])
+
+(define_insn "neon_vq<absneg><mode>"
+ [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
+ (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
+ (match_operand:SI 2 "immediate_operand" "i")]
+ QABSNEG))]
+ @dots{}
+)
+@end smallexample
+
+A port might need to generate this pattern for a variable
+@samp{QABSNEG} value and a variable @samp{VDQIW} mode. There are two
+ways of doing this. The first is to build the rtx for the pattern
+directly from C++ code; this is a valid technique and avoids any risk
+of combinatorial explosion. The second is to prefix the instruction
+name with the special character @samp{@@}, which tells GCC to generate
+the four additional functions below. In each case, @var{name} is the
+name of the instruction without the leading @samp{@@} character,
+without the @samp{<@dots{}>} placeholders, and with any underscore
+before a @samp{<@dots{}>} placeholder removed if keeping it would
+lead to a double or trailing underscore.
+
+@table @samp
+@item insn_code maybe_code_for_@var{name} (@var{i1}, @var{i2}, @dots{})
+See whether replacing the first @samp{<@dots{}>} placeholder with
+iterator value @var{i1}, the second with iterator value @var{i2}, and
+so on, gives a valid instruction. Return its code if so, otherwise
+return @code{CODE_FOR_nothing}.
+
+@item insn_code code_for_@var{name} (@var{i1}, @var{i2}, @dots{})
+Same, but abort the compiler if the requested instruction does not exist.
+
+@item rtx maybe_gen_@var{name} (@var{i1}, @var{i2}, @dots{}, @var{op0}, @var{op1}, @dots{})
+Check for a valid instruction in the same way as
+@code{maybe_code_for_@var{name}}. If the instruction exists,
+generate an instance of it using the operand values given by @var{op0},
+@var{op1}, and so on, otherwise return null.
+
+@item rtx gen_@var{name} (@var{i1}, @var{i2}, @dots{}, @var{op0}, @var{op1}, @dots{})
+Same, but abort the compiler if the requested instruction does not exist,
+or if the instruction generator invoked the @code{FAIL} macro.
+@end table
+
+For example, changing the pattern above to:
+
+@smallexample
+(define_insn "@@neon_vq<absneg><mode>"
+ [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
+ (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
+ (match_operand:SI 2 "immediate_operand" "i")]
+ QABSNEG))]
+ @dots{}
+)
+@end smallexample
+
+would define the same patterns as before, but in addition would generate
+the four functions below:
+
+@smallexample
+insn_code maybe_code_for_neon_vq (int, machine_mode);
+insn_code code_for_neon_vq (int, machine_mode);
+rtx maybe_gen_neon_vq (int, machine_mode, rtx, rtx, rtx);
+rtx gen_neon_vq (int, machine_mode, rtx, rtx, rtx);
+@end smallexample
+
+Calling @samp{code_for_neon_vq (UNSPEC_VQABS, V8QImode)}
+would then give @code{CODE_FOR_neon_vqabsv8qi}.
+
+It is possible to have multiple @samp{@@} patterns with the same
+name and same types of iterator. For example:
+
+@smallexample
+(define_insn "@@some_arithmetic_op<mode>"
+ [(set (match_operand:INTEGER_MODES 0 "register_operand") @dots{})]
+ @dots{}
+)
+
+(define_insn "@@some_arithmetic_op<mode>"
+ [(set (match_operand:FLOAT_MODES 0 "register_operand") @dots{})]
+ @dots{}
+)
+@end smallexample
+
+would produce a single set of functions that handles both
+@code{INTEGER_MODES} and @code{FLOAT_MODES}.
+
@end ifset
diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi
index a37d9ac..0695ad2 100644
--- a/gcc/doc/rtl.texi
+++ b/gcc/doc/rtl.texi
@@ -144,7 +144,8 @@ Currently, @file{rtl.def} defines these classes:
An RTX code that represents an actual object, such as a register
(@code{REG}) or a memory location (@code{MEM}, @code{SYMBOL_REF}).
@code{LO_SUM}) is also included; instead, @code{SUBREG} and
-@code{STRICT_LOW_PART} are not in this class, but in class @code{x}.
+@code{STRICT_LOW_PART} are not in this class, but in class
+@code{RTX_EXTRA}.
@item RTX_CONST_OBJ
An RTX code that represents a constant object. @code{HIGH} is also
@@ -166,7 +167,7 @@ An RTX code for a unary arithmetic operation, such as @code{NEG},
@item RTX_COMM_ARITH
An RTX code for a commutative binary operation, such as @code{PLUS} or
@code{AND}. @code{NE} and @code{EQ} are comparisons, so they have class
-@code{<}.
+@code{RTX_COMM_COMPARE}.
@item RTX_BIN_ARITH
An RTX code for a non-commutative binary operation, such as @code{MINUS},
@@ -284,26 +285,28 @@ Some classes of RTX codes always have the same format. For example, it
is safe to assume that all comparison operations have format @code{ee}.
@table @code
-@item 1
+@item RTX_UNARY
All codes of this class have format @code{e}.
-@item <
-@itemx c
-@itemx 2
+@item RTX_BIN_ARITH
+@itemx RTX_COMM_ARITH
+@itemx RTX_COMM_COMPARE
+@itemx RTX_COMPARE
All codes of these classes have format @code{ee}.
-@item b
-@itemx 3
+@item RTX_BITFIELD_OPS
+@itemx RTX_TERNARY
All codes of these classes have format @code{eee}.
-@item i
+@item RTX_INSN
All codes of this class have formats that begin with @code{iuueiee}.
@xref{Insns}. Note that not all RTL objects linked onto an insn chain
-are of class @code{i}.
+are of class @code{RTX_INSN}.
-@item o
-@itemx m
-@itemx x
+@item RTX_CONST_OBJ
+@itemx RTX_OBJ
+@itemx RTX_MATCH
+@itemx RTX_EXTRA
You can make no assumptions about the format of these codes.
@end table
@@ -2936,11 +2939,12 @@ a set bit indicates it is taken from @var{vec1}.
@item (vec_select:@var{m} @var{vec1} @var{selection})
This describes an operation that selects parts of a vector. @var{vec1} is
the source vector, and @var{selection} is a @code{parallel} that contains a
-@code{const_int} for each of the subparts of the result vector, giving the
-number of the source subpart that should be stored into it.
-The result mode @var{m} is either the submode for a single element of
-@var{vec1} (if only one subpart is selected), or another vector mode
-with that element submode (if multiple subparts are selected).
+@code{const_int} (or another expression, if the selection can be made at
+runtime) for each of the subparts of the result vector, giving the number of
+the source subpart that should be stored into it. The result mode @var{m} is
+either the submode for a single element of @var{vec1} (if only one subpart is
+selected), or another vector mode with that element submode (if multiple
+subparts are selected).
@findex vec_concat
@item (vec_concat:@var{m} @var{x1} @var{x2})
@@ -3296,6 +3300,18 @@ There is one other known use for clobbering a pseudo register in a
clobbered by the insn. In this case, using the same pseudo register in
the clobber and elsewhere in the insn produces the expected results.
+@findex clobber_high
+@item (clobber_high @var{x})
+Represents the storing or possible storing of an unpredictable,
+undescribed value into the upper parts of @var{x}. The mode of the expression
+represents the lower parts of the register which will not be overwritten.
+@code{reg} must be a reg expression.
+
+One place this is used is when calling into functions where the registers are
+preserved, but only up to a given number of bits. For example when using
+Aarch64 SVE, calling a TLS descriptor will cause only the lower 128 bits of
+each of the vector registers to be preserved.
+
@findex use
@item (use @var{x})
Represents the use of the value of @var{x}. It indicates that the
@@ -3349,7 +3365,8 @@ Represents several side effects performed in parallel. The square
brackets stand for a vector; the operand of @code{parallel} is a
vector of expressions. @var{x0}, @var{x1} and so on are individual
side effect expressions---expressions of code @code{set}, @code{call},
-@code{return}, @code{simple_return}, @code{clobber} or @code{use}.
+@code{return}, @code{simple_return}, @code{clobber} @code{use} or
+@code{clobber_high}.
``In parallel'' means that first all the values used in the individual
side-effects are computed, and second all the actual side-effects are
diff --git a/gcc/doc/service.texi b/gcc/doc/service.texi
index df6dbc7..684ff3b 100644
--- a/gcc/doc/service.texi
+++ b/gcc/doc/service.texi
@@ -20,7 +20,7 @@ a bug in GCC, please report it following the instructions at
@item
Look in the service directory for someone who might help you for a fee.
The service directory is found at
-@uref{http://www.fsf.org/resources/service}.
+@uref{https://www.fsf.org/resources/service}.
@end itemize
For further information, see
diff --git a/gcc/doc/standards.texi b/gcc/doc/standards.texi
index a9e7133..bde233e 100644
--- a/gcc/doc/standards.texi
+++ b/gcc/doc/standards.texi
@@ -294,7 +294,7 @@ GCC has currently no support for non-fragile instance variables.
The authoritative manual on Objective-C 2.0 is available from Apple:
@itemize
@item
-@uref{https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Introduction/Introduction.html}
+@uref{https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Introduction/Introduction.html}
@end itemize
For more information concerning the history of Objective-C that is
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 0ddcd1a..561bda3 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -5057,6 +5057,10 @@ Returns true if the target wants GCC's default stack protect runtime support, ot
Whether this target supports splitting the stack when the options described in @var{opts} have been passed. This is called after options have been parsed, so the target may reject splitting the stack in some configurations. The default version of this hook returns false. If @var{report} is true, this function may issue a warning or error; if @var{report} is false, it must simply return a value
@end deftypefn
+@deftypefn {Common Target Hook} {vec<const char *>} TARGET_GET_VALID_OPTION_VALUES (int @var{option_code}, const char *@var{prefix})
+The hook is used for options that have a non-trivial list of possible option values. OPTION_CODE is option code of opt_code enum type. PREFIX is used for bash completion and allows an implementation to return more specific completion based on the prefix. All string values should be allocated from heap memory and consumers should release them. The result will be pruned to cases with PREFIX if not NULL.
+@end deftypefn
+
@node Miscellaneous Register Hooks
@subsection Miscellaneous register hooks
@cindex miscellaneous register hooks
@@ -5267,24 +5271,78 @@ into the stack. Arguments meaning is similar to
@end deftypefn
@node Trampolines
-@section Trampolines for Nested Functions
+@section Support for Nested Functions
+@cindex support for nested functions
@cindex trampolines for nested functions
-@cindex nested functions, trampolines for
-
-A @dfn{trampoline} is a small piece of code that is created at run time
-when the address of a nested function is taken. It normally resides on
-the stack, in the stack frame of the containing function. These macros
-tell GCC how to generate code to allocate and initialize a
-trampoline.
-
-The instructions in the trampoline must do two things: load a constant
-address into the static chain register, and jump to the real address of
-the nested function. On CISC machines such as the m68k, this requires
-two instructions, a move immediate and a jump. Then the two addresses
-exist in the trampoline as word-long immediate operands. On RISC
-machines, it is often necessary to load each address into a register in
-two parts. Then pieces of each address form separate immediate
-operands.
+@cindex descriptors for nested functions
+@cindex nested functions, support for
+
+Taking the address of a nested function requires special compiler
+handling to ensure that the static chain register is loaded when
+the function is invoked via an indirect call.
+
+GCC has traditionally supported nested functions by creating an
+executable @dfn{trampoline} at run time when the address of a nested
+function is taken. This is a small piece of code which normally
+resides on the stack, in the stack frame of the containing function.
+The trampoline loads the static chain register and then jumps to the
+real address of the nested function.
+
+The use of trampolines requires an executable stack, which is a
+security risk. To avoid this problem, GCC also supports another
+strategy: using descriptors for nested functions. Under this model,
+taking the address of a nested function results in a pointer to a
+non-executable function descriptor object. Initializing the static chain
+from the descriptor is handled at indirect call sites.
+
+On some targets, including HPPA and IA-64, function descriptors may be
+mandated by the ABI or be otherwise handled in a target-specific way
+by the back end in its code generation strategy for indirect calls.
+GCC also provides its own generic descriptor implementation to support the
+@option{-fno-trampolines} option. In this case runtime detection of
+function descriptors at indirect call sites relies on descriptor
+pointers being tagged with a bit that is never set in bare function
+addresses. Since GCC's generic function descriptors are
+not ABI-compliant, this option is typically used only on a
+per-language basis (notably by Ada) or when it can otherwise be
+applied to the whole program.
+
+Define the following hook if your backend either implements ABI-specified
+descriptor support, or can use GCC's generic descriptor implementation
+for nested functions.
+
+@deftypevr {Target Hook} int TARGET_CUSTOM_FUNCTION_DESCRIPTORS
+If the target can use GCC's generic descriptor mechanism for nested
+functions, define this hook to a power of 2 representing an unused bit
+in function pointers which can be used to differentiate descriptors at
+run time. This value gives the number of bytes by which descriptor
+pointers are misaligned compared to function pointers. For example, on
+targets that require functions to be aligned to a 4-byte boundary, a
+value of either 1 or 2 is appropriate unless the architecture already
+reserves the bit for another purpose, such as on ARM.
+
+Define this hook to 0 if the target implements ABI support for
+function descriptors in its standard calling sequence, like for example
+HPPA or IA-64.
+
+Using descriptors for nested functions
+eliminates the need for trampolines that reside on the stack and require
+it to be made executable.
+@end deftypevr
+
+The following macros tell GCC how to generate code to allocate and
+initialize an executable trampoline. You can also use this interface
+if your back end needs to create ABI-specified non-executable descriptors; in
+this case the "trampoline" created is the descriptor containing data only.
+
+The instructions in an executable trampoline must do two things: load
+a constant address into the static chain register, and jump to the real
+address of the nested function. On CISC machines such as the m68k,
+this requires two instructions, a move immediate and a jump. Then the
+two addresses exist in the trampoline as word-long immediate operands.
+On RISC machines, it is often necessary to load each address into a
+register in two parts. Then pieces of each address form separate
+immediate operands.
The code generated to initialize the trampoline must store the variable
parts---the static chain value and the function address---into the
@@ -5351,24 +5409,6 @@ be returned; otherwise @var{addr} should be returned unchanged.
If this hook is not defined, @var{addr} will be used for function calls.
@end deftypefn
-@deftypevr {Target Hook} int TARGET_CUSTOM_FUNCTION_DESCRIPTORS
-This hook should be defined to a power of 2 if the target will benefit
-from the use of custom descriptors for nested functions instead of the
-standard trampolines. Such descriptors are created at run time on the
-stack and made up of data only, but they are non-standard so the generated
-code must be prepared to deal with them. This hook should be defined to 0
-if the target uses function descriptors for its standard calling sequence,
-like for example HP-PA or IA-64. Using descriptors for nested functions
-eliminates the need for trampolines that reside on the stack and require
-it to be made executable.
-
-The value of the macro is used to parameterize the run-time identification
-scheme implemented to distinguish descriptors from function addresses: it
-gives the number of bytes by which their address is misaligned compared
-with function addresses. The value of 1 will generally work, unless it is
-already reserved by the target for another purpose, like for example on ARM.
-@end deftypevr
-
Implementing trampolines is difficult on many machines because they have
separate instruction and data caches. Writing into a stack location
fails to clear the memory in the instruction cache, so when the program
@@ -11924,6 +11964,42 @@ maintainer is familiar with.
@end defmac
+@deftypefn {Target Hook} bool TARGET_HAVE_SPECULATION_SAFE_VALUE (bool @var{active})
+This hook is used to determine the level of target support for
+ @code{__builtin_speculation_safe_value}. If called with an argument
+ of false, it returns true if the target has been modified to support
+ this builtin. If called with an argument of true, it returns true
+ if the target requires active mitigation execution might be speculative.
+
+ The default implementation returns false if the target does not define
+ a pattern named @code{speculation_barrier}. Else it returns true
+ for the first case and whether the pattern is enabled for the current
+ compilation for the second case.
+
+ For targets that have no processors that can execute instructions
+ speculatively an alternative implemenation of this hook is available:
+ simply redefine this hook to @code{speculation_safe_value_not_needed}
+ along with your other target hooks.
+@end deftypefn
+
+@deftypefn {Target Hook} rtx TARGET_SPECULATION_SAFE_VALUE (machine_mode @var{mode}, rtx @var{result}, rtx @var{val}, rtx @var{failval})
+This target hook can be used to generate a target-specific code
+ sequence that implements the @code{__builtin_speculation_safe_value}
+ built-in function. The function must always return @var{val} in
+ @var{result} in mode @var{mode} when the cpu is not executing
+ speculatively, but must never return that when speculating until it
+ is known that the speculation will not be unwound. The hook supports
+ two primary mechanisms for implementing the requirements. The first
+ is to emit a speculation barrier which forces the processor to wait
+ until all prior speculative operations have been resolved; the second
+ is to use a target-specific mechanism that can track the speculation
+ state and to return @var{failval} if it can determine that
+ speculation must be unwound at a later time.
+
+ The default implementation simply copies @var{val} to @var{result} and
+ emits a @code{speculation_barrier} instruction if that is defined.
+@end deftypefn
+
@deftypefn {Target Hook} void TARGET_RUN_TARGET_SELFTESTS (void)
If selftests are enabled, run any selftests for this target.
@end deftypefn
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index e275aca..c509a9b 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -3669,6 +3669,8 @@ generic code.
@hook TARGET_SUPPORTS_SPLIT_STACK
+@hook TARGET_GET_VALID_OPTION_VALUES
+
@node Miscellaneous Register Hooks
@subsection Miscellaneous register hooks
@cindex miscellaneous register hooks
@@ -3766,24 +3768,61 @@ These machine description macros help implement varargs:
@hook TARGET_SETUP_INCOMING_VARARG_BOUNDS
@node Trampolines
-@section Trampolines for Nested Functions
+@section Support for Nested Functions
+@cindex support for nested functions
@cindex trampolines for nested functions
-@cindex nested functions, trampolines for
-
-A @dfn{trampoline} is a small piece of code that is created at run time
-when the address of a nested function is taken. It normally resides on
-the stack, in the stack frame of the containing function. These macros
-tell GCC how to generate code to allocate and initialize a
-trampoline.
-
-The instructions in the trampoline must do two things: load a constant
-address into the static chain register, and jump to the real address of
-the nested function. On CISC machines such as the m68k, this requires
-two instructions, a move immediate and a jump. Then the two addresses
-exist in the trampoline as word-long immediate operands. On RISC
-machines, it is often necessary to load each address into a register in
-two parts. Then pieces of each address form separate immediate
-operands.
+@cindex descriptors for nested functions
+@cindex nested functions, support for
+
+Taking the address of a nested function requires special compiler
+handling to ensure that the static chain register is loaded when
+the function is invoked via an indirect call.
+
+GCC has traditionally supported nested functions by creating an
+executable @dfn{trampoline} at run time when the address of a nested
+function is taken. This is a small piece of code which normally
+resides on the stack, in the stack frame of the containing function.
+The trampoline loads the static chain register and then jumps to the
+real address of the nested function.
+
+The use of trampolines requires an executable stack, which is a
+security risk. To avoid this problem, GCC also supports another
+strategy: using descriptors for nested functions. Under this model,
+taking the address of a nested function results in a pointer to a
+non-executable function descriptor object. Initializing the static chain
+from the descriptor is handled at indirect call sites.
+
+On some targets, including HPPA and IA-64, function descriptors may be
+mandated by the ABI or be otherwise handled in a target-specific way
+by the back end in its code generation strategy for indirect calls.
+GCC also provides its own generic descriptor implementation to support the
+@option{-fno-trampolines} option. In this case runtime detection of
+function descriptors at indirect call sites relies on descriptor
+pointers being tagged with a bit that is never set in bare function
+addresses. Since GCC's generic function descriptors are
+not ABI-compliant, this option is typically used only on a
+per-language basis (notably by Ada) or when it can otherwise be
+applied to the whole program.
+
+Define the following hook if your backend either implements ABI-specified
+descriptor support, or can use GCC's generic descriptor implementation
+for nested functions.
+
+@hook TARGET_CUSTOM_FUNCTION_DESCRIPTORS
+
+The following macros tell GCC how to generate code to allocate and
+initialize an executable trampoline. You can also use this interface
+if your back end needs to create ABI-specified non-executable descriptors; in
+this case the "trampoline" created is the descriptor containing data only.
+
+The instructions in an executable trampoline must do two things: load
+a constant address into the static chain register, and jump to the real
+address of the nested function. On CISC machines such as the m68k,
+this requires two instructions, a move immediate and a jump. Then the
+two addresses exist in the trampoline as word-long immediate operands.
+On RISC machines, it is often necessary to load each address into a
+register in two parts. Then pieces of each address form separate
+immediate operands.
The code generated to initialize the trampoline must store the variable
parts---the static chain value and the function address---into the
@@ -3815,8 +3854,6 @@ is used for aligning trampolines.
@hook TARGET_TRAMPOLINE_ADJUST_ADDRESS
-@hook TARGET_CUSTOM_FUNCTION_DESCRIPTORS
-
Implementing trampolines is difficult on many machines because they have
separate instruction and data caches. Writing into a stack location
fails to clear the memory in the instruction cache, so when the program
@@ -8101,4 +8138,8 @@ maintainer is familiar with.
@end defmac
+@hook TARGET_HAVE_SPECULATION_SAFE_VALUE
+
+@hook TARGET_SPECULATION_SAFE_VALUE
+
@hook TARGET_RUN_TARGET_SELFTESTS
diff --git a/gcc/dojump.c b/gcc/dojump.c
index 88cc96a..56c82c5f 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -1215,15 +1215,15 @@ do_compare_and_jump (tree treeop0, tree treeop1, enum rtx_code signed_code,
code = unsignedp ? unsigned_code : signed_code;
/* If function pointers need to be "canonicalized" before they can
- be reliably compared, then canonicalize them.
- Only do this if *both* sides of the comparison are function pointers.
- If one side isn't, we want a noncanonicalized comparison. See PR
- middle-end/17564. */
+ be reliably compared, then canonicalize them. Canonicalize the
+ expression when one of the operands is a function pointer. This
+ handles the case where the other operand is a void pointer. See
+ PR middle-end/17564. */
if (targetm.have_canonicalize_funcptr_for_compare ()
- && POINTER_TYPE_P (TREE_TYPE (treeop0))
- && POINTER_TYPE_P (TREE_TYPE (treeop1))
- && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (treeop0)))
- && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (treeop1))))
+ && ((POINTER_TYPE_P (TREE_TYPE (treeop0))
+ && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (treeop0))))
+ || (POINTER_TYPE_P (TREE_TYPE (treeop1))
+ && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (treeop1))))))
{
rtx new_op0 = gen_reg_rtx (mode);
rtx new_op1 = gen_reg_rtx (mode);
diff --git a/gcc/dse.c b/gcc/dse.c
index 26c6007..cfebfa0 100644
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -2419,8 +2419,7 @@ scan_insn (bb_info_t bb_info, rtx_insn *insn)
&& GET_CODE (sym) == SYMBOL_REF
&& SYMBOL_REF_DECL (sym)
&& TREE_CODE (SYMBOL_REF_DECL (sym)) == FUNCTION_DECL
- && DECL_BUILT_IN_CLASS (SYMBOL_REF_DECL (sym)) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (SYMBOL_REF_DECL (sym)) == BUILT_IN_MEMSET)
+ && fndecl_built_in_p (SYMBOL_REF_DECL (sym), BUILT_IN_MEMSET))
memset_call = SYMBOL_REF_DECL (sym);
if (const_call || memset_call)
diff --git a/gcc/dump-context.h b/gcc/dump-context.h
index a191e3a..5ac9dd6 100644
--- a/gcc/dump-context.h
+++ b/gcc/dump-context.h
@@ -22,6 +22,9 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_DUMP_CONTEXT_H
#define GCC_DUMP_CONTEXT_H 1
+#include "dumpfile.h"
+#include "pretty-print.h"
+
/* A class for handling the various dump_* calls.
In particular, this class has responsibility for consolidating
@@ -39,6 +42,10 @@ class dump_context
~dump_context ();
+ void refresh_dumps_are_enabled ();
+
+ void dump_loc (dump_flags_t dump_kind, const dump_location_t &loc);
+
void dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
gimple *gs, int spc);
@@ -67,11 +74,11 @@ class dump_context
tree t);
void dump_printf_va (dump_flags_t dump_kind, const char *format,
- va_list ap) ATTRIBUTE_PRINTF (3, 0);
+ va_list *ap) ATTRIBUTE_GCC_DUMP_PRINTF (3, 0);
void dump_printf_loc_va (dump_flags_t dump_kind, const dump_location_t &loc,
- const char *format, va_list ap)
- ATTRIBUTE_PRINTF (4, 0);
+ const char *format, va_list *ap)
+ ATTRIBUTE_GCC_DUMP_PRINTF (4, 0);
template<unsigned int N, typename C>
void dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value);
@@ -91,6 +98,8 @@ class dump_context
void end_any_optinfo ();
+ void emit_item (optinfo_item *item, dump_flags_t dump_kind);
+
private:
optinfo &ensure_pending_optinfo ();
optinfo &begin_next_optinfo (const dump_location_t &loc);
@@ -106,6 +115,11 @@ class dump_context
if any. */
optinfo *m_pending;
+ /* For use in selftests: if non-NULL, then items are to be printed
+ to this, using the given flags. */
+ pretty_printer *m_test_pp;
+ dump_flags_t m_test_pp_flags;
+
/* The currently active dump_context, for use by the dump_* API calls. */
static dump_context *s_current;
@@ -121,13 +135,16 @@ class dump_context
class temp_dump_context
{
public:
- temp_dump_context (bool forcibly_enable_optinfo);
+ temp_dump_context (bool forcibly_enable_optinfo,
+ dump_flags_t test_pp_flags);
~temp_dump_context ();
/* Support for selftests. */
optinfo *get_pending_optinfo () const { return m_context.m_pending; }
+ const char *get_dumped_text ();
private:
+ pretty_printer m_pp;
dump_context m_context;
dump_context *m_saved;
bool m_saved_flag_remarks;
diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c
index 176c9b8..5655e46 100644
--- a/gcc/dumpfile.c
+++ b/gcc/dumpfile.c
@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see
#include "cgraph.h"
#include "tree-pass.h" /* for "current_pass". */
#include "optinfo-emit-json.h"
+#include "stringpool.h" /* for get_identifier. */
/* If non-NULL, return one past-the-end of the matching SUBPART of
the WHOLE string. */
@@ -63,15 +64,6 @@ dump_flags_t dump_flags;
bool dumps_are_enabled = false;
-/* Update the "dumps_are_enabled" global; to be called whenever dump_file
- or alt_dump_file change. */
-
-static void
-refresh_dumps_are_enabled ()
-{
- dumps_are_enabled = (dump_file || alt_dump_file || optinfo_enabled_p ());
-}
-
/* Set global "dump_file" to NEW_DUMP_FILE, refreshing the "dumps_are_enabled"
global. */
@@ -80,7 +72,7 @@ set_dump_file (FILE *new_dump_file)
{
dumpfile_ensure_any_optinfo_are_flushed ();
dump_file = new_dump_file;
- refresh_dumps_are_enabled ();
+ dump_context::get ().refresh_dumps_are_enabled ();
}
/* Set "alt_dump_file" to NEW_ALT_DUMP_FILE, refreshing the "dumps_are_enabled"
@@ -91,7 +83,7 @@ set_alt_dump_file (FILE *new_alt_dump_file)
{
dumpfile_ensure_any_optinfo_are_flushed ();
alt_dump_file = new_alt_dump_file;
- refresh_dumps_are_enabled ();
+ dump_context::get ().refresh_dumps_are_enabled ();
}
#define DUMP_FILE_INFO(suffix, swtch, dkind, num) \
@@ -406,7 +398,7 @@ dump_open_alternate_stream (struct dump_file_info *dfi)
/* Construct a dump_user_location_t from STMT (using its location and
hotness). */
-dump_user_location_t::dump_user_location_t (gimple *stmt)
+dump_user_location_t::dump_user_location_t (const gimple *stmt)
: m_count (), m_loc (UNKNOWN_LOCATION)
{
if (stmt)
@@ -420,7 +412,7 @@ dump_user_location_t::dump_user_location_t (gimple *stmt)
/* Construct a dump_user_location_t from an RTL instruction (using its
location and hotness). */
-dump_user_location_t::dump_user_location_t (rtx_insn *insn)
+dump_user_location_t::dump_user_location_t (const rtx_insn *insn)
: m_count (), m_loc (UNKNOWN_LOCATION)
{
if (insn)
@@ -465,6 +457,27 @@ dump_loc (dump_flags_t dump_kind, FILE *dfile, source_location loc)
}
}
+/* Print source location to PP if enabled. */
+
+static void
+dump_loc (dump_flags_t dump_kind, pretty_printer *pp, source_location loc)
+{
+ if (dump_kind)
+ {
+ if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION)
+ pp_printf (pp, "%s:%d:%d: note: ", LOCATION_FILE (loc),
+ LOCATION_LINE (loc), LOCATION_COLUMN (loc));
+ else if (current_function_decl)
+ pp_printf (pp, "%s:%d:%d: note: ",
+ DECL_SOURCE_FILE (current_function_decl),
+ DECL_SOURCE_LINE (current_function_decl),
+ DECL_SOURCE_COLUMN (current_function_decl));
+ /* Indentation based on scope depth. */
+ for (unsigned i = 0; i < get_dump_scope_depth (); i++)
+ pp_character (pp, ' ');
+ }
+}
+
/* Implementation of dump_context member functions. */
/* dump_context's dtor. */
@@ -474,6 +487,59 @@ dump_context::~dump_context ()
delete m_pending;
}
+/* Update the "dumps_are_enabled" global; to be called whenever dump_file
+ or alt_dump_file change, or when changing dump_context in selftests. */
+
+void
+dump_context::refresh_dumps_are_enabled ()
+{
+ dumps_are_enabled = (dump_file || alt_dump_file || optinfo_enabled_p ()
+ || m_test_pp);
+}
+
+/* Print LOC to the appropriate dump destinations, given DUMP_KIND.
+ If optinfos are enabled, begin a new optinfo. */
+
+void
+dump_context::dump_loc (dump_flags_t dump_kind, const dump_location_t &loc)
+{
+ end_any_optinfo ();
+
+ location_t srcloc = loc.get_location_t ();
+
+ if (dump_file && (dump_kind & pflags))
+ ::dump_loc (dump_kind, dump_file, srcloc);
+
+ if (alt_dump_file && (dump_kind & alt_flags))
+ ::dump_loc (dump_kind, alt_dump_file, srcloc);
+
+ /* Support for temp_dump_context in selftests. */
+ if (m_test_pp && (dump_kind & m_test_pp_flags))
+ ::dump_loc (dump_kind, m_test_pp, srcloc);
+
+ if (optinfo_enabled_p ())
+ {
+ optinfo &info = begin_next_optinfo (loc);
+ info.handle_dump_file_kind (dump_kind);
+ }
+}
+
+/* Make an item for the given dump call, equivalent to print_gimple_stmt. */
+
+static optinfo_item *
+make_item_for_dump_gimple_stmt (gimple *stmt, int spc, dump_flags_t dump_flags)
+{
+ pretty_printer pp;
+ pp_needs_newline (&pp) = true;
+ pp_gimple_stmt_1 (&pp, stmt, spc, dump_flags);
+ pp_newline (&pp);
+
+ optinfo_item *item
+ = new optinfo_item (OPTINFO_ITEM_KIND_GIMPLE, gimple_location (stmt),
+ xstrdup (pp_formatted_text (&pp)));
+ return item;
+}
+
/* Dump gimple statement GS with SPC indentation spaces and
EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
@@ -482,18 +548,18 @@ dump_context::dump_gimple_stmt (dump_flags_t dump_kind,
dump_flags_t extra_dump_flags,
gimple *gs, int spc)
{
- if (dump_file && (dump_kind & pflags))
- print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
-
- if (alt_dump_file && (dump_kind & alt_flags))
- print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
+ optinfo_item *item
+ = make_item_for_dump_gimple_stmt (gs, spc, dump_flags | extra_dump_flags);
+ emit_item (item, dump_kind);
if (optinfo_enabled_p ())
{
optinfo &info = ensure_pending_optinfo ();
info.handle_dump_file_kind (dump_kind);
- info.add_gimple_stmt (gs, spc, dump_flags | extra_dump_flags);
+ info.add_item (item);
}
+ else
+ delete item;
}
/* Similar to dump_gimple_stmt, except additionally print source location. */
@@ -504,25 +570,24 @@ dump_context::dump_gimple_stmt_loc (dump_flags_t dump_kind,
dump_flags_t extra_dump_flags,
gimple *gs, int spc)
{
- location_t srcloc = loc.get_location_t ();
- if (dump_file && (dump_kind & pflags))
- {
- dump_loc (dump_kind, dump_file, srcloc);
- print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
- }
+ dump_loc (dump_kind, loc);
+ dump_gimple_stmt (dump_kind, extra_dump_flags, gs, spc);
+}
- if (alt_dump_file && (dump_kind & alt_flags))
- {
- dump_loc (dump_kind, alt_dump_file, srcloc);
- print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
- }
+/* Make an item for the given dump call, equivalent to print_gimple_expr. */
- if (optinfo_enabled_p ())
- {
- optinfo &info = begin_next_optinfo (loc);
- info.handle_dump_file_kind (dump_kind);
- info.add_gimple_stmt (gs, spc, dump_flags | extra_dump_flags);
- }
+static optinfo_item *
+make_item_for_dump_gimple_expr (gimple *stmt, int spc, dump_flags_t dump_flags)
+{
+ dump_flags |= TDF_RHS_ONLY;
+ pretty_printer pp;
+ pp_needs_newline (&pp) = true;
+ pp_gimple_stmt_1 (&pp, stmt, spc, dump_flags);
+
+ optinfo_item *item
+ = new optinfo_item (OPTINFO_ITEM_KIND_GIMPLE, gimple_location (stmt),
+ xstrdup (pp_formatted_text (&pp)));
+ return item;
}
/* Dump gimple statement GS with SPC indentation spaces and
@@ -534,18 +599,18 @@ dump_context::dump_gimple_expr (dump_flags_t dump_kind,
dump_flags_t extra_dump_flags,
gimple *gs, int spc)
{
- if (dump_file && (dump_kind & pflags))
- print_gimple_expr (dump_file, gs, spc, dump_flags | extra_dump_flags);
-
- if (alt_dump_file && (dump_kind & alt_flags))
- print_gimple_expr (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
+ optinfo_item *item
+ = make_item_for_dump_gimple_expr (gs, spc, dump_flags | extra_dump_flags);
+ emit_item (item, dump_kind);
if (optinfo_enabled_p ())
{
optinfo &info = ensure_pending_optinfo ();
info.handle_dump_file_kind (dump_kind);
- info.add_gimple_expr (gs, spc, dump_flags | extra_dump_flags);
+ info.add_item (item);
}
+ else
+ delete item;
}
/* Similar to dump_gimple_expr, except additionally print source location. */
@@ -557,27 +622,29 @@ dump_context::dump_gimple_expr_loc (dump_flags_t dump_kind,
gimple *gs,
int spc)
{
- location_t srcloc = loc.get_location_t ();
- if (dump_file && (dump_kind & pflags))
- {
- dump_loc (dump_kind, dump_file, srcloc);
- print_gimple_expr (dump_file, gs, spc, dump_flags | extra_dump_flags);
- }
+ dump_loc (dump_kind, loc);
+ dump_gimple_expr (dump_kind, extra_dump_flags, gs, spc);
+}
- if (alt_dump_file && (dump_kind & alt_flags))
- {
- dump_loc (dump_kind, alt_dump_file, srcloc);
- print_gimple_expr (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
- }
+/* Make an item for the given dump call, equivalent to print_generic_expr. */
- if (optinfo_enabled_p ())
- {
- optinfo &info = begin_next_optinfo (loc);
- info.handle_dump_file_kind (dump_kind);
- info.add_gimple_expr (gs, spc, dump_flags | extra_dump_flags);
- }
-}
+static optinfo_item *
+make_item_for_dump_generic_expr (tree node, dump_flags_t dump_flags)
+{
+ pretty_printer pp;
+ pp_needs_newline (&pp) = true;
+ pp_translate_identifiers (&pp) = false;
+ dump_generic_node (&pp, node, 0, dump_flags, false);
+ location_t loc = UNKNOWN_LOCATION;
+ if (EXPR_HAS_LOCATION (node))
+ loc = EXPR_LOCATION (node);
+
+ optinfo_item *item
+ = new optinfo_item (OPTINFO_ITEM_KIND_TREE, loc,
+ xstrdup (pp_formatted_text (&pp)));
+ return item;
+}
/* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
DUMP_KIND is enabled. */
@@ -587,18 +654,18 @@ dump_context::dump_generic_expr (dump_flags_t dump_kind,
dump_flags_t extra_dump_flags,
tree t)
{
- if (dump_file && (dump_kind & pflags))
- print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
-
- if (alt_dump_file && (dump_kind & alt_flags))
- print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
+ optinfo_item *item
+ = make_item_for_dump_generic_expr (t, dump_flags | extra_dump_flags);
+ emit_item (item, dump_kind);
if (optinfo_enabled_p ())
{
optinfo &info = ensure_pending_optinfo ();
info.handle_dump_file_kind (dump_kind);
- info.add_tree (t, dump_flags | extra_dump_flags);
+ info.add_item (item);
}
+ else
+ delete item;
}
@@ -611,24 +678,238 @@ dump_context::dump_generic_expr_loc (dump_flags_t dump_kind,
dump_flags_t extra_dump_flags,
tree t)
{
- location_t srcloc = loc.get_location_t ();
- if (dump_file && (dump_kind & pflags))
- {
- dump_loc (dump_kind, dump_file, srcloc);
- print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
- }
+ dump_loc (dump_kind, loc);
+ dump_generic_expr (dump_kind, extra_dump_flags, t);
+}
- if (alt_dump_file && (dump_kind & alt_flags))
+/* A subclass of pretty_printer for implementing dump_context::dump_printf_va.
+ In particular, the formatted chunks are captured as optinfo_item instances,
+ thus retaining metadata about the entities being dumped (e.g. source
+ locations), rather than just as plain text. */
+
+class dump_pretty_printer : public pretty_printer
+{
+public:
+ dump_pretty_printer (dump_context *context, dump_flags_t dump_kind);
+
+ void emit_items (optinfo *dest);
+
+private:
+ /* Information on an optinfo_item that was generated during phase 2 of
+ formatting. */
+ struct stashed_item
+ {
+ stashed_item (const char **buffer_ptr_, optinfo_item *item_)
+ : buffer_ptr (buffer_ptr_), item (item_) {}
+ const char **buffer_ptr;
+ optinfo_item *item;
+ };
+
+ static bool format_decoder_cb (pretty_printer *pp, text_info *text,
+ const char *spec, int /*precision*/,
+ bool /*wide*/, bool /*set_locus*/,
+ bool /*verbose*/, bool */*quoted*/,
+ const char **buffer_ptr);
+
+ bool decode_format (text_info *text, const char *spec,
+ const char **buffer_ptr);
+
+ void stash_item (const char **buffer_ptr, optinfo_item *item);
+
+ void emit_any_pending_textual_chunks (optinfo *dest);
+
+ void emit_item (optinfo_item *item, optinfo *dest);
+
+ dump_context *m_context;
+ dump_flags_t m_dump_kind;
+ auto_vec<stashed_item> m_stashed_items;
+};
+
+/* dump_pretty_printer's ctor. */
+
+dump_pretty_printer::dump_pretty_printer (dump_context *context,
+ dump_flags_t dump_kind)
+: pretty_printer (), m_context (context), m_dump_kind (dump_kind),
+ m_stashed_items ()
+{
+ pp_format_decoder (this) = format_decoder_cb;
+}
+
+/* Phase 3 of formatting; compare with pp_output_formatted_text.
+
+ Emit optinfo_item instances for the various formatted chunks from phases
+ 1 and 2 (i.e. pp_format).
+
+ Some chunks may already have had their items built (during decode_format).
+ These chunks have been stashed into m_stashed_items; we emit them here.
+
+ For all other purely textual chunks, they are printed into
+ buffer->formatted_obstack, and then emitted as a textual optinfo_item.
+ This consolidates multiple adjacent text chunks into a single text
+ optinfo_item. */
+
+void
+dump_pretty_printer::emit_items (optinfo *dest)
+{
+ output_buffer *buffer = pp_buffer (this);
+ struct chunk_info *chunk_array = buffer->cur_chunk_array;
+ const char **args = chunk_array->args;
+
+ gcc_assert (buffer->obstack == &buffer->formatted_obstack);
+ gcc_assert (buffer->line_length == 0);
+
+ unsigned stashed_item_idx = 0;
+ for (unsigned chunk = 0; args[chunk]; chunk++)
{
- dump_loc (dump_kind, alt_dump_file, srcloc);
- print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
+ if (stashed_item_idx < m_stashed_items.length ()
+ && args[chunk] == *m_stashed_items[stashed_item_idx].buffer_ptr)
+ {
+ emit_any_pending_textual_chunks (dest);
+ /* This chunk has a stashed item: use it. */
+ emit_item (m_stashed_items[stashed_item_idx++].item, dest);
+ }
+ else
+ /* This chunk is purely textual. Print it (to
+ buffer->formatted_obstack), so that we can consolidate adjacent
+ chunks into one textual optinfo_item. */
+ pp_string (this, args[chunk]);
}
- if (optinfo_enabled_p ())
+ emit_any_pending_textual_chunks (dest);
+
+ /* Ensure that we consumed all of stashed_items. */
+ gcc_assert (stashed_item_idx == m_stashed_items.length ());
+
+ /* Deallocate the chunk structure and everything after it (i.e. the
+ associated series of formatted strings). */
+ buffer->cur_chunk_array = chunk_array->prev;
+ obstack_free (&buffer->chunk_obstack, chunk_array);
+}
+
+/* Subroutine of dump_pretty_printer::emit_items
+ for consolidating multiple adjacent pure-text chunks into single
+ optinfo_items (in phase 3). */
+
+void
+dump_pretty_printer::emit_any_pending_textual_chunks (optinfo *dest)
+{
+ gcc_assert (buffer->obstack == &buffer->formatted_obstack);
+
+ /* Don't emit an item if the pending text is empty. */
+ if (output_buffer_last_position_in_text (buffer) == NULL)
+ return;
+
+ char *formatted_text = xstrdup (pp_formatted_text (this));
+ optinfo_item *item
+ = new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
+ formatted_text);
+ emit_item (item, dest);
+
+ /* Clear the pending text by unwinding formatted_text back to the start
+ of the buffer (without deallocating). */
+ obstack_free (&buffer->formatted_obstack,
+ buffer->formatted_obstack.object_base);
+}
+
+/* Emit ITEM and take ownership of it. If DEST is non-NULL, add ITEM
+ to DEST; otherwise delete ITEM. */
+
+void
+dump_pretty_printer::emit_item (optinfo_item *item, optinfo *dest)
+{
+ m_context->emit_item (item, m_dump_kind);
+ if (dest)
+ dest->add_item (item);
+ else
+ delete item;
+}
+
+/* Record that ITEM (generated in phase 2 of formatting) is to be used for
+ the chunk at BUFFER_PTR in phase 3 (by emit_items). */
+
+void
+dump_pretty_printer::stash_item (const char **buffer_ptr, optinfo_item *item)
+{
+ gcc_assert (buffer_ptr);
+ gcc_assert (item);
+
+ m_stashed_items.safe_push (stashed_item (buffer_ptr, item));
+}
+
+/* pp_format_decoder callback for dump_pretty_printer, and thus for
+ dump_printf and dump_printf_loc.
+
+ A wrapper around decode_format, for type-safety. */
+
+bool
+dump_pretty_printer::format_decoder_cb (pretty_printer *pp, text_info *text,
+ const char *spec, int /*precision*/,
+ bool /*wide*/, bool /*set_locus*/,
+ bool /*verbose*/, bool */*quoted*/,
+ const char **buffer_ptr)
+{
+ dump_pretty_printer *opp = static_cast <dump_pretty_printer *> (pp);
+ return opp->decode_format (text, spec, buffer_ptr);
+}
+
+/* Format decoder for dump_pretty_printer, and thus for dump_printf and
+ dump_printf_loc.
+
+ Supported format codes (in addition to the standard pretty_printer ones)
+ are:
+
+ %E: gimple *:
+ Equivalent to: dump_gimple_expr (MSG_*, TDF_SLIM, stmt, 0)
+ %G: gimple *:
+ Equivalent to: dump_gimple_stmt (MSG_*, TDF_SLIM, stmt, 0)
+ %T: tree:
+ Equivalent to: dump_generic_expr (MSG_*, arg, TDF_SLIM).
+
+ FIXME: add symtab_node?
+
+ These format codes build optinfo_item instances, thus capturing metadata
+ about the arguments being dumped, as well as the textual output. */
+
+bool
+dump_pretty_printer::decode_format (text_info *text, const char *spec,
+ const char **buffer_ptr)
+{
+ /* Various format codes that imply making an optinfo_item and stashed it
+ for later use (to capture metadata, rather than plain text). */
+ switch (*spec)
{
- optinfo &info = begin_next_optinfo (loc);
- info.handle_dump_file_kind (dump_kind);
- info.add_tree (t, dump_flags | extra_dump_flags);
+ case 'E':
+ {
+ gimple *stmt = va_arg (*text->args_ptr, gimple *);
+
+ /* Make an item for the stmt, and stash it. */
+ optinfo_item *item = make_item_for_dump_gimple_expr (stmt, 0, TDF_SLIM);
+ stash_item (buffer_ptr, item);
+ return true;
+ }
+
+ case 'G':
+ {
+ gimple *stmt = va_arg (*text->args_ptr, gimple *);
+
+ /* Make an item for the stmt, and stash it. */
+ optinfo_item *item = make_item_for_dump_gimple_stmt (stmt, 0, TDF_SLIM);
+ stash_item (buffer_ptr, item);
+ return true;
+ }
+
+ case 'T':
+ {
+ tree t = va_arg (*text->args_ptr, tree);
+
+ /* Make an item for the tree, and stash it. */
+ optinfo_item *item = make_item_for_dump_generic_expr (t, TDF_SLIM);
+ stash_item (buffer_ptr, item);
+ return true;
+ }
+
+ default:
+ return false;
}
}
@@ -636,32 +917,27 @@ dump_context::dump_generic_expr_loc (dump_flags_t dump_kind,
void
dump_context::dump_printf_va (dump_flags_t dump_kind, const char *format,
- va_list ap)
+ va_list *ap)
{
- if (dump_file && (dump_kind & pflags))
- {
- va_list aq;
- va_copy (aq, ap);
- vfprintf (dump_file, format, aq);
- va_end (aq);
- }
+ dump_pretty_printer pp (this, dump_kind);
- if (alt_dump_file && (dump_kind & alt_flags))
- {
- va_list aq;
- va_copy (aq, ap);
- vfprintf (alt_dump_file, format, aq);
- va_end (aq);
- }
+ text_info text;
+ text.err_no = errno;
+ text.args_ptr = ap;
+ text.format_spec = format;
+
+ /* Phases 1 and 2, using pp_format. */
+ pp_format (&pp, &text);
+ /* Phase 3. */
if (optinfo_enabled_p ())
{
optinfo &info = ensure_pending_optinfo ();
- va_list aq;
- va_copy (aq, ap);
- info.add_printf_va (format, aq);
- va_end (aq);
+ info.handle_dump_file_kind (dump_kind);
+ pp.emit_items (&info);
}
+ else
+ pp.emit_items (NULL);
}
/* Similar to dump_printf, except source location is also printed, and
@@ -670,37 +946,39 @@ dump_context::dump_printf_va (dump_flags_t dump_kind, const char *format,
void
dump_context::dump_printf_loc_va (dump_flags_t dump_kind,
const dump_location_t &loc,
- const char *format, va_list ap)
+ const char *format, va_list *ap)
{
- location_t srcloc = loc.get_location_t ();
+ dump_loc (dump_kind, loc);
+ dump_printf_va (dump_kind, format, ap);
+}
- if (dump_file && (dump_kind & pflags))
- {
- dump_loc (dump_kind, dump_file, srcloc);
- va_list aq;
- va_copy (aq, ap);
- vfprintf (dump_file, format, aq);
- va_end (aq);
- }
+/* Make an item for the given dump call, equivalent to print_dec. */
- if (alt_dump_file && (dump_kind & alt_flags))
- {
- dump_loc (dump_kind, alt_dump_file, srcloc);
- va_list aq;
- va_copy (aq, ap);
- vfprintf (alt_dump_file, format, aq);
- va_end (aq);
- }
+template<unsigned int N, typename C>
+static optinfo_item *
+make_item_for_dump_dec (const poly_int<N, C> &value)
+{
+ STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
+ signop sgn = poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED;
- if (optinfo_enabled_p ())
+ pretty_printer pp;
+
+ if (value.is_constant ())
+ pp_wide_int (&pp, value.coeffs[0], sgn);
+ else
{
- optinfo &info = begin_next_optinfo (loc);
- info.handle_dump_file_kind (dump_kind);
- va_list aq;
- va_copy (aq, ap);
- info.add_printf_va (format, aq);
- va_end (aq);
+ pp_character (&pp, '[');
+ for (unsigned int i = 0; i < N; ++i)
+ {
+ pp_wide_int (&pp, value.coeffs[i], sgn);
+ pp_character (&pp, i == N - 1 ? ']' : ',');
+ }
}
+
+ optinfo_item *item
+ = new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
+ xstrdup (pp_formatted_text (&pp)));
+ return item;
}
/* Output VALUE in decimal to appropriate dump streams. */
@@ -709,20 +987,29 @@ template<unsigned int N, typename C>
void
dump_context::dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value)
{
- STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
- signop sgn = poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED;
- if (dump_file && (dump_kind & pflags))
- print_dec (value, dump_file, sgn);
-
- if (alt_dump_file && (dump_kind & alt_flags))
- print_dec (value, alt_dump_file, sgn);
+ optinfo_item *item = make_item_for_dump_dec (value);
+ emit_item (item, dump_kind);
if (optinfo_enabled_p ())
{
optinfo &info = ensure_pending_optinfo ();
info.handle_dump_file_kind (dump_kind);
- info.add_poly_int<N,C> (value);
+ info.add_item (item);
}
+ else
+ delete item;
+}
+
+/* Make an item for the given dump call. */
+
+static optinfo_item *
+make_item_for_dump_symtab_node (symtab_node *node)
+{
+ location_t loc = DECL_SOURCE_LOCATION (node->decl);
+ optinfo_item *item
+ = new optinfo_item (OPTINFO_ITEM_KIND_SYMTAB_NODE, loc,
+ xstrdup (node->dump_name ()));
+ return item;
}
/* Output the name of NODE on appropriate dump streams. */
@@ -730,18 +1017,17 @@ dump_context::dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value)
void
dump_context::dump_symtab_node (dump_flags_t dump_kind, symtab_node *node)
{
- if (dump_file && (dump_kind & pflags))
- fprintf (dump_file, "%s", node->dump_name ());
-
- if (alt_dump_file && (dump_kind & alt_flags))
- fprintf (alt_dump_file, "%s", node->dump_name ());
+ optinfo_item *item = make_item_for_dump_symtab_node (node);
+ emit_item (item, dump_kind);
if (optinfo_enabled_p ())
{
optinfo &info = ensure_pending_optinfo ();
info.handle_dump_file_kind (dump_kind);
- info.add_symtab_node (node);
+ info.add_item (item);
}
+ else
+ delete item;
}
/* Get the current dump scope-nesting depth.
@@ -762,28 +1048,31 @@ dump_context::get_scope_depth () const
void
dump_context::begin_scope (const char *name, const dump_location_t &loc)
{
- /* Specialcase, to avoid going through dump_printf_loc,
- so that we can create a optinfo of kind OPTINFO_KIND_SCOPE. */
+ if (dump_file && (MSG_NOTE & pflags))
+ ::dump_loc (MSG_NOTE, dump_file, loc.get_location_t ());
- if (dump_file)
- {
- dump_loc (MSG_NOTE, dump_file, loc.get_location_t ());
- fprintf (dump_file, "=== %s ===\n", name);
- }
+ if (alt_dump_file && (MSG_NOTE & alt_flags))
+ ::dump_loc (MSG_NOTE, alt_dump_file, loc.get_location_t ());
- if (alt_dump_file)
- {
- dump_loc (MSG_NOTE, alt_dump_file, loc.get_location_t ());
- fprintf (alt_dump_file, "=== %s ===\n", name);
- }
+ /* Support for temp_dump_context in selftests. */
+ if (m_test_pp && (MSG_NOTE & m_test_pp_flags))
+ ::dump_loc (MSG_NOTE, m_test_pp, loc.get_location_t ());
+
+ pretty_printer pp;
+ pp_printf (&pp, "=== %s ===\n", name);
+ optinfo_item *item
+ = new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
+ xstrdup (pp_formatted_text (&pp)));
+ emit_item (item, MSG_NOTE);
if (optinfo_enabled_p ())
{
- end_any_optinfo ();
- optinfo info (loc, OPTINFO_KIND_SCOPE, current_pass);
- info.add_printf ("=== %s ===", name);
- info.emit ();
+ optinfo &info = begin_next_optinfo (loc);
+ info.m_kind = OPTINFO_KIND_SCOPE;
+ info.add_item (item);
}
+ else
+ delete item;
m_scope_depth++;
}
@@ -833,6 +1122,23 @@ dump_context::end_any_optinfo ()
m_pending = NULL;
}
+/* Emit ITEM to all item destinations (those that don't require
+ consolidation into optinfo instances). */
+
+void
+dump_context::emit_item (optinfo_item *item, dump_flags_t dump_kind)
+{
+ if (dump_file && (dump_kind & pflags))
+ fprintf (dump_file, "%s", item->get_text ());
+
+ if (alt_dump_file && (dump_kind & alt_flags))
+ fprintf (alt_dump_file, "%s", item->get_text ());
+
+ /* Support for temp_dump_context in selftests. */
+ if (m_test_pp && (dump_kind & m_test_pp_flags))
+ pp_string (m_test_pp, item->get_text ());
+}
+
/* The current singleton dump_context, and its default. */
dump_context *dump_context::s_current = &dump_context::s_default;
@@ -910,7 +1216,7 @@ dump_printf (dump_flags_t dump_kind, const char *format, ...)
{
va_list ap;
va_start (ap, format);
- dump_context::get ().dump_printf_va (dump_kind, format, ap);
+ dump_context::get ().dump_printf_va (dump_kind, format, &ap);
va_end (ap);
}
@@ -923,7 +1229,7 @@ dump_printf_loc (dump_flags_t dump_kind, const dump_location_t &loc,
{
va_list ap;
va_start (ap, format);
- dump_context::get ().dump_printf_loc_va (dump_kind, loc, format, ap);
+ dump_context::get ().dump_printf_loc_va (dump_kind, loc, format, &ap);
va_end (ap);
}
@@ -1567,12 +1873,18 @@ enable_rtl_dump_file (void)
/* temp_dump_context's ctor. Temporarily override the dump_context
(to forcibly enable optinfo-generation). */
-temp_dump_context::temp_dump_context (bool forcibly_enable_optinfo)
+temp_dump_context::temp_dump_context (bool forcibly_enable_optinfo,
+ dump_flags_t test_pp_flags)
+
: m_context (),
m_saved (&dump_context ().get ())
{
dump_context::s_current = &m_context;
m_context.m_forcibly_enable_optinfo = forcibly_enable_optinfo;
+ m_context.m_test_pp = &m_pp;
+ m_context.m_test_pp_flags = test_pp_flags;
+
+ dump_context::get ().refresh_dumps_are_enabled ();
}
/* temp_dump_context's dtor. Restore the saved dump_context. */
@@ -1580,6 +1892,16 @@ temp_dump_context::temp_dump_context (bool forcibly_enable_optinfo)
temp_dump_context::~temp_dump_context ()
{
dump_context::s_current = m_saved;
+
+ dump_context::get ().refresh_dumps_are_enabled ();
+}
+
+/* 0-terminate the text dumped so far, and return it. */
+
+const char *
+temp_dump_context::get_dumped_text ()
+{
+ return pp_formatted_text (&m_pp);
}
namespace selftest {
@@ -1618,6 +1940,29 @@ test_impl_location ()
#endif
}
+/* Verify that the text dumped so far in CONTEXT equals
+ EXPECTED_TEXT, using LOC for the location of any failure.
+ As a side-effect, the internal buffer is 0-terminated. */
+
+static void
+verify_dumped_text (const location &loc,
+ temp_dump_context *context,
+ const char *expected_text)
+{
+ gcc_assert (context);
+ ASSERT_STREQ_AT (loc, context->get_dumped_text (),
+ expected_text);
+}
+
+/* Verify that the text dumped so far in CONTEXT equals
+ EXPECTED_TEXT.
+ As a side-effect, the internal buffer is 0-terminated. */
+
+#define ASSERT_DUMPED_TEXT_EQ(CONTEXT, EXPECTED_TEXT) \
+ SELFTEST_BEGIN_STMT \
+ verify_dumped_text (SELFTEST_LOCATION, &(CONTEXT), (EXPECTED_TEXT)); \
+ SELFTEST_END_STMT
+
/* Verify that ITEM has the expected values. */
static void
@@ -1668,116 +2013,284 @@ test_capture_of_dump_calls (const line_table_case &case_)
linemap_line_start (line_table, 5, 100);
linemap_add (line_table, LC_LEAVE, false, NULL, 0);
location_t where = linemap_position_for_column (line_table, 10);
+ if (where > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
dump_location_t loc = dump_location_t::from_location_t (where);
- /* Test of dump_printf. */
- {
- temp_dump_context tmp (true);
- dump_printf (MSG_NOTE, "int: %i str: %s", 42, "foo");
-
- optinfo *info = tmp.get_pending_optinfo ();
- ASSERT_TRUE (info != NULL);
- ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
- ASSERT_EQ (info->num_items (), 1);
- ASSERT_IS_TEXT (info->get_item (0), "int: 42 str: foo");
- }
-
- /* Tree, via dump_generic_expr. */
- {
- temp_dump_context tmp (true);
- dump_printf_loc (MSG_NOTE, loc, "test of tree: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, integer_zero_node);
-
- optinfo *info = tmp.get_pending_optinfo ();
- ASSERT_TRUE (info != NULL);
- ASSERT_EQ (info->get_location_t (), where);
- ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
- ASSERT_EQ (info->num_items (), 2);
- ASSERT_IS_TEXT (info->get_item (0), "test of tree: ");
- ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
- }
-
- /* Tree, via dump_generic_expr_loc. */
- {
- temp_dump_context tmp (true);
- dump_generic_expr_loc (MSG_NOTE, loc, TDF_SLIM, integer_one_node);
-
- optinfo *info = tmp.get_pending_optinfo ();
- ASSERT_TRUE (info != NULL);
- ASSERT_EQ (info->get_location_t (), where);
- ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
- ASSERT_EQ (info->num_items (), 1);
- ASSERT_IS_TREE (info->get_item (0), UNKNOWN_LOCATION, "1");
- }
-
- /* Gimple. */
- {
- greturn *stmt = gimple_build_return (NULL);
- gimple_set_location (stmt, where);
-
- /* dump_gimple_stmt_loc. */
- {
- temp_dump_context tmp (true);
- dump_gimple_stmt_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
-
- optinfo *info = tmp.get_pending_optinfo ();
- ASSERT_TRUE (info != NULL);
- ASSERT_EQ (info->num_items (), 1);
- ASSERT_IS_GIMPLE (info->get_item (0), where, "return;\n");
- }
-
- /* dump_gimple_stmt. */
- {
- temp_dump_context tmp (true);
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 2);
-
- optinfo *info = tmp.get_pending_optinfo ();
- ASSERT_TRUE (info != NULL);
- ASSERT_EQ (info->num_items (), 1);
- ASSERT_IS_GIMPLE (info->get_item (0), where, "return;\n");
- }
+ gimple *stmt = gimple_build_return (NULL);
+ gimple_set_location (stmt, where);
- /* dump_gimple_expr_loc. */
+ tree test_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+ get_identifier ("test_decl"),
+ integer_type_node);
+ /* Run all tests twice, with and then without optinfo enabled, to ensure
+ that immediate destinations vs optinfo-based destinations both
+ work, independently of each other, with no leaks. */
+ for (int i = 0 ; i < 2; i++)
{
- temp_dump_context tmp (true);
- dump_gimple_expr_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
+ bool with_optinfo = (i == 0);
+
+ /* Test of dump_printf. */
+ {
+ temp_dump_context tmp (with_optinfo, MSG_ALL);
+ dump_printf (MSG_NOTE, "int: %i str: %s", 42, "foo");
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "int: 42 str: foo");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->num_items (), 1);
+ ASSERT_IS_TEXT (info->get_item (0), "int: 42 str: foo");
+ }
+ }
+
+ /* Test of dump_printf with %T. */
+ {
+ temp_dump_context tmp (with_optinfo, MSG_ALL);
+ dump_printf (MSG_NOTE, "tree: %T", integer_zero_node);
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "tree: 0");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->num_items (), 2);
+ ASSERT_IS_TEXT (info->get_item (0), "tree: ");
+ ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
+ }
+ }
+
+ /* Test of dump_printf with %E. */
+ {
+ temp_dump_context tmp (with_optinfo, MSG_ALL);
+ dump_printf (MSG_NOTE, "gimple: %E", stmt);
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "gimple: return;");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->num_items (), 2);
+ ASSERT_IS_TEXT (info->get_item (0), "gimple: ");
+ ASSERT_IS_GIMPLE (info->get_item (1), where, "return;");
+ }
+ }
+
+ /* Test of dump_printf with %G. */
+ {
+ temp_dump_context tmp (with_optinfo, MSG_ALL);
+ dump_printf (MSG_NOTE, "gimple: %G", stmt);
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "gimple: return;\n");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->num_items (), 2);
+ ASSERT_IS_TEXT (info->get_item (0), "gimple: ");
+ ASSERT_IS_GIMPLE (info->get_item (1), where, "return;\n");
+ }
+ }
+
+ /* dump_print_loc with multiple format codes. This tests various
+ things:
+ - intermingling of text, format codes handled by the base
+ pretty_printer, and dump-specific format codes
+ - multiple dump-specific format codes: some consecutive, others
+ separated by text, trailing text after the final one. */
+ {
+ temp_dump_context tmp (with_optinfo, MSG_ALL);
+ dump_printf_loc (MSG_NOTE, loc, "before %T and %T"
+ " %i consecutive %E%E after\n",
+ integer_zero_node, test_decl, 42, stmt, stmt);
+
+ ASSERT_DUMPED_TEXT_EQ (tmp,
+ "test.txt:5:10: note: before 0 and test_decl"
+ " 42 consecutive return;return; after\n");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->num_items (), 8);
+ ASSERT_IS_TEXT (info->get_item (0), "before ");
+ ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
+ ASSERT_IS_TEXT (info->get_item (2), " and ");
+ ASSERT_IS_TREE (info->get_item (3), UNKNOWN_LOCATION, "test_decl");
+ ASSERT_IS_TEXT (info->get_item (4), " 42 consecutive ");
+ ASSERT_IS_GIMPLE (info->get_item (5), where, "return;");
+ ASSERT_IS_GIMPLE (info->get_item (6), where, "return;");
+ ASSERT_IS_TEXT (info->get_item (7), " after\n");
+ }
+ }
+
+ /* Tree, via dump_generic_expr. */
+ {
+ temp_dump_context tmp (with_optinfo, MSG_ALL);
+ dump_printf_loc (MSG_NOTE, loc, "test of tree: ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM, integer_zero_node);
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: test of tree: 0");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->get_location_t (), where);
+ ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->num_items (), 2);
+ ASSERT_IS_TEXT (info->get_item (0), "test of tree: ");
+ ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
+ }
+ }
+
+ /* Tree, via dump_generic_expr_loc. */
+ {
+ temp_dump_context tmp (with_optinfo, MSG_ALL);
+ dump_generic_expr_loc (MSG_NOTE, loc, TDF_SLIM, integer_one_node);
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: 1");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->get_location_t (), where);
+ ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->num_items (), 1);
+ ASSERT_IS_TREE (info->get_item (0), UNKNOWN_LOCATION, "1");
+ }
+ }
+
+ /* Gimple. */
+ {
+ /* dump_gimple_stmt_loc. */
+ {
+ temp_dump_context tmp (with_optinfo, MSG_ALL);
+ dump_gimple_stmt_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: return;\n");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->num_items (), 1);
+ ASSERT_IS_GIMPLE (info->get_item (0), where, "return;\n");
+ }
+ }
- optinfo *info = tmp.get_pending_optinfo ();
- ASSERT_TRUE (info != NULL);
- ASSERT_EQ (info->num_items (), 1);
- ASSERT_IS_GIMPLE (info->get_item (0), where, "return;");
- }
+ /* dump_gimple_stmt. */
+ {
+ temp_dump_context tmp (with_optinfo, MSG_ALL);
+ dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 2);
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "return;\n");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->num_items (), 1);
+ ASSERT_IS_GIMPLE (info->get_item (0), where, "return;\n");
+ }
+ }
- /* dump_gimple_expr. */
- {
- temp_dump_context tmp (true);
- dump_gimple_expr (MSG_NOTE, TDF_SLIM, stmt, 2);
+ /* dump_gimple_expr_loc. */
+ {
+ temp_dump_context tmp (with_optinfo, MSG_ALL);
+ dump_gimple_expr_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: return;");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->num_items (), 1);
+ ASSERT_IS_GIMPLE (info->get_item (0), where, "return;");
+ }
+ }
- optinfo *info = tmp.get_pending_optinfo ();
- ASSERT_TRUE (info != NULL);
- ASSERT_EQ (info->num_items (), 1);
- ASSERT_IS_GIMPLE (info->get_item (0), where, "return;");
+ /* dump_gimple_expr. */
+ {
+ temp_dump_context tmp (with_optinfo, MSG_ALL);
+ dump_gimple_expr (MSG_NOTE, TDF_SLIM, stmt, 2);
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "return;");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->num_items (), 1);
+ ASSERT_IS_GIMPLE (info->get_item (0), where, "return;");
+ }
+ }
+ }
+
+ /* poly_int. */
+ {
+ temp_dump_context tmp (with_optinfo, MSG_ALL);
+ dump_dec (MSG_NOTE, poly_int64 (42));
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "42");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->num_items (), 1);
+ ASSERT_IS_TEXT (info->get_item (0), "42");
+ }
+ }
+
+ /* scopes. */
+ {
+ temp_dump_context tmp (with_optinfo, MSG_ALL);
+ dump_printf_loc (MSG_NOTE, stmt, "msg 1\n");
+ {
+ AUTO_DUMP_SCOPE ("outer scope", stmt);
+ dump_printf_loc (MSG_NOTE, stmt, "msg 2\n");
+ {
+ AUTO_DUMP_SCOPE ("middle scope", stmt);
+ dump_printf_loc (MSG_NOTE, stmt, "msg 3\n");
+ {
+ AUTO_DUMP_SCOPE ("inner scope", stmt);
+ dump_printf_loc (MSG_NOTE, stmt, "msg 4\n");
+ }
+ dump_printf_loc (MSG_NOTE, stmt, "msg 5\n");
+ }
+ dump_printf_loc (MSG_NOTE, stmt, "msg 6\n");
+ }
+ dump_printf_loc (MSG_NOTE, stmt, "msg 7\n");
+
+ ASSERT_DUMPED_TEXT_EQ (tmp,
+ "test.txt:5:10: note: msg 1\n"
+ "test.txt:5:10: note: === outer scope ===\n"
+ "test.txt:5:10: note: msg 2\n"
+ "test.txt:5:10: note: === middle scope ===\n"
+ "test.txt:5:10: note: msg 3\n"
+ "test.txt:5:10: note: === inner scope ===\n"
+ "test.txt:5:10: note: msg 4\n"
+ "test.txt:5:10: note: msg 5\n"
+ "test.txt:5:10: note: msg 6\n"
+ "test.txt:5:10: note: msg 7\n");
+ if (with_optinfo)
+ {
+ optinfo *info = tmp.get_pending_optinfo ();
+ ASSERT_TRUE (info != NULL);
+ ASSERT_EQ (info->num_items (), 1);
+ ASSERT_IS_TEXT (info->get_item (0), "msg 7\n");
+ }
+ }
}
- }
-
- /* poly_int. */
- {
- temp_dump_context tmp (true);
- dump_dec (MSG_NOTE, poly_int64 (42));
-
- optinfo *info = tmp.get_pending_optinfo ();
- ASSERT_TRUE (info != NULL);
- ASSERT_EQ (info->num_items (), 1);
- ASSERT_IS_TEXT (info->get_item (0), "42");
- }
/* Verify that MSG_* affects optinfo->get_kind (); we tested MSG_NOTE
above. */
{
/* MSG_OPTIMIZED_LOCATIONS. */
{
- temp_dump_context tmp (true);
+ temp_dump_context tmp (true, MSG_ALL);
dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, "test");
ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
OPTINFO_KIND_SUCCESS);
@@ -1785,12 +2298,35 @@ test_capture_of_dump_calls (const line_table_case &case_)
/* MSG_MISSED_OPTIMIZATION. */
{
- temp_dump_context tmp (true);
+ temp_dump_context tmp (true, MSG_ALL);
dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, "test");
ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
OPTINFO_KIND_FAILURE);
}
}
+
+ /* Verify that MSG_* affect AUTO_DUMP_SCOPE and the dump calls. */
+ {
+ temp_dump_context tmp (false, MSG_OPTIMIZED_LOCATIONS);
+ dump_printf_loc (MSG_NOTE, stmt, "msg 1\n");
+ {
+ AUTO_DUMP_SCOPE ("outer scope", stmt);
+ dump_printf_loc (MSG_NOTE, stmt, "msg 2\n");
+ {
+ AUTO_DUMP_SCOPE ("middle scope", stmt);
+ dump_printf_loc (MSG_NOTE, stmt, "msg 3\n");
+ {
+ AUTO_DUMP_SCOPE ("inner scope", stmt);
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, stmt, "msg 4\n");
+ }
+ dump_printf_loc (MSG_NOTE, stmt, "msg 5\n");
+ }
+ dump_printf_loc (MSG_NOTE, stmt, "msg 6\n");
+ }
+ dump_printf_loc (MSG_NOTE, stmt, "msg 7\n");
+
+ ASSERT_DUMPED_TEXT_EQ (tmp, "test.txt:5:10: note: msg 4\n");
+ }
}
/* Run all of the selftests within this file. */
diff --git a/gcc/dumpfile.h b/gcc/dumpfile.h
index 1dbe3b8..671b7b9 100644
--- a/gcc/dumpfile.h
+++ b/gcc/dumpfile.h
@@ -23,6 +23,19 @@ along with GCC; see the file COPYING3. If not see
#include "profile-count.h"
+/* An attribute for annotating formatting printing functions that use
+ the dumpfile/optinfo formatting codes. These are the pretty_printer
+ format codes (see pretty-print.c), with additional codes for middle-end
+ specific entities (see dumpfile.c). */
+
+#if GCC_VERSION >= 9000
+#define ATTRIBUTE_GCC_DUMP_PRINTF(m, n) \
+ __attribute__ ((__format__ (__gcc_dump_printf__, m ,n))) \
+ ATTRIBUTE_NONNULL(m)
+#else
+#define ATTRIBUTE_GCC_DUMP_PRINTF(m, n) ATTRIBUTE_NONNULL(m)
+#endif
+
/* Different tree dump places. When you add new tree dump places,
extend the DUMP_FILES array in dumpfile.c. */
enum tree_dump_index
@@ -285,10 +298,10 @@ class dump_user_location_t
dump_user_location_t () : m_count (), m_loc (UNKNOWN_LOCATION) {}
/* Construct from a gimple statement (using its location and hotness). */
- dump_user_location_t (gimple *stmt);
+ dump_user_location_t (const gimple *stmt);
/* Construct from an RTL instruction (using its location and hotness). */
- dump_user_location_t (rtx_insn *insn);
+ dump_user_location_t (const rtx_insn *insn);
/* Construct from a location_t. This one is deprecated (since it doesn't
capture hotness information); it thus needs to be spelled out. */
@@ -363,7 +376,7 @@ class dump_location_t
}
/* Construct from a gimple statement (using its location and hotness). */
- dump_location_t (gimple *stmt,
+ dump_location_t (const gimple *stmt,
const dump_impl_location_t &impl_location
= dump_impl_location_t ())
: m_user_location (dump_user_location_t (stmt)),
@@ -372,7 +385,7 @@ class dump_location_t
}
/* Construct from an RTL instruction (using its location and hotness). */
- dump_location_t (rtx_insn *insn,
+ dump_location_t (const rtx_insn *insn,
const dump_impl_location_t &impl_location
= dump_impl_location_t ())
: m_user_location (dump_user_location_t (insn)),
@@ -442,19 +455,27 @@ dump_enabled_p (void)
}
/* The following API calls (which *don't* take a "FILE *")
- write the output to zero or more locations:
- (a) the active dump_file, if any
- (b) the -fopt-info destination, if any
- (c) to the "optinfo" destinations, if any:
- (c.1) as optimization records
-
- dump_* (MSG_*) --> dumpfile.c --+--> (a) dump_file
- |
- +--> (b) alt_dump_file
- |
- `--> (c) optinfo
- `---> optinfo destinations
- (c.1) optimization records
+ write the output to zero or more locations.
+
+ Some destinations are written to immediately as dump_* calls
+ are made; for others, the output is consolidated into an "optinfo"
+ instance (with its own metadata), and only emitted once the optinfo
+ is complete.
+
+ The destinations are:
+
+ (a) the "immediate" destinations:
+ (a.1) the active dump_file, if any
+ (a.2) the -fopt-info destination, if any
+ (b) the "optinfo" destinations, if any:
+ (b.1) as optimization records
+
+ dump_* (MSG_*) --> dumpfile.c --> items --> (a.1) dump_file
+ | `-> (a.2) alt_dump_file
+ |
+ `--> (b) optinfo
+ `---> optinfo destinations
+ (b.1) optimization records
For optinfos, the dump_*_loc mark the beginning of an optinfo
instance: all subsequent dump_* calls are consolidated into
@@ -468,9 +489,12 @@ dump_enabled_p (void)
to minimize the work done for the common case where dumps
are disabled. */
-extern void dump_printf (dump_flags_t, const char *, ...) ATTRIBUTE_PRINTF_2;
+extern void dump_printf (dump_flags_t, const char *, ...)
+ ATTRIBUTE_GCC_DUMP_PRINTF (2, 3);
+
extern void dump_printf_loc (dump_flags_t, const dump_location_t &,
- const char *, ...) ATTRIBUTE_PRINTF_3;
+ const char *, ...)
+ ATTRIBUTE_GCC_DUMP_PRINTF (3, 0);
extern void dump_function (int phase, tree fn);
extern void dump_basic_block (dump_flags_t, basic_block, int);
extern void dump_generic_expr_loc (dump_flags_t, const dump_location_t &,
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 208f2e9..55fcb7b 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -102,6 +102,7 @@ static void dwarf2out_source_line (unsigned int, unsigned int, const char *,
static rtx_insn *last_var_location_insn;
static rtx_insn *cached_next_real_insn;
static void dwarf2out_decl (tree);
+static bool is_redundant_typedef (const_tree);
#ifndef XCOFF_DEBUGGING_INFO
#define XCOFF_DEBUGGING_INFO 0
@@ -297,6 +298,10 @@ static unsigned int rnglist_idx;
#define FUNC_BEGIN_LABEL "LFB"
#endif
+#ifndef FUNC_SECOND_SECT_LABEL
+#define FUNC_SECOND_SECT_LABEL "LFSB"
+#endif
+
#ifndef FUNC_END_LABEL
#define FUNC_END_LABEL "LFE"
#endif
@@ -1212,21 +1217,24 @@ static void set_cur_line_info_table (section *);
void
dwarf2out_switch_text_section (void)
{
+ char label[MAX_ARTIFICIAL_LABEL_BYTES];
section *sect;
dw_fde_ref fde = cfun->fde;
gcc_assert (cfun && fde && fde->dw_fde_second_begin == NULL);
+ ASM_GENERATE_INTERNAL_LABEL (label, FUNC_SECOND_SECT_LABEL,
+ current_function_funcdef_no);
+
+ fde->dw_fde_second_begin = ggc_strdup (label);
if (!in_cold_section_p)
{
fde->dw_fde_end = crtl->subsections.cold_section_end_label;
- fde->dw_fde_second_begin = crtl->subsections.hot_section_label;
fde->dw_fde_second_end = crtl->subsections.hot_section_end_label;
}
else
{
fde->dw_fde_end = crtl->subsections.hot_section_end_label;
- fde->dw_fde_second_begin = crtl->subsections.cold_section_label;
fde->dw_fde_second_end = crtl->subsections.cold_section_end_label;
}
have_multiple_function_sections = true;
@@ -3671,6 +3679,7 @@ static const char *get_AT_string (dw_die_ref, enum dwarf_attribute);
static int get_AT_flag (dw_die_ref, enum dwarf_attribute);
static unsigned get_AT_unsigned (dw_die_ref, enum dwarf_attribute);
static inline dw_die_ref get_AT_ref (dw_die_ref, enum dwarf_attribute);
+static bool is_c (void);
static bool is_cxx (void);
static bool is_cxx (const_tree);
static bool is_fortran (void);
@@ -3808,6 +3817,7 @@ static bool add_location_or_const_value_attribute (dw_die_ref, tree, bool);
static bool tree_add_const_value_attribute (dw_die_ref, tree);
static bool tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
static void add_name_attribute (dw_die_ref, const char *);
+static void add_desc_attribute (dw_die_ref, tree);
static void add_gnat_descriptive_type_attribute (dw_die_ref, tree, dw_die_ref);
static void add_comp_dir_attribute (dw_die_ref);
static void add_scalar_info (dw_die_ref, enum dwarf_attribute, tree, int,
@@ -5434,6 +5444,19 @@ get_AT_file (dw_die_ref die, enum dwarf_attribute attr_kind)
return a ? AT_file (a) : NULL;
}
+/* Return TRUE if the language is C. */
+
+static inline bool
+is_c (void)
+{
+ unsigned int lang = get_AT_unsigned (comp_unit_die (), DW_AT_language);
+
+ return (lang == DW_LANG_C || lang == DW_LANG_C89 || lang == DW_LANG_C99
+ || lang == DW_LANG_C11 || lang == DW_LANG_ObjC);
+
+
+}
+
/* Return TRUE if the language is C++. */
static inline bool
@@ -6022,6 +6045,8 @@ dwarf2out_register_external_die (tree decl, const char *sym,
else
equate_decl_number_to_die (decl, die);
+ add_desc_attribute (die, decl);
+
/* Add a reference to the DIE providing early debug at $sym + off. */
add_AT_external_die_ref (die, DW_AT_abstract_origin, sym, off);
}
@@ -6455,7 +6480,12 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
print_indent -= 4;
}
else
- fprintf (outfile, " (%p)\n", (void *) val->v.val_loc);
+ {
+ if (flag_dump_noaddr || flag_dump_unnumbered)
+ fprintf (outfile, " #\n");
+ else
+ fprintf (outfile, " (%p)\n", (void *) val->v.val_loc);
+ }
break;
case dw_val_class_loc_list:
fprintf (outfile, "location list -> label:%s",
@@ -6524,7 +6554,10 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
}
else
fprintf (outfile, "die -> %ld", die->die_offset);
- fprintf (outfile, " (%p)", (void *) die);
+ if (flag_dump_noaddr || flag_dump_unnumbered)
+ fprintf (outfile, " #");
+ else
+ fprintf (outfile, " (%p)", (void *) die);
}
else
fprintf (outfile, "die -> <null>");
@@ -6614,8 +6647,11 @@ print_loc_descr (dw_loc_descr_ref loc, FILE *outfile)
for (l = loc; l != NULL; l = l->dw_loc_next)
{
print_spaces (outfile);
- fprintf (outfile, "(%p) %s",
- (void *) l,
+ if (flag_dump_noaddr || flag_dump_unnumbered)
+ fprintf (outfile, "#");
+ else
+ fprintf (outfile, "(%p)", (void *) l);
+ fprintf (outfile, " %s",
dwarf_stack_op_name (l->dw_loc_opc));
if (l->dw_loc_oprnd1.val_class != dw_val_class_none)
{
@@ -6642,9 +6678,12 @@ print_die (dw_die_ref die, FILE *outfile)
unsigned ix;
print_spaces (outfile);
- fprintf (outfile, "DIE %4ld: %s (%p)\n",
- die->die_offset, dwarf_tag_name (die->die_tag),
- (void*) die);
+ fprintf (outfile, "DIE %4ld: %s ",
+ die->die_offset, dwarf_tag_name (die->die_tag));
+ if (flag_dump_noaddr || flag_dump_unnumbered)
+ fprintf (outfile, "#\n");
+ else
+ fprintf (outfile, "(%p)\n", (void*) die);
print_spaces (outfile);
fprintf (outfile, " abbrev id: %lu", die->die_abbrev);
fprintf (outfile, " offset: %ld", die->die_offset);
@@ -14303,13 +14342,13 @@ based_loc_descr (rtx reg, poly_int64 offset,
if (elim != reg)
{
+ /* Allow hard frame pointer here even if frame pointer
+ isn't used since hard frame pointer is encoded with
+ DW_OP_fbreg which uses the DW_AT_frame_base attribute,
+ not hard frame pointer directly. */
elim = strip_offset_and_add (elim, &offset);
- gcc_assert ((SUPPORTS_STACK_ALIGNMENT
- && (elim == hard_frame_pointer_rtx
- || elim == stack_pointer_rtx))
- || elim == (frame_pointer_needed
- ? hard_frame_pointer_rtx
- : stack_pointer_rtx));
+ gcc_assert (elim == hard_frame_pointer_rtx
+ || elim == stack_pointer_rtx);
/* If drap register is used to align stack, use frame
pointer + offset to access stack variables. If stack
@@ -15476,7 +15515,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
if (dwarf_strict && dwarf_version < 5)
break;
- if (REGNO (rtl) > FIRST_PSEUDO_REGISTER)
+ if (REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
break;
type_die = base_type_for_mode (mode, SCALAR_INT_MODE_P (mode));
if (type_die == NULL)
@@ -16321,6 +16360,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
case CONST_FIXED:
case CLRSB:
case CLOBBER:
+ case CLOBBER_HIGH:
/* If delegitimize_address couldn't do anything with the UNSPEC, we
can't express it in the debug info. This can happen e.g. with some
TLS UNSPECs. */
@@ -20489,14 +20529,13 @@ compute_frame_pointer_to_fb_displacement (poly_int64 offset)
in which to eliminate. This is because it's stack pointer isn't
directly accessible as a register within the ISA. To work around
this, assume that while we cannot provide a proper value for
- frame_pointer_fb_offset, we won't need one either. */
+ frame_pointer_fb_offset, we won't need one either. We can use
+ hard frame pointer in debug info even if frame pointer isn't used
+ since hard frame pointer in debug info is encoded with DW_OP_fbreg
+ which uses the DW_AT_frame_base attribute, not hard frame pointer
+ directly. */
frame_pointer_fb_offset_valid
- = ((SUPPORTS_STACK_ALIGNMENT
- && (elim == hard_frame_pointer_rtx
- || elim == stack_pointer_rtx))
- || elim == (frame_pointer_needed
- ? hard_frame_pointer_rtx
- : stack_pointer_rtx));
+ = (elim == hard_frame_pointer_rtx || elim == stack_pointer_rtx);
}
/* Generate a DW_AT_name attribute given some string value to be included as
@@ -20514,6 +20553,52 @@ add_name_attribute (dw_die_ref die, const char *name_string)
}
}
+/* Generate a DW_AT_description attribute given some string value to be included
+ as the value of the attribute. */
+
+static void
+add_desc_attribute (dw_die_ref die, const char *name_string)
+{
+ if (!flag_describe_dies || (dwarf_version < 3 && dwarf_strict))
+ return;
+
+ if (name_string == NULL || *name_string == 0)
+ return;
+
+ if (demangle_name_func)
+ name_string = (*demangle_name_func) (name_string);
+
+ add_AT_string (die, DW_AT_description, name_string);
+}
+
+/* Generate a DW_AT_description attribute given some decl to be included
+ as the value of the attribute. */
+
+static void
+add_desc_attribute (dw_die_ref die, tree decl)
+{
+ tree decl_name;
+
+ if (!flag_describe_dies || (dwarf_version < 3 && dwarf_strict))
+ return;
+
+ if (decl == NULL_TREE || !DECL_P (decl))
+ return;
+ decl_name = DECL_NAME (decl);
+
+ if (decl_name != NULL && IDENTIFIER_POINTER (decl_name) != NULL)
+ {
+ const char *name = dwarf2_name (decl, 0);
+ add_desc_attribute (die, name ? name : IDENTIFIER_POINTER (decl_name));
+ }
+ else
+ {
+ char *desc = print_generic_expr_to_str (decl);
+ add_desc_attribute (die, desc);
+ free (desc);
+ }
+}
+
/* Retrieve the descriptive type of TYPE, if any, make sure it has a
DIE and attach a DW_AT_GNAT_descriptive_type attribute to the DIE
of TYPE accordingly.
@@ -20597,7 +20682,7 @@ static void
add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
int forms, struct loc_descr_context *context)
{
- dw_die_ref context_die, decl_die;
+ dw_die_ref context_die, decl_die = NULL;
dw_loc_list_ref list;
bool strip_conversions = true;
bool placeholder_seen = false;
@@ -20674,7 +20759,7 @@ add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
if (decl != NULL_TREE)
{
- dw_die_ref decl_die = lookup_decl_die (decl);
+ decl_die = lookup_decl_die (decl);
/* ??? Can this happen, or should the variable have been bound
first? Probably it can, since I imagine that we try to create
@@ -20683,8 +20768,12 @@ add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
later parameter. */
if (decl_die != NULL)
{
- add_AT_die_ref (die, attr, decl_die);
- return;
+ if (get_AT (decl_die, DW_AT_location)
+ || get_AT (decl_die, DW_AT_const_value))
+ {
+ add_AT_die_ref (die, attr, decl_die);
+ return;
+ }
}
}
}
@@ -20728,15 +20817,19 @@ add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
|| placeholder_seen)
return;
- if (current_function_decl == 0)
- context_die = comp_unit_die ();
- else
- context_die = lookup_decl_die (current_function_decl);
+ if (!decl_die)
+ {
+ if (current_function_decl == 0)
+ context_die = comp_unit_die ();
+ else
+ context_die = lookup_decl_die (current_function_decl);
+
+ decl_die = new_die (DW_TAG_variable, context_die, value);
+ add_AT_flag (decl_die, DW_AT_artificial, 1);
+ add_type_attribute (decl_die, TREE_TYPE (value), TYPE_QUAL_CONST, false,
+ context_die);
+ }
- decl_die = new_die (DW_TAG_variable, context_die, value);
- add_AT_flag (decl_die, DW_AT_artificial, 1);
- add_type_attribute (decl_die, TREE_TYPE (value), TYPE_QUAL_CONST, false,
- context_die);
add_AT_location_description (decl_die, DW_AT_location, list);
add_AT_die_ref (die, attr, decl_die);
}
@@ -20921,8 +21014,16 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
if (!get_AT (subrange_die, DW_AT_lower_bound))
add_bound_info (subrange_die, DW_AT_lower_bound, lower, NULL);
- if (upper && !get_AT (subrange_die, DW_AT_upper_bound))
- add_bound_info (subrange_die, DW_AT_upper_bound, upper, NULL);
+ if (!get_AT (subrange_die, DW_AT_upper_bound)
+ && !get_AT (subrange_die, DW_AT_count))
+ {
+ if (upper)
+ add_bound_info (subrange_die, DW_AT_upper_bound, upper, NULL);
+ else if ((is_c () || is_cxx ()) && COMPLETE_TYPE_P (type))
+ /* Zero-length array. */
+ add_bound_info (subrange_die, DW_AT_count,
+ build_int_cst (TREE_TYPE (lower), 0), NULL);
+ }
}
/* Otherwise we have an array type with an unspecified length. The
@@ -21264,12 +21365,17 @@ add_name_and_src_coords_attributes (dw_die_ref die, tree decl,
const char *name = dwarf2_name (decl, 0);
if (name)
add_name_attribute (die, name);
+ else
+ add_desc_attribute (die, decl);
+
if (! DECL_ARTIFICIAL (decl))
add_src_coords_attributes (die, decl);
if (!no_linkage_name)
add_linkage_name (die, decl);
}
+ else
+ add_desc_attribute (die, decl);
#ifdef VMS_DEBUGGING_INFO
/* Get the function's name, as described by its RTL. This may be different
@@ -23242,6 +23348,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
dw_die_ref die = NULL;
rtx tloc = NULL_RTX, tlocc = NULL_RTX;
rtx arg, next_arg;
+ tree arg_decl = NULL_TREE;
for (arg = (ca_loc->call_arg_loc_note != NULL_RTX
? XEXP (ca_loc->call_arg_loc_note, 0)
@@ -23306,6 +23413,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
tdie = lookup_decl_die (tdecl);
if (tdie == NULL)
continue;
+ arg_decl = tdecl;
}
else
continue;
@@ -23322,6 +23430,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
die = gen_call_site_die (decl, subr_die, ca_loc);
cdie = new_die (dwarf_TAG (DW_TAG_call_site_parameter), die,
NULL_TREE);
+ add_desc_attribute (cdie, arg_decl);
if (reg != NULL)
add_AT_loc (cdie, DW_AT_location, reg);
else if (tdie != NULL)
@@ -24239,6 +24348,7 @@ gen_producer_string (void)
case OPT_U:
case OPT_SPECIAL_unknown:
case OPT_SPECIAL_ignore:
+ case OPT_SPECIAL_deprecated:
case OPT_SPECIAL_program_name:
case OPT_SPECIAL_input_file:
case OPT_grecord_gcc_switches:
@@ -24246,6 +24356,8 @@ gen_producer_string (void)
case OPT_fdiagnostics_show_location_:
case OPT_fdiagnostics_show_option:
case OPT_fdiagnostics_show_caret:
+ case OPT_fdiagnostics_show_labels:
+ case OPT_fdiagnostics_show_line_numbers:
case OPT_fdiagnostics_color_:
case OPT_fverbose_asm:
case OPT____:
@@ -25805,7 +25917,7 @@ decls_for_scope (tree stmt, dw_die_ref context_die)
/* Is this a typedef we can avoid emitting? */
-bool
+static bool
is_redundant_typedef (const_tree decl)
{
if (TYPE_DECL_IS_STUB (decl))
@@ -27819,8 +27931,10 @@ dwarf2out_source_line (unsigned int line, unsigned int column,
if (is_stmt != table->is_stmt)
{
+#if HAVE_GAS_LOC_STMT
fputs (" is_stmt ", asm_out_file);
putc (is_stmt ? '1' : '0', asm_out_file);
+#endif
}
if (SUPPORTS_DISCRIMINATOR && discriminator != 0)
{
@@ -28253,6 +28367,12 @@ save_macinfo_strings (void)
&& (debug_str_section->common.flags & SECTION_MERGE) != 0)
set_indirect_string (find_AT_string (ref->info));
break;
+ case DW_MACINFO_start_file:
+ /* -gsplit-dwarf -g3 will also output filename as indirect
+ string. */
+ if (!dwarf_split_debug_info)
+ break;
+ /* Fall through. */
case DW_MACRO_define_strp:
case DW_MACRO_undef_strp:
set_indirect_string (find_AT_string (ref->info));
@@ -31086,7 +31206,7 @@ reset_dies (dw_die_ref die)
and generate the DWARF-2 debugging info. */
static void
-dwarf2out_finish (const char *)
+dwarf2out_finish (const char *filename)
{
comdat_type_node *ctnode;
dw_die_ref main_comp_unit_die;
@@ -31167,6 +31287,12 @@ dwarf2out_finish (const char *)
resolve_addr (comp_unit_die ());
move_marked_base_types ();
+ if (dump_file)
+ {
+ fprintf (dump_file, "DWARF for %s\n", filename);
+ print_die (comp_unit_die (), dump_file);
+ }
+
/* Initialize sections and labels used for actual assembler output. */
unsigned generation = init_sections_and_labels (false);
@@ -31862,6 +31988,11 @@ dwarf2out_early_finish (const char *filename)
if (in_lto_p)
{
early_dwarf_finished = true;
+ if (dump_file)
+ {
+ fprintf (dump_file, "LTO EARLY DWARF for %s\n", filename);
+ print_die (comp_unit_die (), dump_file);
+ }
return;
}
@@ -31939,13 +32070,18 @@ dwarf2out_early_finish (const char *filename)
/* The early debug phase is now finished. */
early_dwarf_finished = true;
+ if (dump_file)
+ {
+ fprintf (dump_file, "EARLY DWARF for %s\n", filename);
+ print_die (comp_unit_die (), dump_file);
+ }
/* Do not generate DWARF assembler now when not producing LTO bytecode. */
if ((!flag_generate_lto && !flag_generate_offload)
- /* FIXME: Disable debug info generation for PE-COFF targets since the
+ /* FIXME: Disable debug info generation for (PE-)COFF targets since the
copy_lto_debug_sections operation of the simple object support in
libiberty is not implemented for them yet. */
- || TARGET_PECOFF)
+ || TARGET_PECOFF || TARGET_COFF)
return;
/* Now as we are going to output for LTO initialize sections and labels
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index e4b0704..9a735fa 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -2865,6 +2865,7 @@ verify_rtx_sharing (rtx orig, rtx insn)
/* SCRATCH must be shared because they represent distinct values. */
return;
case CLOBBER:
+ case CLOBBER_HIGH:
/* Share clobbers of hard registers (like cc0), but do not share pseudo reg
clobbers or clobbers of hard registers that originated as pseudos.
This is needed to allow safe register renaming. */
@@ -3118,6 +3119,7 @@ repeat:
/* SCRATCH must be shared because they represent distinct values. */
return;
case CLOBBER:
+ case CLOBBER_HIGH:
/* Share clobbers of hard registers (like cc0), but do not share pseudo reg
clobbers or clobbers of hard registers that originated as pseudos.
This is needed to allow safe register renaming. */
@@ -5690,6 +5692,7 @@ copy_insn_1 (rtx orig)
case SIMPLE_RETURN:
return orig;
case CLOBBER:
+ case CLOBBER_HIGH:
/* Share clobbers of hard registers (like cc0), but do not share pseudo reg
clobbers or clobbers of hard registers that originated as pseudos.
This is needed to allow safe register renaming. */
@@ -6407,13 +6410,6 @@ init_emit_once (void)
if (GET_MODE_CLASS ((machine_mode) i) == MODE_CC)
const_tiny_rtx[0][i] = const0_rtx;
- FOR_EACH_MODE_IN_CLASS (smode_iter, MODE_POINTER_BOUNDS)
- {
- scalar_mode smode = smode_iter.require ();
- wide_int wi_zero = wi::zero (GET_MODE_PRECISION (smode));
- const_tiny_rtx[0][smode] = immed_wide_int_const (wi_zero, smode);
- }
-
pc_rtx = gen_rtx_fmt_ (PC, VOIDmode);
ret_rtx = gen_rtx_fmt_ (RETURN, VOIDmode);
simple_return_rtx = gen_rtx_fmt_ (SIMPLE_RETURN, VOIDmode);
@@ -6508,6 +6504,21 @@ gen_hard_reg_clobber (machine_mode mode, unsigned int regno)
gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (mode, regno)));
}
+static GTY((deletable)) rtx
+hard_reg_clobbers_high[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
+
+/* Return a CLOBBER_HIGH expression for register REGNO that clobbers MODE,
+ caching into HARD_REG_CLOBBERS_HIGH. */
+rtx
+gen_hard_reg_clobber_high (machine_mode mode, unsigned int regno)
+{
+ if (hard_reg_clobbers_high[mode][regno])
+ return hard_reg_clobbers_high[mode][regno];
+ else
+ return (hard_reg_clobbers_high[mode][regno]
+ = gen_rtx_CLOBBER_HIGH (VOIDmode, gen_rtx_REG (mode, regno)));
+}
+
location_t prologue_location;
location_t epilogue_location;
diff --git a/gcc/emit-rtl.h b/gcc/emit-rtl.h
index 4e7bd1e..f089355 100644
--- a/gcc/emit-rtl.h
+++ b/gcc/emit-rtl.h
@@ -75,9 +75,6 @@ struct GTY(()) rtl_data {
result in a register, current_function_return_rtx will always be
the hard register containing the result. */
rtx return_rtx;
- /* If nonxero, an RTL expression for the lcoation at which the current
- function returns bounds for its result. */
- rtx return_bnd;
/* Vector of initial-value pairs. Each pair consists of a pseudo
register of approprite mode that stores the initial value a hard
diff --git a/gcc/except.c b/gcc/except.c
index 84666d9..728b1e1 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -3189,7 +3189,8 @@ output_function_exception_table (int section)
rtx personality = get_personality_function (current_function_decl);
/* Not all functions need anything. */
- if (!crtl->uses_eh_lsda)
+ if (!crtl->uses_eh_lsda
+ || targetm_common.except_unwind_info (&global_options) == UI_NONE)
return;
/* No need to emit any boilerplate stuff for the cold part. */
diff --git a/gcc/explow.c b/gcc/explow.c
index 9a6182a..7d83eb1 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -56,8 +56,7 @@ trunc_int_for_mode (HOST_WIDE_INT c, machine_mode mode)
int width = GET_MODE_PRECISION (smode);
/* You want to truncate to a _what_? */
- gcc_assert (SCALAR_INT_MODE_P (mode)
- || POINTER_BOUNDS_MODE_P (mode));
+ gcc_assert (SCALAR_INT_MODE_P (mode));
/* Canonicalize BImode to 0 and STORE_FLAG_VALUE. */
if (smode == BImode)
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 101e7b8..29ce10b 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -2392,6 +2392,10 @@ extract_low_bits (machine_mode mode, machine_mode src_mode, rtx src)
return NULL_RTX;
src = gen_lowpart (src_int_mode, src);
+ if (!validate_subreg (int_mode, src_int_mode, src,
+ subreg_lowpart_offset (int_mode, src_int_mode)))
+ return NULL_RTX;
+
src = convert_modes (int_mode, src_int_mode, src, true);
src = gen_lowpart (mode, src);
return src;
@@ -3343,19 +3347,21 @@ expand_mult_const (machine_mode mode, rtx op0, HOST_WIDE_INT val,
/* Write a REG_EQUAL note on the last insn so that we can cse
multiplication sequences. Note that if ACCUM is a SUBREG,
we've set the inner register and must properly indicate that. */
- tem = op0, nmode = mode;
- accum_inner = accum;
- if (GET_CODE (accum) == SUBREG)
+ tem = op0, nmode = mode;
+ accum_inner = accum;
+ if (GET_CODE (accum) == SUBREG)
{
accum_inner = SUBREG_REG (accum);
nmode = GET_MODE (accum_inner);
tem = gen_lowpart (nmode, op0);
}
- insn = get_last_insn ();
- set_dst_reg_note (insn, REG_EQUAL,
- gen_rtx_MULT (nmode, tem,
- gen_int_mode (val_so_far, nmode)),
+ insn = get_last_insn ();
+ wide_int wval_so_far
+ = wi::uhwi (val_so_far,
+ GET_MODE_PRECISION (as_a <scalar_mode> (nmode)));
+ rtx c = immed_wide_int_const (wval_so_far, nmode);
+ set_dst_reg_note (insn, REG_EQUAL, gen_rtx_MULT (nmode, tem, c),
accum_inner);
}
}
@@ -5541,6 +5547,9 @@ emit_store_flag_1 (rtx target, enum rtx_code code, rtx op0, rtx op1,
if (mode == VOIDmode)
mode = GET_MODE (op0);
+ if (CONST_SCALAR_INT_P (op1))
+ canonicalize_comparison (mode, &code, &op1);
+
/* For some comparisons with 1 and -1, we can convert this to
comparisons with zero. This will often produce more opportunities for
store-flag insns. */
@@ -6161,6 +6170,106 @@ emit_store_flag_force (rtx target, enum rtx_code code, rtx op0, rtx op1,
return target;
}
+
+/* Helper function for canonicalize_cmp_for_target. Swap between inclusive
+ and exclusive ranges in order to create an equivalent comparison. See
+ canonicalize_cmp_for_target for the possible cases. */
+
+static enum rtx_code
+equivalent_cmp_code (enum rtx_code code)
+{
+ switch (code)
+ {
+ case GT:
+ return GE;
+ case GE:
+ return GT;
+ case LT:
+ return LE;
+ case LE:
+ return LT;
+ case GTU:
+ return GEU;
+ case GEU:
+ return GTU;
+ case LTU:
+ return LEU;
+ case LEU:
+ return LTU;
+
+ default:
+ return code;
+ }
+}
+
+/* Choose the more appropiate immediate in scalar integer comparisons. The
+ purpose of this is to end up with an immediate which can be loaded into a
+ register in fewer moves, if possible.
+
+ For each integer comparison there exists an equivalent choice:
+ i) a > b or a >= b + 1
+ ii) a <= b or a < b + 1
+ iii) a >= b or a > b - 1
+ iv) a < b or a <= b - 1
+
+ MODE is the mode of the first operand.
+ CODE points to the comparison code.
+ IMM points to the rtx containing the immediate. *IMM must satisfy
+ CONST_SCALAR_INT_P on entry and continues to satisfy CONST_SCALAR_INT_P
+ on exit. */
+
+void
+canonicalize_comparison (machine_mode mode, enum rtx_code *code, rtx *imm)
+{
+ if (!SCALAR_INT_MODE_P (mode))
+ return;
+
+ int to_add = 0;
+ enum signop sgn = unsigned_condition_p (*code) ? UNSIGNED : SIGNED;
+
+ /* Extract the immediate value from the rtx. */
+ wide_int imm_val = rtx_mode_t (*imm, mode);
+
+ if (*code == GT || *code == GTU || *code == LE || *code == LEU)
+ to_add = 1;
+ else if (*code == GE || *code == GEU || *code == LT || *code == LTU)
+ to_add = -1;
+ else
+ return;
+
+ /* Check for overflow/underflow in the case of signed values and
+ wrapping around in the case of unsigned values. If any occur
+ cancel the optimization. */
+ wi::overflow_type overflow = wi::OVF_NONE;
+ wide_int imm_modif;
+
+ if (to_add == 1)
+ imm_modif = wi::add (imm_val, 1, sgn, &overflow);
+ else
+ imm_modif = wi::sub (imm_val, 1, sgn, &overflow);
+
+ if (overflow)
+ return;
+
+ /* The following creates a pseudo; if we cannot do that, bail out. */
+ if (!can_create_pseudo_p ())
+ return;
+
+ rtx reg = gen_rtx_REG (mode, LAST_VIRTUAL_REGISTER + 1);
+ rtx new_imm = immed_wide_int_const (imm_modif, mode);
+
+ rtx_insn *old_rtx = gen_move_insn (reg, *imm);
+ rtx_insn *new_rtx = gen_move_insn (reg, new_imm);
+
+ /* Update the immediate and the code. */
+ if (insn_cost (old_rtx, true) > insn_cost (new_rtx, true))
+ {
+ *code = equivalent_cmp_code (*code);
+ *imm = new_imm;
+ }
+}
+
+
/* Perform possibly multi-word comparison and conditional jump to LABEL
if ARG1 OP ARG2 true where ARG1 and ARG2 are of mode MODE. This is
diff --git a/gcc/expmed.h b/gcc/expmed.h
index 2890d9c..cc247c4 100644
--- a/gcc/expmed.h
+++ b/gcc/expmed.h
@@ -702,6 +702,8 @@ extern rtx emit_store_flag (rtx, enum rtx_code, rtx, rtx, machine_mode,
extern rtx emit_store_flag_force (rtx, enum rtx_code, rtx, rtx,
machine_mode, int, int);
+extern void canonicalize_comparison (machine_mode, enum rtx_code *, rtx *);
+
/* Choose a minimal N + 1 bit approximation to 1/D that can be used to
replace division by D, and put the least significant N bits of the result
in *MULTIPLIER_PTR and return the most significant bit. */
diff --git a/gcc/expr.c b/gcc/expr.c
index de6709d..b8782b9 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -2767,6 +2767,7 @@ copy_blkmode_to_reg (machine_mode mode_in, tree src)
/* No current ABI uses variable-sized modes to pass a BLKmnode type. */
fixed_size_mode mode = as_a <fixed_size_mode> (mode_in);
fixed_size_mode dst_mode;
+ scalar_int_mode min_mode;
gcc_assert (TYPE_MODE (TREE_TYPE (src)) == BLKmode);
@@ -2796,6 +2797,7 @@ copy_blkmode_to_reg (machine_mode mode_in, tree src)
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);
+ min_mode = smallest_int_mode_for_size (bitsize);
/* Copy the structure BITSIZE bits at a time. */
for (bitpos = 0, xbitpos = padding_correction;
@@ -2816,6 +2818,25 @@ copy_blkmode_to_reg (machine_mode mode_in, tree src)
emit_move_insn (dst_word, CONST0_RTX (word_mode));
}
+ /* Find the largest integer mode that can be used to copy all or as
+ many bits as possible of the structure if the target supports larger
+ copies. There are too many corner cases here w.r.t to alignments on
+ the read/writes. So if there is any padding just use single byte
+ operations. */
+ opt_scalar_int_mode mode_iter;
+ if (padding_correction == 0 && !STRICT_ALIGNMENT)
+ {
+ FOR_EACH_MODE_FROM (mode_iter, min_mode)
+ {
+ unsigned int msize = GET_MODE_BITSIZE (mode_iter.require ());
+ if (msize <= ((bytes * BITS_PER_UNIT) - bitpos)
+ && msize <= BITS_PER_WORD)
+ bitsize = msize;
+ else
+ break;
+ }
+ }
+
/* We need a new source operand each time bitpos is on a word
boundary. */
if (bitpos % BITS_PER_WORD == 0)
@@ -5249,6 +5270,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
MEM_VOLATILE_P (to_rtx) = 1;
}
+ gcc_checking_assert (known_ge (bitpos, 0));
if (optimize_bitfield_assignment_op (bitsize, bitpos,
bitregion_start, bitregion_end,
mode1, to_rtx, to, from,
@@ -7025,6 +7047,7 @@ store_field (rtx target, poly_int64 bitsize, poly_int64 bitpos,
}
/* Store the value in the bitfield. */
+ gcc_checking_assert (known_ge (bitpos, 0));
store_bit_field (target, bitsize, bitpos,
bitregion_start, bitregion_end,
mode, temp, reverse);
@@ -10524,6 +10547,14 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
mode2
= CONSTANT_P (op0) ? TYPE_MODE (TREE_TYPE (tem)) : GET_MODE (op0);
+ /* Make sure bitpos is not negative, it can wreak havoc later. */
+ if (maybe_lt (bitpos, 0))
+ {
+ gcc_checking_assert (offset == NULL_TREE);
+ offset = size_int (bits_to_bytes_round_down (bitpos));
+ bitpos = num_trailing_bits (bitpos);
+ }
+
/* If we have either an offset, a BLKmode result, or a reference
outside the underlying object, we must force it to memory.
Such a case can occur in Ada if we have unchecked conversion
@@ -10774,6 +10805,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
&& GET_MODE_CLASS (ext_mode) == MODE_INT)
reversep = TYPE_REVERSE_STORAGE_ORDER (type);
+ gcc_checking_assert (known_ge (bitpos, 0));
op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp,
(modifier == EXPAND_STACK_PARM
? NULL_RTX : target),
@@ -10905,7 +10937,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
}
/* Check for a built-in function. */
- if (fndecl && DECL_BUILT_IN (fndecl))
+ if (fndecl && fndecl_built_in_p (fndecl))
{
gcc_assert (DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_FRONTEND);
return expand_builtin (exp, target, subtarget, tmode, ignore);
@@ -11271,10 +11303,11 @@ is_aligning_offset (const_tree offset, const_tree exp)
/* Return the tree node if an ARG corresponds to a string constant or zero
if it doesn't. If we return nonzero, set *PTR_OFFSET to the (possibly
non-constant) offset in bytes within the string that ARG is accessing.
- The type of the offset is sizetype. */
+ If MEM_SIZE is non-zero the storage size of the memory is returned.
+ If DECL is non-zero the constant declaration is returned if available. */
tree
-string_constant (tree arg, tree *ptr_offset)
+string_constant (tree arg, tree *ptr_offset, tree *mem_size, tree *decl)
{
tree array;
STRIP_NOPS (arg);
@@ -11303,6 +11336,12 @@ string_constant (tree arg, tree *ptr_offset)
if (TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE)
return NULL_TREE;
+
+ if (!integer_zerop (array_ref_low_bound (arg)))
+ return NULL_TREE;
+
+ if (!integer_onep (array_ref_element_size (arg)))
+ return NULL_TREE;
}
}
array = get_addr_base_and_unit_offset (ref, &base_off);
@@ -11328,7 +11367,7 @@ string_constant (tree arg, tree *ptr_offset)
return NULL_TREE;
tree offset;
- if (tree str = string_constant (arg0, &offset))
+ if (tree str = string_constant (arg0, &offset, mem_size, decl))
{
/* Avoid pointers to arrays (see bug 86622). */
if (POINTER_TYPE_P (TREE_TYPE (arg))
@@ -11358,16 +11397,18 @@ string_constant (tree arg, tree *ptr_offset)
if (TREE_CODE (chartype) != INTEGER_TYPE)
return NULL;
- tree charsize = array_ref_element_size (arg);
- /* Set the non-constant offset to the non-constant index scaled
- by the size of the character type. */
- offset = fold_build2 (MULT_EXPR, TREE_TYPE (offset),
- fold_convert (sizetype, varidx), charsize);
+ offset = fold_convert (sizetype, varidx);
}
if (TREE_CODE (array) == STRING_CST)
{
*ptr_offset = fold_convert (sizetype, offset);
+ if (mem_size)
+ *mem_size = TYPE_SIZE_UNIT (TREE_TYPE (array));
+ if (decl)
+ *decl = NULL_TREE;
+ gcc_checking_assert (tree_to_shwi (TYPE_SIZE_UNIT (TREE_TYPE (array)))
+ >= TREE_STRING_LENGTH (array));
return array;
}
@@ -11410,30 +11451,350 @@ string_constant (tree arg, tree *ptr_offset)
if (!init || TREE_CODE (init) != STRING_CST)
return NULL_TREE;
- tree array_size = DECL_SIZE_UNIT (array);
- if (!array_size || TREE_CODE (array_size) != INTEGER_CST)
- return NULL_TREE;
+ if (mem_size)
+ *mem_size = TYPE_SIZE_UNIT (TREE_TYPE (init));
+ if (decl)
+ *decl = array;
- /* Avoid returning a string that doesn't fit in the array
- it is stored in, like
- const char a[4] = "abcde";
- but do handle those that fit even if they have excess
- initializers, such as in
- const char a[4] = "abc\000\000";
- The excess elements contribute to TREE_STRING_LENGTH()
- but not to strlen(). */
- unsigned HOST_WIDE_INT charsize
- = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (init))));
- unsigned HOST_WIDE_INT length = TREE_STRING_LENGTH (init);
- length = string_length (TREE_STRING_POINTER (init), charsize,
- length / charsize);
- if (compare_tree_int (array_size, length + 1) < 0)
- return NULL_TREE;
+ gcc_checking_assert (tree_to_shwi (TYPE_SIZE_UNIT (TREE_TYPE (init)))
+ >= TREE_STRING_LENGTH (init));
*ptr_offset = offset;
return init;
}
+/* Compute the modular multiplicative inverse of A modulo M
+ using extended Euclid's algorithm. Assumes A and M are coprime. */
+static wide_int
+mod_inv (const wide_int &a, const wide_int &b)
+{
+ /* Verify the assumption. */
+ gcc_checking_assert (wi::eq_p (wi::gcd (a, b), 1));
+
+ unsigned int p = a.get_precision () + 1;
+ gcc_checking_assert (b.get_precision () + 1 == p);
+ wide_int c = wide_int::from (a, p, UNSIGNED);
+ wide_int d = wide_int::from (b, p, UNSIGNED);
+ wide_int x0 = wide_int::from (0, p, UNSIGNED);
+ wide_int x1 = wide_int::from (1, p, UNSIGNED);
+
+ if (wi::eq_p (b, 1))
+ return wide_int::from (1, p, UNSIGNED);
+
+ while (wi::gt_p (c, 1, UNSIGNED))
+ {
+ wide_int t = d;
+ wide_int q = wi::divmod_trunc (c, d, UNSIGNED, &d);
+ c = t;
+ wide_int s = x0;
+ x0 = wi::sub (x1, wi::mul (q, x0));
+ x1 = s;
+ }
+ if (wi::lt_p (x1, 0, SIGNED))
+ x1 += d;
+ return x1;
+}
+
+/* Optimize x % C1 == C2 for signed modulo if C1 is a power of two and C2
+ is non-zero and C3 ((1<<(prec-1)) | (C1 - 1)):
+ for C2 > 0 to x & C3 == C2
+ for C2 < 0 to x & C3 == (C2 & C3). */
+enum tree_code
+maybe_optimize_pow2p_mod_cmp (enum tree_code code, tree *arg0, tree *arg1)
+{
+ gimple *stmt = get_def_for_expr (*arg0, TRUNC_MOD_EXPR);
+ tree treeop0 = gimple_assign_rhs1 (stmt);
+ tree treeop1 = gimple_assign_rhs2 (stmt);
+ tree type = TREE_TYPE (*arg0);
+ scalar_int_mode mode;
+ if (!is_a <scalar_int_mode> (TYPE_MODE (type), &mode))
+ return code;
+ if (GET_MODE_BITSIZE (mode) != TYPE_PRECISION (type)
+ || TYPE_PRECISION (type) <= 1
+ || TYPE_UNSIGNED (type)
+ /* Signed x % c == 0 should have been optimized into unsigned modulo
+ earlier. */
+ || integer_zerop (*arg1)
+ /* If c is known to be non-negative, modulo will be expanded as unsigned
+ modulo. */
+ || get_range_pos_neg (treeop0) == 1)
+ return code;
+
+ /* x % c == d where d < 0 && d <= -c should be always false. */
+ if (tree_int_cst_sgn (*arg1) == -1
+ && -wi::to_widest (treeop1) >= wi::to_widest (*arg1))
+ return code;
+
+ int prec = TYPE_PRECISION (type);
+ wide_int w = wi::to_wide (treeop1) - 1;
+ w |= wi::shifted_mask (0, prec - 1, true, prec);
+ tree c3 = wide_int_to_tree (type, w);
+ tree c4 = *arg1;
+ if (tree_int_cst_sgn (*arg1) == -1)
+ c4 = wide_int_to_tree (type, w & wi::to_wide (*arg1));
+
+ rtx op0 = expand_normal (treeop0);
+ treeop0 = make_tree (TREE_TYPE (treeop0), op0);
+
+ bool speed_p = optimize_insn_for_speed_p ();
+
+ do_pending_stack_adjust ();
+
+ location_t loc = gimple_location (stmt);
+ struct separate_ops ops;
+ ops.code = TRUNC_MOD_EXPR;
+ ops.location = loc;
+ ops.type = TREE_TYPE (treeop0);
+ ops.op0 = treeop0;
+ ops.op1 = treeop1;
+ ops.op2 = NULL_TREE;
+ start_sequence ();
+ rtx mor = expand_expr_real_2 (&ops, NULL_RTX, TYPE_MODE (ops.type),
+ EXPAND_NORMAL);
+ rtx_insn *moinsns = get_insns ();
+ end_sequence ();
+
+ unsigned mocost = seq_cost (moinsns, speed_p);
+ mocost += rtx_cost (mor, mode, EQ, 0, speed_p);
+ mocost += rtx_cost (expand_normal (*arg1), mode, EQ, 1, speed_p);
+
+ ops.code = BIT_AND_EXPR;
+ ops.location = loc;
+ ops.type = TREE_TYPE (treeop0);
+ ops.op0 = treeop0;
+ ops.op1 = c3;
+ ops.op2 = NULL_TREE;
+ start_sequence ();
+ rtx mur = expand_expr_real_2 (&ops, NULL_RTX, TYPE_MODE (ops.type),
+ EXPAND_NORMAL);
+ rtx_insn *muinsns = get_insns ();
+ end_sequence ();
+
+ unsigned mucost = seq_cost (muinsns, speed_p);
+ mucost += rtx_cost (mur, mode, EQ, 0, speed_p);
+ mucost += rtx_cost (expand_normal (c4), mode, EQ, 1, speed_p);
+
+ if (mocost <= mucost)
+ {
+ emit_insn (moinsns);
+ *arg0 = make_tree (TREE_TYPE (*arg0), mor);
+ return code;
+ }
+
+ emit_insn (muinsns);
+ *arg0 = make_tree (TREE_TYPE (*arg0), mur);
+ *arg1 = c4;
+ return code;
+}
+
+/* Attempt to optimize unsigned (X % C1) == C2 (or (X % C1) != C2).
+ If C1 is odd to:
+ (X - C2) * C3 <= C4 (or >), where
+ C3 is modular multiplicative inverse of C1 and 1<<prec and
+ C4 is ((1<<prec) - 1) / C1 or ((1<<prec) - 1) / C1 - 1 (the latter
+ if C2 > ((1<<prec) - 1) % C1).
+ If C1 is even, S = ctz (C1) and C2 is 0, use
+ ((X * C3) r>> S) <= C4, where C3 is modular multiplicative
+ inverse of C1>>S and 1<<prec and C4 is (((1<<prec) - 1) / (C1>>S)) >> S.
+
+ For signed (X % C1) == 0 if C1 is odd to (all operations in it
+ unsigned):
+ (X * C3) + C4 <= 2 * C4, where
+ C3 is modular multiplicative inverse of (unsigned) C1 and 1<<prec and
+ C4 is ((1<<(prec - 1) - 1) / C1).
+ If C1 is even, S = ctz(C1), use
+ ((X * C3) + C4) r>> S <= (C4 >> (S - 1))
+ where C3 is modular multiplicative inverse of (unsigned)(C1>>S) and 1<<prec
+ and C4 is ((1<<(prec - 1) - 1) / (C1>>S)) & (-1<<S).
+
+ See the Hacker's Delight book, section 10-17. */
+enum tree_code
+maybe_optimize_mod_cmp (enum tree_code code, tree *arg0, tree *arg1)
+{
+ gcc_checking_assert (code == EQ_EXPR || code == NE_EXPR);
+ gcc_checking_assert (TREE_CODE (*arg1) == INTEGER_CST);
+
+ if (optimize < 2)
+ return code;
+
+ gimple *stmt = get_def_for_expr (*arg0, TRUNC_MOD_EXPR);
+ if (stmt == NULL)
+ return code;
+
+ tree treeop0 = gimple_assign_rhs1 (stmt);
+ tree treeop1 = gimple_assign_rhs2 (stmt);
+ if (TREE_CODE (treeop0) != SSA_NAME
+ || TREE_CODE (treeop1) != INTEGER_CST
+ /* Don't optimize the undefined behavior case x % 0;
+ x % 1 should have been optimized into zero, punt if
+ it makes it here for whatever reason;
+ x % -c should have been optimized into x % c. */
+ || compare_tree_int (treeop1, 2) <= 0
+ /* Likewise x % c == d where d >= c should be always false. */
+ || tree_int_cst_le (treeop1, *arg1))
+ return code;
+
+ /* Unsigned x % pow2 is handled right already, for signed
+ modulo handle it in maybe_optimize_pow2p_mod_cmp. */
+ if (integer_pow2p (treeop1))
+ return maybe_optimize_pow2p_mod_cmp (code, arg0, arg1);
+
+ tree type = TREE_TYPE (*arg0);
+ scalar_int_mode mode;
+ if (!is_a <scalar_int_mode> (TYPE_MODE (type), &mode))
+ return code;
+ if (GET_MODE_BITSIZE (mode) != TYPE_PRECISION (type)
+ || TYPE_PRECISION (type) <= 1)
+ return code;
+
+ signop sgn = UNSIGNED;
+ /* If both operands are known to have the sign bit clear, handle
+ even the signed modulo case as unsigned. treeop1 is always
+ positive >= 2, checked above. */
+ if (!TYPE_UNSIGNED (type) && get_range_pos_neg (treeop0) != 1)
+ sgn = SIGNED;
+
+ if (!TYPE_UNSIGNED (type))
+ {
+ if (tree_int_cst_sgn (*arg1) == -1)
+ return code;
+ type = unsigned_type_for (type);
+ if (!type || TYPE_MODE (type) != TYPE_MODE (TREE_TYPE (*arg0)))
+ return code;
+ }
+
+ int prec = TYPE_PRECISION (type);
+ wide_int w = wi::to_wide (treeop1);
+ int shift = wi::ctz (w);
+ /* Unsigned (X % C1) == C2 is equivalent to (X - C2) % C1 == 0 if
+ C2 <= -1U % C1, because for any Z >= 0U - C2 in that case (Z % C1) != 0.
+ If C1 is odd, we can handle all cases by subtracting
+ C4 below. We could handle even the even C1 and C2 > -1U % C1 cases
+ e.g. by testing for overflow on the subtraction, punt on that for now
+ though. */
+ if ((sgn == SIGNED || shift) && !integer_zerop (*arg1))
+ {
+ if (sgn == SIGNED)
+ return code;
+ wide_int x = wi::umod_trunc (wi::mask (prec, false, prec), w);
+ if (wi::gtu_p (wi::to_wide (*arg1), x))
+ return code;
+ }
+
+ imm_use_iterator imm_iter;
+ use_operand_p use_p;
+ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, treeop0)
+ {
+ gimple *use_stmt = USE_STMT (use_p);
+ /* Punt if treeop0 is used in the same bb in a division
+ or another modulo with the same divisor. We should expect
+ the division and modulo combined together. */
+ if (use_stmt == stmt
+ || gimple_bb (use_stmt) != gimple_bb (stmt))
+ continue;
+ if (!is_gimple_assign (use_stmt)
+ || (gimple_assign_rhs_code (use_stmt) != TRUNC_DIV_EXPR
+ && gimple_assign_rhs_code (use_stmt) != TRUNC_MOD_EXPR))
+ continue;
+ if (gimple_assign_rhs1 (use_stmt) != treeop0
+ || !operand_equal_p (gimple_assign_rhs2 (use_stmt), treeop1, 0))
+ continue;
+ return code;
+ }
+
+ w = wi::lrshift (w, shift);
+ wide_int a = wide_int::from (w, prec + 1, UNSIGNED);
+ wide_int b = wi::shifted_mask (prec, 1, false, prec + 1);
+ wide_int m = wide_int::from (mod_inv (a, b), prec, UNSIGNED);
+ tree c3 = wide_int_to_tree (type, m);
+ tree c5 = NULL_TREE;
+ wide_int d, e;
+ if (sgn == UNSIGNED)
+ {
+ d = wi::divmod_trunc (wi::mask (prec, false, prec), w, UNSIGNED, &e);
+ /* Use <= floor ((1<<prec) - 1) / C1 only if C2 <= ((1<<prec) - 1) % C1,
+ otherwise use < or subtract one from C4. E.g. for
+ x % 3U == 0 we transform this into x * 0xaaaaaaab <= 0x55555555, but
+ x % 3U == 1 already needs to be
+ (x - 1) * 0xaaaaaaabU <= 0x55555554. */
+ if (!shift && wi::gtu_p (wi::to_wide (*arg1), e))
+ d -= 1;
+ if (shift)
+ d = wi::lrshift (d, shift);
+ }
+ else
+ {
+ e = wi::udiv_trunc (wi::mask (prec - 1, false, prec), w);
+ if (!shift)
+ d = wi::lshift (e, 1);
+ else
+ {
+ e = wi::bit_and (e, wi::mask (shift, true, prec));
+ d = wi::lrshift (e, shift - 1);
+ }
+ c5 = wide_int_to_tree (type, e);
+ }
+ tree c4 = wide_int_to_tree (type, d);
+
+ rtx op0 = expand_normal (treeop0);
+ treeop0 = make_tree (TREE_TYPE (treeop0), op0);
+
+ bool speed_p = optimize_insn_for_speed_p ();
+
+ do_pending_stack_adjust ();
+
+ location_t loc = gimple_location (stmt);
+ struct separate_ops ops;
+ ops.code = TRUNC_MOD_EXPR;
+ ops.location = loc;
+ ops.type = TREE_TYPE (treeop0);
+ ops.op0 = treeop0;
+ ops.op1 = treeop1;
+ ops.op2 = NULL_TREE;
+ start_sequence ();
+ rtx mor = expand_expr_real_2 (&ops, NULL_RTX, TYPE_MODE (ops.type),
+ EXPAND_NORMAL);
+ rtx_insn *moinsns = get_insns ();
+ end_sequence ();
+
+ unsigned mocost = seq_cost (moinsns, speed_p);
+ mocost += rtx_cost (mor, mode, EQ, 0, speed_p);
+ mocost += rtx_cost (expand_normal (*arg1), mode, EQ, 1, speed_p);
+
+ tree t = fold_convert_loc (loc, type, treeop0);
+ if (!integer_zerop (*arg1))
+ t = fold_build2_loc (loc, MINUS_EXPR, type, t, fold_convert (type, *arg1));
+ t = fold_build2_loc (loc, MULT_EXPR, type, t, c3);
+ if (sgn == SIGNED)
+ t = fold_build2_loc (loc, PLUS_EXPR, type, t, c5);
+ if (shift)
+ {
+ tree s = build_int_cst (NULL_TREE, shift);
+ t = fold_build2_loc (loc, RROTATE_EXPR, type, t, s);
+ }
+
+ start_sequence ();
+ rtx mur = expand_normal (t);
+ rtx_insn *muinsns = get_insns ();
+ end_sequence ();
+
+ unsigned mucost = seq_cost (muinsns, speed_p);
+ mucost += rtx_cost (mur, mode, LE, 0, speed_p);
+ mucost += rtx_cost (expand_normal (c4), mode, LE, 1, speed_p);
+
+ if (mocost <= mucost)
+ {
+ emit_insn (moinsns);
+ *arg0 = make_tree (TREE_TYPE (*arg0), mor);
+ return code;
+ }
+
+ emit_insn (muinsns);
+ *arg0 = make_tree (type, mur);
+ *arg1 = c4;
+ return code == EQ_EXPR ? LE_EXPR : GT_EXPR;
+}
+
/* Generate code to calculate OPS, and exploded expression
using a store-flag instruction and return an rtx for the result.
OPS reflects a comparison.
@@ -11481,17 +11842,15 @@ do_store_flag (sepops ops, rtx target, machine_mode mode)
/* We won't bother with store-flag operations involving function pointers
when function pointers must be canonicalized before comparisons. */
if (targetm.have_canonicalize_funcptr_for_compare ()
- && ((TREE_CODE (TREE_TYPE (arg0)) == POINTER_TYPE
- && (TREE_CODE (TREE_TYPE (TREE_TYPE (arg0)))
- == FUNCTION_TYPE))
- || (TREE_CODE (TREE_TYPE (arg1)) == POINTER_TYPE
- && (TREE_CODE (TREE_TYPE (TREE_TYPE (arg1)))
- == FUNCTION_TYPE))))
+ && ((POINTER_TYPE_P (TREE_TYPE (arg0))
+ && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (arg0))))
+ || (POINTER_TYPE_P (TREE_TYPE (arg1))
+ && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (arg1))))))
return 0;
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. */
@@ -11510,6 +11869,24 @@ do_store_flag (sepops ops, rtx target, machine_mode mode)
}
}
+ /* Optimize (x % C1) == C2 or (x % C1) != C2 if it is beneficial
+ into (x - C2) * C3 < C4. */
+ if ((ops->code == EQ_EXPR || ops->code == NE_EXPR)
+ && TREE_CODE (arg0) == SSA_NAME
+ && TREE_CODE (arg1) == INTEGER_CST)
+ {
+ enum tree_code code = maybe_optimize_mod_cmp (ops->code, &arg0, &arg1);
+ if (code != ops->code)
+ {
+ struct separate_ops nops = *ops;
+ nops.code = ops->code = code;
+ nops.op0 = arg0;
+ nops.op1 = arg1;
+ nops.type = TREE_TYPE (arg0);
+ return do_store_flag (&nops, target, mode);
+ }
+ }
+
/* Get the rtx comparison code to use. We know that EXP is a comparison
operation of some type. Some comparisons against 1 and -1 can be
converted to comparisons with zero. Do so here so that the tests
diff --git a/gcc/expr.h b/gcc/expr.h
index cf047d4..19028f0 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -288,7 +288,9 @@ expand_normal (tree exp)
/* Return the tree node and offset if a given argument corresponds to
a string constant. */
-extern tree string_constant (tree, tree *);
+extern tree string_constant (tree, tree *, tree *, tree *);
+
+extern enum tree_code maybe_optimize_mod_cmp (enum tree_code, tree *, tree *);
/* Two different ways of generating switch statements. */
extern int try_casesi (tree, tree, tree, tree, rtx, rtx, rtx, profile_probability);
diff --git a/gcc/final.c b/gcc/final.c
index 6fa4acd..6943c07 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -122,12 +122,20 @@ static int last_linenum;
/* Column number of last NOTE. */
static int last_columnnum;
-/* Last discriminator written to assembly. */
+/* Discriminator written to assembly. */
static int last_discriminator;
-/* Discriminator of current block. */
+/* Discriminator to be written to assembly for current instruction.
+ Note: actual usage depends on loc_discriminator_kind setting. */
static int discriminator;
+/* Discriminator identifying current basic block among others sharing
+ the same locus. */
+static int bb_discriminator;
+
+/* Basic block discriminator for previous instruction. */
+static int last_bb_discriminator;
+
/* Highest line number in current block. */
static int high_block_linenum;
@@ -1701,6 +1709,7 @@ final_start_function_1 (rtx_insn **firstp, FILE *file, int *seen,
last_linenum = LOCATION_LINE (prologue_location);
last_columnnum = LOCATION_COLUMN (prologue_location);
last_discriminator = discriminator = 0;
+ last_bb_discriminator = bb_discriminator = 0;
high_block_linenum = high_function_linenum = last_linenum;
@@ -2223,6 +2232,9 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
ASM_OUTPUT_LABEL (asm_out_file,
IDENTIFIER_POINTER (cold_function_name));
#endif
+ if (dwarf2out_do_frame ()
+ && cfun->fde->dw_fde_second_begin != NULL)
+ ASM_OUTPUT_LABEL (asm_out_file, cfun->fde->dw_fde_second_begin);
}
break;
@@ -2236,8 +2248,7 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
if (targetm.asm_out.unwind_emit)
targetm.asm_out.unwind_emit (asm_out_file, insn);
- discriminator = NOTE_BASIC_BLOCK (insn)->discriminator;
-
+ bb_discriminator = NOTE_BASIC_BLOCK (insn)->discriminator;
break;
case NOTE_INSN_EH_REGION_BEG:
@@ -3144,6 +3155,62 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p,
}
+
+/* Map DECLs to instance discriminators. This is allocated and
+ defined in ada/gcc-interfaces/trans.c, when compiling with -gnateS.
+ Mappings from this table are saved and restored for LTO, so
+ link-time compilation will have this map set, at least in
+ partitions containing at least one DECL with an associated instance
+ discriminator. */
+
+decl_to_instance_map_t *decl_to_instance_map;
+
+/* Return the instance number assigned to DECL. */
+
+static inline int
+map_decl_to_instance (const_tree decl)
+{
+ int *inst;
+
+ if (!decl_to_instance_map || !decl || !DECL_P (decl))
+ return 0;
+
+ inst = decl_to_instance_map->get (decl);
+
+ if (!inst)
+ return 0;
+
+ return *inst;
+}
+
+/* Set DISCRIMINATOR to the appropriate value, possibly derived from LOC. */
+
+static inline void
+maybe_set_discriminator (location_t loc)
+{
+ if (!decl_to_instance_map)
+ discriminator = bb_discriminator;
+ else
+ {
+ tree block = LOCATION_BLOCK (loc);
+
+ while (block && TREE_CODE (block) == BLOCK
+ && !inlined_function_outer_scope_p (block))
+ block = BLOCK_SUPERCONTEXT (block);
+
+ tree decl;
+
+ if (!block)
+ decl = current_function_decl;
+ else if (DECL_P (block))
+ decl = block;
+ else
+ decl = block_ultimate_origin (block);
+
+ discriminator = map_decl_to_instance (decl);
+ }
+}
+
/* Return whether a source line note needs to be emitted before INSN.
Sets IS_STMT to TRUE if the line should be marked as a possible
breakpoint location. */
@@ -3178,6 +3245,7 @@ notice_source_line (rtx_insn *insn, bool *is_stmt)
filename = xloc.file;
linenum = xloc.line;
columnnum = xloc.column;
+ maybe_set_discriminator (loc);
force_source_line = true;
}
else if (override_filename)
@@ -3192,6 +3260,7 @@ notice_source_line (rtx_insn *insn, bool *is_stmt)
filename = xloc.file;
linenum = xloc.line;
columnnum = xloc.column;
+ maybe_set_discriminator (INSN_LOCATION (insn));
}
else
{
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index b318fc77..3a6d1b1 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -3451,7 +3451,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
case tcc_declaration:
/* Consider __builtin_sqrt equal to sqrt. */
return (TREE_CODE (arg0) == FUNCTION_DECL
- && DECL_BUILT_IN (arg0) && DECL_BUILT_IN (arg1)
+ && fndecl_built_in_p (arg0) && fndecl_built_in_p (arg1)
&& DECL_BUILT_IN_CLASS (arg0) == DECL_BUILT_IN_CLASS (arg1)
&& DECL_FUNCTION_CODE (arg0) == DECL_FUNCTION_CODE (arg1));
@@ -4956,8 +4956,8 @@ build_range_check (location_t loc, tree type, tree exp, int in_p,
/* Disable this optimization for function pointer expressions
on targets that require function pointer canonicalization. */
if (targetm.have_canonicalize_funcptr_for_compare ()
- && TREE_CODE (etype) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (etype)) == FUNCTION_TYPE)
+ && POINTER_TYPE_P (etype)
+ && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (etype)))
return NULL_TREE;
if (! in_p)
@@ -10661,28 +10661,6 @@ fold_binary_loc (location_t loc, enum tree_code code, tree type,
}
}
- /* If this is an NE or EQ comparison of zero against the result of a
- signed MOD operation whose second operand is a power of 2, make
- the MOD operation unsigned since it is simpler and equivalent. */
- if (integer_zerop (arg1)
- && !TYPE_UNSIGNED (TREE_TYPE (arg0))
- && (TREE_CODE (arg0) == TRUNC_MOD_EXPR
- || TREE_CODE (arg0) == CEIL_MOD_EXPR
- || TREE_CODE (arg0) == FLOOR_MOD_EXPR
- || TREE_CODE (arg0) == ROUND_MOD_EXPR)
- && integer_pow2p (TREE_OPERAND (arg0, 1)))
- {
- tree newtype = unsigned_type_for (TREE_TYPE (arg0));
- tree newmod = fold_build2_loc (loc, TREE_CODE (arg0), newtype,
- fold_convert_loc (loc, newtype,
- TREE_OPERAND (arg0, 0)),
- fold_convert_loc (loc, newtype,
- TREE_OPERAND (arg0, 1)));
-
- return fold_build2_loc (loc, code, type, newmod,
- fold_convert_loc (loc, newtype, arg1));
- }
-
/* Fold ((X >> C1) & C2) == 0 and ((X >> C1) & C2) != 0 where
C1 is a valid shift constant, and C2 is a power of two, i.e.
a single bit. */
@@ -10753,8 +10731,7 @@ fold_binary_loc (location_t loc, enum tree_code code, tree type,
tree fndecl = get_callee_fndecl (arg0);
if (fndecl
- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRLEN
+ && fndecl_built_in_p (fndecl, BUILT_IN_STRLEN)
&& call_expr_nargs (arg0) == 1
&& TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (arg0, 0))) == POINTER_TYPE)
{
@@ -11608,10 +11585,16 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
&& integer_pow2p (arg1)
&& TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_AND_EXPR
&& operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1),
- arg1, OEP_ONLY_CONST))
+ arg1, OEP_ONLY_CONST)
+ /* operand_equal_p compares just value, not precision, so e.g.
+ arg1 could be 8-bit -128 and be power of two, but BIT_AND_EXPR
+ second operand 32-bit -128, which is not a power of two (or vice
+ versa. */
+ && integer_pow2p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1)))
return pedantic_non_lvalue_loc (loc,
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg0, 0)));
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0,
+ 0)));
/* Disable the transformations below for vectors, since
fold_binary_op_with_conditional_arg may undo them immediately,
@@ -13780,7 +13763,7 @@ fold_read_from_constant_string (tree exp)
location_t loc = EXPR_LOCATION (exp);
if (TREE_CODE (exp) == INDIRECT_REF)
- string = string_constant (exp1, &index);
+ string = string_constant (exp1, &index, NULL, NULL);
else
{
tree low_bound = array_ref_low_bound (exp);
@@ -14577,23 +14560,20 @@ fold_build_pointer_plus_hwi_loc (location_t loc, tree ptr, HOST_WIDE_INT off)
/* Return a pointer P to a NUL-terminated string representing the sequence
of constant characters referred to by SRC (or a subsequence of such
characters within it if SRC is a reference to a string plus some
- constant offset). If STRLEN is non-null, store stgrlen(P) in *STRLEN.
- If STRSIZE is non-null, store in *STRSIZE the size of the array
- the string is stored in; in that case, even though P points to a NUL
- terminated string, SRC need not refer to one. This can happen when
- SRC refers to a constant character array initialized to all non-NUL
- values, as in the C declaration: char a[4] = "1234"; */
+ constant offset). If STRLEN is non-null, store the number of bytes
+ in the string constant including the terminating NUL char. *STRLEN is
+ typically strlen(P) + 1 in the absence of embedded NUL characters. */
const char *
-c_getstr (tree src, unsigned HOST_WIDE_INT *strlen /* = NULL */,
- unsigned HOST_WIDE_INT *strsize /* = NULL */)
+c_getstr (tree src, unsigned HOST_WIDE_INT *strlen /* = NULL */)
{
tree offset_node;
+ tree mem_size;
if (strlen)
*strlen = 0;
- src = string_constant (src, &offset_node);
+ src = string_constant (src, &offset_node, &mem_size, NULL);
if (src == 0)
return NULL;
@@ -14606,47 +14586,49 @@ c_getstr (tree src, unsigned HOST_WIDE_INT *strlen /* = NULL */,
offset = tree_to_uhwi (offset_node);
}
+ if (!tree_fits_uhwi_p (mem_size))
+ return NULL;
+
/* STRING_LENGTH is the size of the string literal, including any
embedded NULs. STRING_SIZE is the size of the array the string
literal is stored in. */
unsigned HOST_WIDE_INT string_length = TREE_STRING_LENGTH (src);
- unsigned HOST_WIDE_INT string_size = string_length;
- tree type = TREE_TYPE (src);
- if (tree size = TYPE_SIZE_UNIT (type))
- if (tree_fits_shwi_p (size))
- string_size = tree_to_uhwi (size);
+ unsigned HOST_WIDE_INT string_size = tree_to_uhwi (mem_size);
- if (strlen)
- {
- /* Compute and store the length of the substring at OFFSET.
- All offsets past the initial length refer to null strings. */
- if (offset <= string_length)
- *strlen = string_length - offset;
- else
- *strlen = 0;
- }
+ /* Ideally this would turn into a gcc_checking_assert over time. */
+ if (string_length > string_size)
+ string_length = string_size;
const char *string = TREE_STRING_POINTER (src);
+ /* Ideally this would turn into a gcc_checking_assert over time. */
+ if (string_length > string_size)
+ string_length = string_size;
+
if (string_length == 0
|| offset >= string_size)
return NULL;
- if (strsize)
+ if (strlen)
{
- /* Support even constant character arrays that aren't proper
- NUL-terminated strings. */
- *strsize = string_size;
+ /* Compute and store the length of the substring at OFFSET.
+ All offsets past the initial length refer to null strings. */
+ if (offset < string_length)
+ *strlen = string_length - offset;
+ else
+ *strlen = 1;
}
- else if (string[string_length - 1] != '\0')
+ else
{
- /* Support only properly NUL-terminated strings but handle
- consecutive strings within the same array, such as the six
- substrings in "1\0002\0003". */
- return NULL;
+ tree eltype = TREE_TYPE (TREE_TYPE (src));
+ /* Support only properly NUL-terminated single byte strings. */
+ if (tree_to_uhwi (TYPE_SIZE_UNIT (eltype)) != 1)
+ return NULL;
+ if (string[string_length - 1] != '\0')
+ return NULL;
}
- return offset <= string_length ? string + offset : "";
+ return offset < string_length ? string + offset : "";
}
/* Given a tree T, compute which bits in T may be nonzero. */
diff --git a/gcc/fold-const.h b/gcc/fold-const.h
index 1b9ccc0..ca6d47b 100644
--- a/gcc/fold-const.h
+++ b/gcc/fold-const.h
@@ -187,8 +187,7 @@ extern bool expr_not_equal_to (tree t, const wide_int &);
extern tree const_unop (enum tree_code, tree, tree);
extern tree const_binop (enum tree_code, tree, tree, tree);
extern bool negate_mathfn_p (combined_fn);
-extern const char *c_getstr (tree, unsigned HOST_WIDE_INT * = NULL,
- unsigned HOST_WIDE_INT * = NULL);
+extern const char *c_getstr (tree, unsigned HOST_WIDE_INT * = NULL);
extern wide_int tree_nonzero_bits (const_tree);
/* Return OFF converted to a pointer offset type suitable as offset for
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 9454102..5bc8856 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,394 @@
+2018-09-24 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/87397
+ * gfc_conv_procedure_call: Do not add clobber on INTENT(OUT)
+ for variables in an associate statement.
+
+2018-09-24 Bernhard Reuther-Fischer <aldot@gcc.gnu.org>
+ Cesar Philippidis <cesar@codesourcery.com>
+
+ * openmp.c (resolve_oacc_loop_blocks):
+
+2018-09-23 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/87397
+ * gfc_conv_procedure_call: Do not add clobber on INTENT(OUT)
+ for variables having the dimension attribute.
+
+2018-09-23 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * trans-expr.c (gfc_caf_get_image_index): Do array index
+ calculations in gfc_array_index_type.
+ * trans-intrinsic.c (conv_intrinsic_event_query): Likewise.
+ * trans-stmt.c (gfc_trans_lock_unlock): Likewise.
+ (gfc_trans_event_post_wait): Likewise.
+
+2018-09-23 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/87395
+ * gfc_conv_procedure_call: Reformat comments slightly. Do not add
+ clobber on INTENT(OUT) for saved variables.
+
+2018-09-22 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/41453
+ * trans.h (gfc_conv_expr_reference): Add optional argument
+ add_clobber to prototype.
+ (gfc_conv_procedure_call): Set add_clobber argument to
+ gfc_conv_procedure_reference to true for scalar, INTENT(OUT),
+ non-pointer, non-allocatable, non-dummy variables whose type
+ is neither BT_CHARACTER, BT_DERIVED or BT_CLASS, but only if
+ the procedure is not elemental.
+ * trans-expr.c (gfc_conv_procedure_reference): Add clobber
+ statement before call if add_clobber is set.
+
+2018-09-22 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/85603
+ * trans-array.c (gfc_alloc_allocatable_for_assignment): Test
+ the charlen backend_decl before using the VAR_P macro.
+
+2018-09-21 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/77325
+ * trans-array.c (gfc_alloc_allocatable_for_assignment): If the
+ rhs has a charlen expression, convert that and use it.
+ * trans-expr.c (gfc_trans_assignment_1): The rse.pre for the
+ assignment of deferred character array vars to a realocatable
+ lhs should not be added to the exterior block since vector
+ indices, for example, generate temporaries indexed within the
+ loop.
+
+2018-09-21 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/87359
+ * trans-stmt.c (gfc_trans_allocate): Don't deallocate alloc
+ components if must_finalize is set for expr3.
+
+2018-09-21 Andrew Stubbs <ams@codesourcery.com>
+ Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ * trans-expr.c (gfc_trans_structure_assign): Ensure that the first
+ argument of a call to _gfortran_caf_register is of size_type_node.
+ * trans-intrinsic.c (conv_intrinsic_event_query): Convert computed
+ index to a size_type_node type.
+ * trans-stmt.c (gfc_trans_event_post_wait): Likewise.
+
+2018-09-20 Allan Sandfeld Jensen <allan.jensen@qt.io>
+
+ * gfortranspec.c (lang_specific_driver): Handle -r like -nostdlib.
+
+2018-09-20 Janus Weil <janus@gcc.gnu.org>
+
+ * gfortran.h (gfc_str_startswith): New macro.
+ * decl.c (variable_decl, gfc_match_end): Use it.
+ * iresolve.c (is_trig_resolved): Ditto.
+ * module.c (load_omp_udrs, read_module): Ditto.
+ * options.c (gfc_handle_runtime_check_option): Ditto.
+ * primary.c (match_arg_list_function): Ditto.
+ * trans-decl.c (gfc_get_symbol_decl): Ditto.
+ * trans-expr.c (gfc_conv_procedure_call): Ditto.
+ * interface.c (dtio_op): Replace strncmp by strcmp.
+ * resolve.c (resolve_actual_arglist, resolve_function): Ditto.
+ * trans-expr.c (conv_arglist_function): Ditto.
+ * trans-intrinsic.c (gfc_conv_ieee_arithmetic_function): Replace macro
+ STARTS_WITH by gfc_str_startswith.
+
+2018-09-20 Cesar Philippidis <cesar@codesourcery.com>
+
+ * dump-parse-tree.c (show_omp_clauses): Add missing omp list_types
+ and reorder the switch cases to match the enum in gfortran.h.
+
+2018-09-19 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/84109
+ * trans-expr.c (gfc_trans_assignment_1): The rse.pre for the
+ assignment of deferred character intrinsic elemental function
+ results to a realocatable lhs must not be added to the exterior
+ block if they are array valued but must go to the loop body.
+
+2018-09-18 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/29550
+ * gfortran.h (gfc_expr): Add external_blas flag.
+ * frontend-passes.c (matrix_case): Add case A2TB2T.
+ (optimize_namespace): Handle flag_external_blas by
+ calling call_external_blas.
+ (get_array_inq_function): Add argument okind. If
+ it is nonzero, use it as the kind of argument
+ to be used.
+ (inline_limit_check): Remove m_case argument, add
+ limit argument instead. Remove assert about m_case.
+ Set the limit for inlining from the limit argument.
+ (matmul_lhs_realloc): Handle case A2TB2T.
+ (inline_matmul_assign): Handle inline limit for other cases with
+ two rank-two matrices. Remove no-op calls to inline_limit_check.
+ (call_external_blas): New function.
+ * trans-intrinsic.c (gfc_conv_intrinsic_funcall): Do not add
+ argument to external BLAS if external_blas is already set.
+
+2018-09-18 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/87239
+ * trans-expr.c (gfc_trans_assignment_1): The rse.pre for the
+ assignment of deferred character elemental function results to
+ a realocatable lhs must not be added to the exterior block but
+ must go to the loop body.
+
+2018-09-18 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/87336
+ * trans-array.c (gfc_get_array_span): Try to get the element
+ length of incomplete types. Return NULL_TREE otherwise.
+ (gfc_conv_expr_descriptor): Only set the 'span' field if the
+ above does not return NULL_TREE. Set 'span' field if possible
+ for all new descriptors.
+
+2018-09-17 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/64120
+ * trans-decl.c (gfc_get_symbol_decl): Flag allocatable, scalar
+ characters with a variable length expression for deferred init.
+ (gfc_trans_deferred_vars): Perform the assignment for these
+ symbols by calling gfc_conv_string_length.
+
+2018-09-17 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/85954
+ * resolve.c (resolve_assoc_var): If the target expression is a
+ deferred charlen dummy and the associate name shares the
+ charlen, generate a new one. Make sure that new charlens are in
+ the namespace list so that they get cleaned up.
+ * trans-array.c (gfc_is_reallocatable_lhs): Associate names are
+ not reallocatable.
+ * trans-decl.c (gfc_get_symbol_decl): Put deferred character
+ length dummy and result arrays on the deferred initialization
+ list so that the variable length arrays can be correctly dealt
+ with.
+ * trans-expr.c (gfc_conv_string_length): Return if 'expr' is
+ NULL rather than ICEing..
+
+2018-09-16 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/86484
+ PR fortran/84543
+ * match.c (gfc_match_assignment): For a polymorphic assignment,
+ make sure that the vtab for the rhs type is generated.
+
+2018-09-16 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/37802
+ * frontend-passes.c (B_ERROR): New macro for matmul bounds
+ checking error messages.
+ (C_ERROR): Likewise.
+ (inline_matmul_assign): Reorganize bounds checking, use B_ERROR
+ and C_ERROR macros.
+
+2018-09-13 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * trans-array.c (gfc_conv_array_initializer): Remove excess precision
+ from overlength string initializers.
+
+2018-09-12 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/87284
+ * trans-expr.c (gfc_trans_class_init_assign): Access to
+ to array elements of the dynamic type requires that the array
+ reference be added to the class expression and not the _data
+ component, unlike scalar expressions.
+
+2018-09-11 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/87172
+ * resolve.c (resolve_fl_derived): If a type has the 'use_assoc'
+ attribute, then it was declared in another module, so there should be
+ no error that it has not been declared.
+
+2018-09-11 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/87277
+ * expr.c (is_subref_array): Add the check of dimensionality for
+ class, dummy, pointer arrays.
+
+2018-09-11 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/86830
+ * expr.c (gfc_is_simply_contiguous): Handle type-bound procedure calls
+ with non-polymorphic objects.
+
+2018-09-10 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/85395
+ * decl.c (match_binding_attributes): Use correct default accessibility
+ for procedure pointer components.
+
+2018-09-03 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ * simplify.c (gfc_simplify_modulo): Re-arrange code to test whether
+ 'P' is zero and issue an error if it is.
+
+2018-08-31 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/86328
+ PR fortran/86760
+ * trans-array.c (gfc_conv_scalarized_array_ref): Do not fix
+ info->descriptor but pass it directly to gfc_build_array_ref.
+ (gfc_conv_array_ref): Likewise for se->expr.
+ * trans.c (gfc_build_array_ref): If 'decl' is a COMPONENT_REF
+ obtain the span field directly from it.
+
+2017-08-28 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/80477
+ * trans-expr.c (gfc_conv_procedure_call): Allocatable class
+ scalar results being passed to a derived type formal argument
+ are finalized if possible. Otherwise, rely on existing code for
+ deallocation. Make the deallocation of allocatable result
+ components conditional on finalization not taking place. Make
+ the freeing of data components after finalization conditional
+ on the data being NULL.
+ (gfc_trans_arrayfunc_assign): Change the gcc_assert to a
+ condition to return NULL_TREE.
+ (gfc_trans_assignment_1): If the assignment is class to class
+ and the rhs expression must be finalized but the assignment
+ is not marked as a polymorphic assignment, use the vptr copy
+ function instead of gfc_trans_scalar_assign.
+
+ PR fortran/86481
+ * trans-expr.c (gfc_conv_expr_reference): Do not add the post
+ block to the pre block if the expression is to be finalized.
+ * trans-stmt.c (gfc_trans_allocate): If the expr3 must be
+ finalized, load the post block into a finalization block and
+ add it right at the end of the allocation block.
+
+2018-08-27 David Malcolm <dmalcolm@redhat.com>
+
+ PR 87091
+ * error.c (gfc_format_decoder): Update for conversion of
+ show_caret_p to a tri-state.
+
+2018-08-25 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/86545
+ * resolve.c (resolve_transfer): Correctly determine typespec for
+ generic function calls, in order to throw a proper error.
+
+2018-08-24 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/86837
+ * frontend-passes.c (var_in_expr_callback): New function.
+ (var_in_expr): New function.
+ (traverse_io_block): Use var_in_expr instead of
+ gfc_check_dependency for checking if the variable depends on the
+ previous interators.
+
+2018-08-23 Janne Blomqvist <blomqvist.janne@gmail.com>
+
+ * trans-intrinsic.c (gfc_conv_intrinsic_minmaxval): Delete
+ HONOR_SIGNED_ZEROS checks.
+
+2018-08-23 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/86863
+ * resolve.c (resolve_typebound_call): If the TBP is not marked
+ as a subroutine, check the specific symbol.
+
+2018-08-22 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ * gfortran.texi: Mention that asynchronous I/O does
+ not work on systems which lack condition variables, such
+ as AIX.
+
+2018-08-22 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/86935
+ * match.c (gfc_match_associate): Improve diagnostics for the ASSOCIATE
+ statement.
+
+2018-08-22 Andrew Benson <abensonca@gmail.com>
+
+ * module.c (load_generic_interfaces): Move call to find_symbol()
+ so that only occurs if actually needed.
+
+2018-08-22 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/86888
+ * decl.c (gfc_match_data_decl): Allow allocatable components of
+ indirectly recursive type.
+ * resolve.c (resolve_component): Remove two errors messages ...
+ (resolve_fl_derived): ... and replace them by a new one.
+
+2018-08-21 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * trans-intrinsic.c (gfc_conv_intrinsic_minmax): Use
+ MAX_EXPR/MIN_EXPR unconditionally for real arguments.
+ * gfortran.texi (Compiler Characteristics): Document MAX/MIN
+ behavior wrt NaN.
+
+2018-08-21 Nicolas Koenig <koenigni@gcc.gnu.org>
+ Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/25829
+ * gfortran.texi: Add description of asynchronous I/O.
+ * trans-decl.c (gfc_finish_var_decl): Treat asynchronous variables
+ as volatile.
+ * trans-io.c (gfc_build_io_library_fndecls): Rename st_wait to
+ st_wait_async and change argument spec from ".X" to ".w".
+ (gfc_trans_wait): Pass ID argument via reference.
+
+2018-08-16 Nathan Sidwell <nathan@acm.org>
+
+ * cpp.c (dump_macro): Use cpp_user_macro_p.
+
+2018-08-14 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/86116
+ * interface.c (compare_type): Remove a CLASS/TYPE check.
+ (compare_type_characteristics): New function that behaves like the old
+ 'compare_type'.
+ (gfc_check_dummy_characteristics, gfc_check_result_characteristics):
+ Call 'compare_type_characteristics' instead of 'compare_type'.
+
+2018-08-12 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/66679
+ * trans-intrinsic.c (gfc_conv_intrinsic_transfer): Class array
+ elements are returned as references to the data element. Get
+ the class expression by stripping back the references. Use this
+ for the element size.
+
+2018-08-12 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/86906
+ * resolve.c (resolve_fl_variable_derived): Check if the derived
+ type is use associated before checking for the host association
+ error.
+
+2018-08-10 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/57160
+ * invoke.texi (frontend-optimize): Mention short-circuiting.
+ * options.c (gfc_post_options): Disable -ffrontend-optimize with -Og.
+ * resolve.c (resolve_operator): Warn about short-circuiting only with
+ -ffrontend-optimize.
+ * trans-expr.c (gfc_conv_expr_op): Use short-circuiting operators only
+ with -ffrontend-optimize. Without that flag, make sure that both
+ operands are evaluated.
+
+2018-08-08 Nathan Sidwell <nathan@acm.org>
+
+ * cpp.c (cb_file_change): Use linemap_included_from.
+
+2018-08-07 Cesar Philippidis <cesar@codesourcery.com>
+
+ * trans-stmt.h: Remove stale reference to trans-openacc.c.
+
+2018-08-04 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/45521
+ * interface.c (gfc_compare_interfaces): Apply additional
+ distinguishability criteria of F08 to operator interfaces.
+
2018-07-31 Andre Vieira <andre.simoesdiasvieira@arm.com>
Revert 'AsyncI/O patch committed'
@@ -819,7 +1210,7 @@
* trans-intrinsic.c (conv_intrinsic_kill, conv_intrinsic_kill_sub): new
functions.
(gfc_conv_intrinsic_function): Use conv_intrinsic_kill.
- (gfc_conv_intrinsic_subroutine): Use conv_intrinsic_kill_sub.
+ (gfc_conv_intrinsic_subroutine): Use conv_intrinsic_kill_sub.
* trans.h: Declare gfor_fndecl_kill and gfor_fndecl_kill_sub.
2018-03-11 Paul Thomas <pault@gcc.gnu.org>
@@ -1054,7 +1445,7 @@
* trans-stmt.c (gfc_trans_lock_unlock): Likewise.
(gfc_trans_event_post_wait): Likewise.
(gfc_trans_sync): Likewise.
- (gfc_trans_stop): Use size_t for character lengths, int for exit
+ (gfc_trans_stop): Use size_t for character lengths, int for exit
codes.
2018-02-20 Thomas Koenig <tkoenig@gcc.gnu.org>
@@ -1675,7 +2066,7 @@
(gfc_interpret_character): Use gfc_charlen_t.
* target-memory.h (gfc_encode_character): Modify prototype.
* trans-array.c (gfc_trans_array_ctor_element): Use existing type.
- (get_array_ctor_var_strlen): Use gfc_conv_mpz_to_tree_type.
+ (get_array_ctor_var_strlen): Use gfc_conv_mpz_to_tree_type.
(trans_array_constructor): Use existing type.
(get_array_charlen): Likewise.
* trans-const.c (gfc_conv_mpz_to_tree_type): New function.
diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c
index 82e890f..0b3de42 100644
--- a/gcc/fortran/cpp.c
+++ b/gcc/fortran/cpp.c
@@ -881,10 +881,7 @@ cb_file_change (cpp_reader * ARG_UNUSED (pfile), const line_map_ordinary *map)
{
/* Bring current file to correct line when entering a new file. */
if (map->reason == LC_ENTER)
- {
- const line_map_ordinary *from = INCLUDED_FROM (line_table, map);
- maybe_print_line (LAST_SOURCE_LINE_LOCATION (from));
- }
+ maybe_print_line (linemap_included_from (map));
if (map->reason == LC_ENTER)
flags = " 1";
else if (map->reason == LC_LEAVE)
@@ -993,7 +990,7 @@ cb_include (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line,
static int
dump_macro (cpp_reader *pfile, cpp_hashnode *node, void *v ATTRIBUTE_UNUSED)
{
- if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
+ if (cpp_user_macro_p (node))
{
fputs ("#define ", print.outf);
fputs ((const char *) cpp_macro_definition (pfile, node),
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 1384bc7..91a1f34 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -2529,7 +2529,7 @@ variable_decl (int elem)
}
/* %FILL components may not have initializers. */
- if (strncmp (name, "%FILL", 5) == 0 && gfc_match_eos () != MATCH_YES)
+ if (gfc_str_startswith (name, "%FILL") && gfc_match_eos () != MATCH_YES)
{
gfc_error ("%qs entity cannot have an initializer at %C", "%FILL");
m = MATCH_ERROR;
@@ -5864,8 +5864,7 @@ gfc_match_data_decl (void)
if (current_attr.pointer && gfc_comp_struct (gfc_current_state ()))
goto ok;
- if (current_attr.allocatable && gfc_current_state () == COMP_DERIVED
- && current_ts.u.derived == gfc_current_block ())
+ if (current_attr.allocatable && gfc_current_state () == COMP_DERIVED)
goto ok;
gfc_find_symbol (current_ts.u.derived->name,
@@ -7812,7 +7811,7 @@ gfc_match_end (gfc_statement *st)
{
case COMP_ASSOCIATE:
case COMP_BLOCK:
- if (!strncmp (block_name, "block@", strlen("block@")))
+ if (gfc_str_startswith (block_name, "block@"))
block_name = NULL;
break;
@@ -10571,7 +10570,8 @@ match_binding_attributes (gfc_typebound_proc* ba, bool generic, bool ppc)
done:
if (ba->access == ACCESS_UNKNOWN)
- ba->access = gfc_typebound_default_access;
+ ba->access = ppc ? gfc_current_block()->component_access
+ : gfc_typebound_default_access;
if (ppc && !seen_ptr)
{
diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index 2a28fa3..f1be5a6 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -1384,21 +1384,26 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses)
const char *type = NULL;
switch (list_type)
{
- case OMP_LIST_USE_DEVICE: type = "USE_DEVICE"; break;
- case OMP_LIST_DEVICE_RESIDENT: type = "USE_DEVICE"; break;
- case OMP_LIST_CACHE: type = ""; break;
case OMP_LIST_PRIVATE: type = "PRIVATE"; break;
case OMP_LIST_FIRSTPRIVATE: type = "FIRSTPRIVATE"; break;
case OMP_LIST_LASTPRIVATE: type = "LASTPRIVATE"; break;
+ case OMP_LIST_COPYPRIVATE: type = "COPYPRIVATE"; break;
case OMP_LIST_SHARED: type = "SHARED"; break;
case OMP_LIST_COPYIN: type = "COPYIN"; break;
case OMP_LIST_UNIFORM: type = "UNIFORM"; break;
case OMP_LIST_ALIGNED: type = "ALIGNED"; break;
case OMP_LIST_LINEAR: type = "LINEAR"; break;
+ case OMP_LIST_DEPEND: type = "DEPEND"; break;
+ case OMP_LIST_MAP: type = "MAP"; break;
+ case OMP_LIST_TO: type = "TO"; break;
+ case OMP_LIST_FROM: type = "FROM"; break;
case OMP_LIST_REDUCTION: type = "REDUCTION"; break;
+ case OMP_LIST_DEVICE_RESIDENT: type = "DEVICE_RESIDENT"; break;
+ case OMP_LIST_LINK: type = "LINK"; break;
+ case OMP_LIST_USE_DEVICE: type = "USE_DEVICE"; break;
+ case OMP_LIST_CACHE: type = "CACHE"; break;
case OMP_LIST_IS_DEVICE_PTR: type = "IS_DEVICE_PTR"; break;
case OMP_LIST_USE_DEVICE_PTR: type = "USE_DEVICE_PTR"; break;
- case OMP_LIST_DEPEND: type = "DEPEND"; break;
default:
gcc_unreachable ();
}
diff --git a/gcc/fortran/error.c b/gcc/fortran/error.c
index 7e882ba..b3b0138 100644
--- a/gcc/fortran/error.c
+++ b/gcc/fortran/error.c
@@ -953,7 +953,7 @@ gfc_format_decoder (pretty_printer *pp, text_info *text, const char *spec,
= linemap_position_for_loc_and_offset (line_table,
loc->lb->location,
offset);
- text->set_location (loc_num, src_loc, true);
+ text->set_location (loc_num, src_loc, SHOW_RANGE_WITH_CARET);
pp_string (pp, result[loc_num]);
return true;
}
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index c5bf822..3315bb8 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -1069,6 +1069,7 @@ is_subref_array (gfc_expr * e)
if (e->symtree->n.sym->ts.type == BT_CLASS
&& e->symtree->n.sym->attr.dummy
+ && CLASS_DATA (e->symtree->n.sym)->attr.dimension
&& CLASS_DATA (e->symtree->n.sym)->attr.class_pointer)
return true;
@@ -5385,16 +5386,13 @@ gfc_is_simply_contiguous (gfc_expr *expr, bool strict, bool permit_element)
return expr->value.function.esym->result->attr.contiguous;
else
{
- /* We have to jump through some hoops if this is a vtab entry. */
- gfc_symbol *s;
- gfc_ref *r, *rc;
-
- s = expr->symtree->n.sym;
- if (s->ts.type != BT_CLASS)
+ /* Type-bound procedures. */
+ gfc_symbol *s = expr->symtree->n.sym;
+ if (s->ts.type != BT_CLASS && s->ts.type != BT_DERIVED)
return false;
- rc = NULL;
- for (r = expr->ref; r; r = r->next)
+ gfc_ref *rc = NULL;
+ for (gfc_ref *r = expr->ref; r; r = r->next)
if (r->type == REF_COMPONENT)
rc = r;
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c
index f9dcddc..2a65b52 100644
--- a/gcc/fortran/frontend-passes.c
+++ b/gcc/fortran/frontend-passes.c
@@ -53,6 +53,7 @@ static gfc_code * create_do_loop (gfc_expr *, gfc_expr *, gfc_expr *,
char *vname=NULL);
static gfc_expr* check_conjg_transpose_variable (gfc_expr *, bool *,
bool *);
+static int call_external_blas (gfc_code **, int *, void *);
static bool has_dimen_vector_ref (gfc_expr *);
static int matmul_temp_args (gfc_code **, int *,void *data);
static int index_interchange (gfc_code **, int*, void *);
@@ -131,7 +132,7 @@ static int var_num = 1;
/* What sort of matrix we are dealing with when inlining MATMUL. */
-enum matrix_case { none=0, A2B2, A2B1, A1B2, A2B2T, A2TB2 };
+enum matrix_case { none=0, A2B2, A2B1, A1B2, A2B2T, A2TB2, A2TB2T };
/* Keep track of the number of expressions we have inserted so far
using create_var. */
@@ -1104,6 +1105,31 @@ convert_elseif (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
return 0;
}
+/* Callback function to var_in_expr - return true if expr1 and
+ expr2 are identical variables. */
+static int
+var_in_expr_callback (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
+ void *data)
+{
+ gfc_expr *expr1 = (gfc_expr *) data;
+ gfc_expr *expr2 = *e;
+
+ if (expr2->expr_type != EXPR_VARIABLE)
+ return 0;
+
+ return expr1->symtree->n.sym == expr2->symtree->n.sym;
+}
+
+/* Return true if expr1 is found in expr2. */
+
+static bool
+var_in_expr (gfc_expr *expr1, gfc_expr *expr2)
+{
+ gcc_assert (expr1->expr_type == EXPR_VARIABLE);
+
+ return gfc_expr_walker (&expr2, var_in_expr_callback, (void *) expr1);
+}
+
struct do_stack
{
struct do_stack *prev;
@@ -1256,9 +1282,9 @@ traverse_io_block (gfc_code *code, bool *has_reached, gfc_code *prev)
for (int j = i - 1; j < i; j++)
{
if (iters[j]
- && (gfc_check_dependency (var, iters[j]->start, true)
- || gfc_check_dependency (var, iters[j]->end, true)
- || gfc_check_dependency (var, iters[j]->step, true)))
+ && (var_in_expr (var, iters[j]->start)
+ || var_in_expr (var, iters[j]->end)
+ || var_in_expr (var, iters[j]->step)))
return false;
}
}
@@ -1403,7 +1429,7 @@ optimize_namespace (gfc_namespace *ns)
gfc_code_walker (&ns->code, convert_elseif, 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);
- if (flag_inline_matmul_limit != 0)
+ if (flag_inline_matmul_limit != 0 || flag_external_blas)
{
bool found;
do
@@ -1416,9 +1442,15 @@ optimize_namespace (gfc_namespace *ns)
gfc_code_walker (&ns->code, matmul_temp_args, dummy_expr_callback,
NULL);
- gfc_code_walker (&ns->code, inline_matmul_assign, dummy_expr_callback,
- NULL);
}
+
+ if (flag_external_blas)
+ gfc_code_walker (&ns->code, call_external_blas, dummy_expr_callback,
+ NULL);
+
+ if (flag_inline_matmul_limit != 0)
+ gfc_code_walker (&ns->code, inline_matmul_assign, dummy_expr_callback,
+ NULL);
}
if (flag_frontend_loop_interchange)
@@ -2913,7 +2945,7 @@ matmul_temp_args (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
dim is zero-based. */
static gfc_expr *
-get_array_inq_function (gfc_isym_id id, gfc_expr *e, int dim)
+get_array_inq_function (gfc_isym_id id, gfc_expr *e, int dim, int okind = 0)
{
gfc_expr *fcn;
gfc_expr *dim_arg, *kind;
@@ -2939,8 +2971,12 @@ get_array_inq_function (gfc_isym_id id, gfc_expr *e, int dim)
}
dim_arg = gfc_get_int_expr (gfc_default_integer_kind, &e->where, dim);
- kind = gfc_get_int_expr (gfc_default_integer_kind, &e->where,
- gfc_index_integer_kind);
+ if (okind != 0)
+ kind = gfc_get_int_expr (gfc_default_integer_kind, &e->where,
+ okind);
+ else
+ kind = gfc_get_int_expr (gfc_default_integer_kind, &e->where,
+ gfc_index_integer_kind);
ec = gfc_copy_expr (e);
@@ -3001,7 +3037,7 @@ get_operand (gfc_intrinsic_op op, gfc_expr *e1, gfc_expr *e2)
removed by DCE. Only called for rank-two matrices A and B. */
static gfc_code *
-inline_limit_check (gfc_expr *a, gfc_expr *b, enum matrix_case m_case)
+inline_limit_check (gfc_expr *a, gfc_expr *b, int limit)
{
gfc_expr *inline_limit;
gfc_code *if_1, *if_2, *else_2;
@@ -3009,14 +3045,11 @@ inline_limit_check (gfc_expr *a, gfc_expr *b, enum matrix_case m_case)
gfc_typespec ts;
gfc_expr *cond;
- gcc_assert (m_case == A2B2 || m_case == A2B2T || m_case == A2TB2);
-
/* Calculation is done in real to avoid integer overflow. */
inline_limit = gfc_get_constant_expr (BT_REAL, gfc_default_real_kind,
&a->where);
- mpfr_set_si (inline_limit->value.real, flag_inline_matmul_limit,
- GFC_RND_MODE);
+ mpfr_set_si (inline_limit->value.real, limit, GFC_RND_MODE);
mpfr_pow_ui (inline_limit->value.real, inline_limit->value.real, 3,
GFC_RND_MODE);
@@ -3210,6 +3243,22 @@ matmul_lhs_realloc (gfc_expr *c, gfc_expr *a, gfc_expr *b,
get_array_inq_function (GFC_ISYM_SIZE, b, 2));
break;
+ case A2TB2T:
+ /* This can only happen for BLAS, we do not handle that case in
+ inline mamtul. */
+ ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 2);
+ ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 1);
+
+ ne1 = build_logical_expr (INTRINSIC_NE,
+ get_array_inq_function (GFC_ISYM_SIZE, c, 1),
+ get_array_inq_function (GFC_ISYM_SIZE, a, 2));
+ ne2 = build_logical_expr (INTRINSIC_NE,
+ get_array_inq_function (GFC_ISYM_SIZE, c, 2),
+ get_array_inq_function (GFC_ISYM_SIZE, b, 1));
+
+ cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
+ break;
+
default:
gcc_unreachable();
@@ -3723,6 +3772,15 @@ check_conjg_transpose_variable (gfc_expr *e, bool *conjg, bool *transpose)
return NULL;
}
+/* Macros for unified error messages. */
+
+#define B_ERROR(n) _("Incorrect extent in argument B in MATMUL intrinsic in " \
+ "dimension " #n ": is %ld, should be %ld")
+
+#define C_ERROR(n) _("Array bound mismatch for dimension " #n " of array " \
+ "(%ld/%ld)")
+
+
/* Inline assignments of the form c = matmul(a,b).
Handle only the cases currently where b and c are rank-two arrays.
@@ -3768,6 +3826,7 @@ inline_matmul_assign (gfc_code **c, int *walk_subtrees,
gfc_code *if_limit = NULL;
gfc_code **next_code_point;
bool conjg_a, conjg_b, transpose_a, transpose_b;
+ bool realloc_c;
if (co->op != EXEC_ASSIGN)
return 0;
@@ -3911,9 +3970,11 @@ inline_matmul_assign (gfc_code **c, int *walk_subtrees,
/* Take care of the inline flag. If the limit check evaluates to a
constant, dead code elimination will eliminate the unneeded branch. */
- if (m_case == A2B2 && flag_inline_matmul_limit > 0)
+ if (flag_inline_matmul_limit > 0 && matrix_a->rank == 2
+ && matrix_b->rank == 2)
{
- if_limit = inline_limit_check (matrix_a, matrix_b, m_case);
+ if_limit = inline_limit_check (matrix_a, matrix_b,
+ flag_inline_matmul_limit);
/* Insert the original statement into the else branch. */
if_limit->block->block->next = co;
@@ -3933,169 +3994,140 @@ inline_matmul_assign (gfc_code **c, int *walk_subtrees,
assign_zero->expr1->no_bounds_check = 1;
assign_zero->expr2 = zero_e;
- /* Handle the reallocation, if needed. */
- if (flag_realloc_lhs && gfc_is_reallocatable_lhs (expr1))
- {
- gfc_code *lhs_alloc;
+ realloc_c = flag_realloc_lhs && gfc_is_reallocatable_lhs (expr1);
- /* Only need to check a single dimension for the A2B2 case for
- bounds checking, the rest will be allocated. Also check this
- for A2B1. */
+ if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
+ {
+ gfc_code *test;
+ gfc_expr *a2, *b1, *c1, *c2, *a1, *b2;
- if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
+ switch (m_case)
{
- gfc_code *test;
- if (m_case == A2B2 || m_case == A2B1)
- {
- gfc_expr *a2, *b1;
+ case A2B1:
- a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
- b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
- test = runtime_error_ne (b1, a2, "Dimension of array B incorrect "
- "in MATMUL intrinsic: Is %ld, should be %ld");
- *next_code_point = test;
- next_code_point = &test->next;
- }
- else if (m_case == A1B2)
- {
- gfc_expr *a1, *b1;
+ b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
+ a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
+ test = runtime_error_ne (b1, a2, B_ERROR(1));
+ *next_code_point = test;
+ next_code_point = &test->next;
+ if (!realloc_c)
+ {
+ c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
- b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
- test = runtime_error_ne (b1, a1, "Dimension of array B incorrect "
- "in MATMUL intrinsic: Is %ld, should be %ld");
+ test = runtime_error_ne (c1, a1, C_ERROR(1));
*next_code_point = test;
next_code_point = &test->next;
}
- }
-
- lhs_alloc = matmul_lhs_realloc (expr1, matrix_a, matrix_b, m_case);
+ break;
- *next_code_point = lhs_alloc;
- next_code_point = &lhs_alloc->next;
+ case A1B2:
- }
- else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
- {
- gfc_code *test;
- gfc_expr *a2, *b1, *c1, *c2, *a1, *b2;
-
- if (m_case == A2B2 || m_case == A2B1)
- {
- a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
- test = runtime_error_ne (b1, a2, "Dimension of array B incorrect "
- "in MATMUL intrinsic: Is %ld, should be %ld");
+ a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
+ test = runtime_error_ne (b1, a1, B_ERROR(1));
*next_code_point = test;
next_code_point = &test->next;
- c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
- a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
-
- if (m_case == A2B2)
- test = runtime_error_ne (c1, a1, "Incorrect extent in return array in "
- "MATMUL intrinsic for dimension 1: "
- "is %ld, should be %ld");
- else if (m_case == A2B1)
- test = runtime_error_ne (c1, a1, "Incorrect extent in return array in "
- "MATMUL intrinsic: "
- "is %ld, should be %ld");
+ if (!realloc_c)
+ {
+ c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
+ b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
+ test = runtime_error_ne (c1, b2, C_ERROR(1));
+ *next_code_point = test;
+ next_code_point = &test->next;
+ }
+ break;
+ case A2B2:
- *next_code_point = test;
- next_code_point = &test->next;
- }
- else if (m_case == A1B2)
- {
- a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
- test = runtime_error_ne (b1, a1, "Dimension of array B incorrect "
- "in MATMUL intrinsic: Is %ld, should be %ld");
+ a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
+ test = runtime_error_ne (b1, a2, B_ERROR(1));
*next_code_point = test;
next_code_point = &test->next;
- c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
- b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
+ if (!realloc_c)
+ {
+ c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
+ a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
+ test = runtime_error_ne (c1, a1, C_ERROR(1));
+ *next_code_point = test;
+ next_code_point = &test->next;
- test = runtime_error_ne (c1, b2, "Incorrect extent in return array in "
- "MATMUL intrinsic: "
- "is %ld, should be %ld");
+ c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
+ b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
+ test = runtime_error_ne (c2, b2, C_ERROR(2));
+ *next_code_point = test;
+ next_code_point = &test->next;
+ }
+ break;
- *next_code_point = test;
- next_code_point = &test->next;
- }
+ case A2B2T:
- if (m_case == A2B2)
- {
- c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
- test = runtime_error_ne (c2, b2, "Incorrect extent in return array in "
- "MATMUL intrinsic for dimension 2: is %ld, should be %ld");
-
+ a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
+ /* matrix_b is transposed, hence dimension 1 for the error message. */
+ test = runtime_error_ne (b2, a2, B_ERROR(1));
*next_code_point = test;
next_code_point = &test->next;
- }
- if (m_case == A2B2T)
- {
- c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
- a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
- test = runtime_error_ne (c1, a1, "Incorrect extent in return array in "
- "MATMUL intrinsic for dimension 1: "
- "is %ld, should be %ld");
+ if (!realloc_c)
+ {
+ c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
+ a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
+ test = runtime_error_ne (c1, a1, C_ERROR(1));
+ *next_code_point = test;
+ next_code_point = &test->next;
- *next_code_point = test;
- next_code_point = &test->next;
+ c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
+ b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
+ test = runtime_error_ne (c2, b1, C_ERROR(2));
+ *next_code_point = test;
+ next_code_point = &test->next;
+ }
+ break;
+
+ case A2TB2:
- c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
- test = runtime_error_ne (c2, b1, "Incorrect extent in return array in "
- "MATMUL intrinsic for dimension 2: "
- "is %ld, should be %ld");
+ a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
+ test = runtime_error_ne (b1, a1, B_ERROR(1));
*next_code_point = test;
next_code_point = &test->next;
- a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
- b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
+ if (!realloc_c)
+ {
+ c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
+ a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
+ test = runtime_error_ne (c1, a2, C_ERROR(1));
+ *next_code_point = test;
+ next_code_point = &test->next;
- test = runtime_error_ne (b2, a2, "Incorrect extent in argument B in "
- "MATMUL intrnisic for dimension 2: "
- "is %ld, should be %ld");
- *next_code_point = test;
- next_code_point = &test->next;
+ c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
+ b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
+ test = runtime_error_ne (c2, b2, C_ERROR(2));
+ *next_code_point = test;
+ next_code_point = &test->next;
+ }
+ break;
+ default:
+ gcc_unreachable ();
}
+ }
- if (m_case == A2TB2)
- {
- c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
- a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
-
- test = runtime_error_ne (c1, a2, "Incorrect extent in return array in "
- "MATMUL intrinsic for dimension 1: "
- "is %ld, should be %ld");
-
- *next_code_point = test;
- next_code_point = &test->next;
+ /* Handle the reallocation, if needed. */
- c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
- b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
- test = runtime_error_ne (c2, b2, "Incorrect extent in return array in "
- "MATMUL intrinsic for dimension 2: "
- "is %ld, should be %ld");
- *next_code_point = test;
- next_code_point = &test->next;
+ if (realloc_c)
+ {
+ gfc_code *lhs_alloc;
- a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
- b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
+ lhs_alloc = matmul_lhs_realloc (expr1, matrix_a, matrix_b, m_case);
- test = runtime_error_ne (b1, a1, "Incorrect extent in argument B in "
- "MATMUL intrnisic for dimension 2: "
- "is %ld, should be %ld");
- *next_code_point = test;
- next_code_point = &test->next;
+ *next_code_point = lhs_alloc;
+ next_code_point = &lhs_alloc->next;
- }
}
*next_code_point = assign_zero;
@@ -4112,7 +4144,6 @@ inline_matmul_assign (gfc_code **c, int *walk_subtrees,
switch (m_case)
{
case A2B2:
- inline_limit_check (matrix_a, matrix_b, m_case);
u1 = get_size_m1 (matrix_b, 2);
u2 = get_size_m1 (matrix_a, 2);
@@ -4145,7 +4176,6 @@ inline_matmul_assign (gfc_code **c, int *walk_subtrees,
break;
case A2B2T:
- inline_limit_check (matrix_a, matrix_b, m_case);
u1 = get_size_m1 (matrix_b, 1);
u2 = get_size_m1 (matrix_a, 2);
@@ -4178,7 +4208,6 @@ inline_matmul_assign (gfc_code **c, int *walk_subtrees,
break;
case A2TB2:
- inline_limit_check (matrix_a, matrix_b, m_case);
u1 = get_size_m1 (matrix_a, 2);
u2 = get_size_m1 (matrix_b, 2);
@@ -4305,6 +4334,405 @@ inline_matmul_assign (gfc_code **c, int *walk_subtrees,
return 0;
}
+/* Change matmul function calls in the form of
+
+ c = matmul(a,b)
+
+ to the corresponding call to a BLAS routine, if applicable. */
+
+static int
+call_external_blas (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
+ void *data ATTRIBUTE_UNUSED)
+{
+ gfc_code *co, *co_next;
+ gfc_expr *expr1, *expr2;
+ gfc_expr *matrix_a, *matrix_b;
+ gfc_code *if_limit = NULL;
+ gfc_actual_arglist *a, *b;
+ bool conjg_a, conjg_b, transpose_a, transpose_b;
+ gfc_code *call;
+ const char *blas_name;
+ const char *transa, *transb;
+ gfc_expr *c1, *c2, *b1;
+ gfc_actual_arglist *actual, *next;
+ bt type;
+ int kind;
+ enum matrix_case m_case;
+ bool realloc_c;
+ gfc_code **next_code_point;
+
+ /* Many of the tests for inline matmul also apply here. */
+
+ co = *c;
+
+ if (co->op != EXEC_ASSIGN)
+ return 0;
+
+ if (in_where || in_assoc_list)
+ return 0;
+
+ /* The BLOCKS generated for the temporary variables and FORALL don't
+ mix. */
+ if (forall_level > 0)
+ return 0;
+
+ /* For now don't do anything in OpenMP workshare, it confuses
+ its translation, which expects only the allowed statements in there. */
+
+ if (in_omp_workshare)
+ return 0;
+
+ expr1 = co->expr1;
+ expr2 = co->expr2;
+ if (expr2->expr_type != EXPR_FUNCTION
+ || expr2->value.function.isym == NULL
+ || expr2->value.function.isym->id != GFC_ISYM_MATMUL)
+ return 0;
+
+ type = expr2->ts.type;
+ kind = expr2->ts.kind;
+
+ /* Guard against recursion. */
+
+ if (expr2->external_blas)
+ return 0;
+
+ if (type != expr1->ts.type || kind != expr1->ts.kind)
+ return 0;
+
+ if (type == BT_REAL)
+ {
+ if (kind == 4)
+ blas_name = "sgemm";
+ else if (kind == 8)
+ blas_name = "dgemm";
+ else
+ return 0;
+ }
+ else if (type == BT_COMPLEX)
+ {
+ if (kind == 4)
+ blas_name = "cgemm";
+ else if (kind == 8)
+ blas_name = "zgemm";
+ else
+ return 0;
+ }
+ else
+ return 0;
+
+ a = expr2->value.function.actual;
+ if (a->expr->rank != 2)
+ return 0;
+
+ b = a->next;
+ if (b->expr->rank != 2)
+ return 0;
+
+ matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a);
+ if (matrix_a == NULL)
+ return 0;
+
+ if (transpose_a)
+ {
+ if (conjg_a)
+ transa = "C";
+ else
+ transa = "T";
+ }
+ else
+ transa = "N";
+
+ matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b);
+ if (matrix_b == NULL)
+ return 0;
+
+ if (transpose_b)
+ {
+ if (conjg_b)
+ transb = "C";
+ else
+ transb = "T";
+ }
+ else
+ transb = "N";
+
+ if (transpose_a)
+ {
+ if (transpose_b)
+ m_case = A2TB2T;
+ else
+ m_case = A2TB2;
+ }
+ else
+ {
+ if (transpose_b)
+ m_case = A2B2T;
+ else
+ m_case = A2B2;
+ }
+
+ current_code = c;
+ inserted_block = NULL;
+ changed_statement = NULL;
+
+ expr2->external_blas = 1;
+
+ /* We do not handle data dependencies yet. */
+ if (gfc_check_dependency (expr1, matrix_a, true)
+ || gfc_check_dependency (expr1, matrix_b, true))
+ return 0;
+
+ /* Generate the if statement and hang it into the tree. */
+ if_limit = inline_limit_check (matrix_a, matrix_b, flag_blas_matmul_limit);
+ co_next = co->next;
+ (*current_code) = if_limit;
+ co->next = NULL;
+ if_limit->block->next = co;
+
+ call = XCNEW (gfc_code);
+ call->loc = co->loc;
+
+ /* Bounds checking - a bit simpler than for inlining since we only
+ have to take care of two-dimensional arrays here. */
+
+ realloc_c = flag_realloc_lhs && gfc_is_reallocatable_lhs (expr1);
+ next_code_point = &(if_limit->block->block->next);
+
+ if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
+ {
+ gfc_code *test;
+ // gfc_expr *a2, *b1, *c1, *c2, *a1, *b2;
+ gfc_expr *c1, *a1, *c2, *b2, *a2;
+ switch (m_case)
+ {
+ case A2B2:
+ b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
+ a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
+ test = runtime_error_ne (b1, a2, B_ERROR(1));
+ *next_code_point = test;
+ next_code_point = &test->next;
+
+ if (!realloc_c)
+ {
+ c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
+ a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
+ test = runtime_error_ne (c1, a1, C_ERROR(1));
+ *next_code_point = test;
+ next_code_point = &test->next;
+
+ c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
+ b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
+ test = runtime_error_ne (c2, b2, C_ERROR(2));
+ *next_code_point = test;
+ next_code_point = &test->next;
+ }
+ break;
+
+ case A2B2T:
+
+ b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
+ a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
+ /* matrix_b is transposed, hence dimension 1 for the error message. */
+ test = runtime_error_ne (b2, a2, B_ERROR(1));
+ *next_code_point = test;
+ next_code_point = &test->next;
+
+ if (!realloc_c)
+ {
+ c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
+ a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
+ test = runtime_error_ne (c1, a1, C_ERROR(1));
+ *next_code_point = test;
+ next_code_point = &test->next;
+
+ c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
+ b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
+ test = runtime_error_ne (c2, b1, C_ERROR(2));
+ *next_code_point = test;
+ next_code_point = &test->next;
+ }
+ break;
+
+ case A2TB2:
+
+ b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
+ a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
+ test = runtime_error_ne (b1, a1, B_ERROR(1));
+ *next_code_point = test;
+ next_code_point = &test->next;
+
+ if (!realloc_c)
+ {
+ c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
+ a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
+ test = runtime_error_ne (c1, a2, C_ERROR(1));
+ *next_code_point = test;
+ next_code_point = &test->next;
+
+ c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
+ b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
+ test = runtime_error_ne (c2, b2, C_ERROR(2));
+ *next_code_point = test;
+ next_code_point = &test->next;
+ }
+ break;
+
+ case A2TB2T:
+ b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
+ a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
+ test = runtime_error_ne (b2, a1, B_ERROR(1));
+ *next_code_point = test;
+ next_code_point = &test->next;
+
+ if (!realloc_c)
+ {
+ c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
+ a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
+ test = runtime_error_ne (c1, a2, C_ERROR(1));
+ *next_code_point = test;
+ next_code_point = &test->next;
+
+ c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
+ b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
+ test = runtime_error_ne (c2, b1, C_ERROR(2));
+ *next_code_point = test;
+ next_code_point = &test->next;
+ }
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ /* Handle the reallocation, if needed. */
+
+ if (realloc_c)
+ {
+ gfc_code *lhs_alloc;
+
+ lhs_alloc = matmul_lhs_realloc (expr1, matrix_a, matrix_b, m_case);
+ *next_code_point = lhs_alloc;
+ next_code_point = &lhs_alloc->next;
+ }
+
+ *next_code_point = call;
+ if_limit->next = co_next;
+
+ /* Set up the BLAS call. */
+
+ call->op = EXEC_CALL;
+
+ gfc_get_sym_tree (blas_name, current_ns, &(call->symtree), true);
+ call->symtree->n.sym->attr.subroutine = 1;
+ call->symtree->n.sym->attr.procedure = 1;
+ call->symtree->n.sym->attr.flavor = FL_PROCEDURE;
+ call->resolved_sym = call->symtree->n.sym;
+
+ /* Argument TRANSA. */
+ next = gfc_get_actual_arglist ();
+ next->expr = gfc_get_character_expr (gfc_default_character_kind, &co->loc,
+ transa, 1);
+
+ call->ext.actual = next;
+
+ /* Argument TRANSB. */
+ actual = next;
+ next = gfc_get_actual_arglist ();
+ next->expr = gfc_get_character_expr (gfc_default_character_kind, &co->loc,
+ transb, 1);
+ actual->next = next;
+
+ c1 = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (a->expr), 1,
+ gfc_integer_4_kind);
+ c2 = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (b->expr), 2,
+ gfc_integer_4_kind);
+
+ b1 = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (b->expr), 1,
+ gfc_integer_4_kind);
+
+ /* Argument M. */
+ actual = next;
+ next = gfc_get_actual_arglist ();
+ next->expr = c1;
+ actual->next = next;
+
+ /* Argument N. */
+ actual = next;
+ next = gfc_get_actual_arglist ();
+ next->expr = c2;
+ actual->next = next;
+
+ /* Argument K. */
+ actual = next;
+ next = gfc_get_actual_arglist ();
+ next->expr = b1;
+ actual->next = next;
+
+ /* Argument ALPHA - set to one. */
+ actual = next;
+ next = gfc_get_actual_arglist ();
+ next->expr = gfc_get_constant_expr (type, kind, &co->loc);
+ if (type == BT_REAL)
+ mpfr_set_ui (next->expr->value.real, 1, GFC_RND_MODE);
+ else
+ mpc_set_ui (next->expr->value.complex, 1, GFC_MPC_RND_MODE);
+ actual->next = next;
+
+ /* Argument A. */
+ actual = next;
+ next = gfc_get_actual_arglist ();
+ next->expr = gfc_copy_expr (matrix_a);
+ actual->next = next;
+
+ /* Argument LDA. */
+ actual = next;
+ next = gfc_get_actual_arglist ();
+ next->expr = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (matrix_a),
+ 1, gfc_integer_4_kind);
+ actual->next = next;
+
+ /* Argument B. */
+ actual = next;
+ next = gfc_get_actual_arglist ();
+ next->expr = gfc_copy_expr (matrix_b);
+ actual->next = next;
+
+ /* Argument LDB. */
+ actual = next;
+ next = gfc_get_actual_arglist ();
+ next->expr = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (matrix_b),
+ 1, gfc_integer_4_kind);
+ actual->next = next;
+
+ /* Argument BETA - set to zero. */
+ actual = next;
+ next = gfc_get_actual_arglist ();
+ next->expr = gfc_get_constant_expr (type, kind, &co->loc);
+ if (type == BT_REAL)
+ mpfr_set_ui (next->expr->value.real, 0, GFC_RND_MODE);
+ else
+ mpc_set_ui (next->expr->value.complex, 0, GFC_MPC_RND_MODE);
+ actual->next = next;
+
+ /* Argument C. */
+
+ actual = next;
+ next = gfc_get_actual_arglist ();
+ next->expr = gfc_copy_expr (expr1);
+ actual->next = next;
+
+ /* Argument LDC. */
+ actual = next;
+ next = gfc_get_actual_arglist ();
+ next->expr = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (expr1),
+ 1, gfc_integer_4_kind);
+ actual->next = next;
+
+ return 0;
+}
+
/* Code for index interchange for loops which are grouped together in DO
CONCURRENT or FORALL statements. This is currently only applied if the
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 04b0024..b0518e2 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2143,6 +2143,11 @@ typedef struct gfc_expr
unsigned int no_bounds_check : 1;
+ /* Set this if a matmul expression has already been evaluated for conversion
+ to a BLAS call. */
+
+ unsigned int external_blas : 1;
+
/* If an expression comes from a Hollerith constant or compile-time
evaluation of a transfer statement, it may have a prescribed target-
memory representation, and these cannot always be backformed from
@@ -3305,6 +3310,9 @@ bool gfc_is_compile_time_shape (gfc_array_spec *);
bool gfc_ref_dimen_size (gfc_array_ref *, int dimen, mpz_t *, mpz_t *);
+#define gfc_str_startswith(str, pref) \
+ (strncmp ((str), (pref), strlen (pref)) == 0)
+
/* interface.c -- FIXME: some of these should be in symbol.c */
void gfc_free_interface (gfc_interface *);
bool gfc_compare_derived_types (gfc_symbol *, gfc_symbol *);
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index d6bb7aa..3093404 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -879,8 +879,7 @@ than @code{(/.../)}. Type-specification for array constructors like
@item Extensions to the specification and initialization expressions,
including the support for intrinsics with real and complex arguments.
-@item Support for the asynchronous input/output syntax; however, the
-data transfer is currently always synchronously performed.
+@item Support for the asynchronous input/output.
@item
@cindex @code{FLUSH} statement
@@ -1178,11 +1177,13 @@ might in some way or another become visible to the programmer.
* KIND Type Parameters::
* Internal representation of LOGICAL variables::
* Evaluation of logical expressions::
+* MAX and MIN intrinsics with REAL NaN arguments::
* Thread-safety of the runtime library::
* Data consistency and durability::
* Files opened without an explicit ACTION= specifier::
* File operations on symbolic links::
* File format of unformatted sequential files::
+* Asynchronous I/O::
@end menu
@@ -1265,6 +1266,21 @@ program flow and subsequent results, GNU Fortran throws warnings for such
situations with the @option{-Wfunction-elimination} flag.
+@node MAX and MIN intrinsics with REAL NaN arguments
+@section MAX and MIN intrinsics with REAL NaN arguments
+@cindex MAX, MIN, NaN
+
+The Fortran standard does not specify what the result of the
+@code{MAX} and @code{MIN} intrinsics are if one of the arguments is a
+@code{NaN}. Accordingly, the GNU Fortran compiler does not specify
+that either, as this allows for faster and more compact code to be
+generated. If the programmer wishes to take some specific action in
+case one of the arguments is a @code{NaN}, it is necessary to
+explicitly test the arguments before calling @code{MAX} or @code{MIN},
+e.g. with the @code{IEEE_IS_NAN} function from the intrinsic module
+@code{IEEE_ARITHMETIC}.
+
+
@node Thread-safety of the runtime library
@section Thread-safety of the runtime library
@cindex thread-safety, threads
@@ -1486,6 +1502,21 @@ program main
end program main
@end smallexample
+@node Asynchronous I/O
+@section Asynchronous I/O
+@cindex input/output, asynchronous
+@cindex asynchronous I/O
+
+Asynchronous I/O is supported if the program is linked against the
+POSIX thread library. If that is not the case, all I/O is performed
+as synchronous. On systems which do not support pthread condition
+variables, such as AIX, I/O is also performed as synchronous.
+
+On some systems, such as Darwin or Solaris, the POSIX thread library
+is always linked in, so asynchronous I/O is always performed. On other
+sytems, such as Linux, it is necessary to specify @option{-pthread},
+@option{-lpthread} or @option{-fopenmp} during the linking step.
+
@c ---------------------------------------------------------------------
@c Extensions
@c ---------------------------------------------------------------------
diff --git a/gcc/fortran/gfortranspec.c b/gcc/fortran/gfortranspec.c
index 4ba3a8d..7aa2dd7 100644
--- a/gcc/fortran/gfortranspec.c
+++ b/gcc/fortran/gfortranspec.c
@@ -243,6 +243,7 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
case OPT_nostdlib:
case OPT_nodefaultlibs:
case OPT_c:
+ case OPT_r:
case OPT_S:
case OPT_fsyntax_only:
case OPT_E:
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index 9da654e6..ff6b2bb 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -122,9 +122,9 @@ fold_unary_intrinsic (gfc_intrinsic_op op)
static gfc_intrinsic_op
dtio_op (char* mode)
{
- if (strncmp (mode, "formatted", 9) == 0)
+ if (strcmp (mode, "formatted") == 0)
return INTRINSIC_FORMATTED;
- if (strncmp (mode, "unformatted", 9) == 0)
+ if (strcmp (mode, "unformatted") == 0)
return INTRINSIC_UNFORMATTED;
return INTRINSIC_NONE;
}
@@ -735,13 +735,20 @@ compare_type (gfc_symbol *s1, gfc_symbol *s2)
if (s2->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK))
return true;
+ return gfc_compare_types (&s1->ts, &s2->ts) || s2->ts.type == BT_ASSUMED;
+}
+
+
+static bool
+compare_type_characteristics (gfc_symbol *s1, gfc_symbol *s2)
+{
/* TYPE and CLASS of the same declared type are type compatible,
but have different characteristics. */
if ((s1->ts.type == BT_CLASS && s2->ts.type == BT_DERIVED)
|| (s1->ts.type == BT_DERIVED && s2->ts.type == BT_CLASS))
return false;
- return gfc_compare_types (&s1->ts, &s2->ts) || s2->ts.type == BT_ASSUMED;
+ return compare_type (s1, s2);
}
@@ -1309,7 +1316,8 @@ gfc_check_dummy_characteristics (gfc_symbol *s1, gfc_symbol *s2,
/* Check type and rank. */
if (type_must_agree)
{
- if (!compare_type (s1, s2) || !compare_type (s2, s1))
+ if (!compare_type_characteristics (s1, s2)
+ || !compare_type_characteristics (s2, s1))
{
snprintf (errmsg, err_len, "Type mismatch in argument '%s' (%s/%s)",
s1->name, gfc_typename (&s1->ts), gfc_typename (&s2->ts));
@@ -1528,7 +1536,7 @@ gfc_check_result_characteristics (gfc_symbol *s1, gfc_symbol *s2,
return true;
/* Check type and rank. */
- if (!compare_type (r1, r2))
+ if (!compare_type_characteristics (r1, r2))
{
snprintf (errmsg, err_len, "Type mismatch in function result (%s/%s)",
gfc_typename (&r1->ts), gfc_typename (&r2->ts));
@@ -1776,7 +1784,7 @@ gfc_compare_interfaces (gfc_symbol *s1, gfc_symbol *s2, const char *name2,
}
else
{
- /* Only check type and rank. */
+ /* Operators: Only check type and rank of arguments. */
if (!compare_type (f2->sym, f1->sym))
{
if (errmsg != NULL)
@@ -1794,6 +1802,15 @@ gfc_compare_interfaces (gfc_symbol *s1, gfc_symbol *s2, const char *name2,
symbol_rank (f2->sym));
return false;
}
+ if ((gfc_option.allow_std & GFC_STD_F2008)
+ && (compare_ptr_alloc(f1->sym, f2->sym)
+ || compare_ptr_alloc(f2->sym, f1->sym)))
+ {
+ if (errmsg != NULL)
+ snprintf (errmsg, err_len, "Mismatching POINTER/ALLOCATABLE "
+ "attribute in argument '%s' ", f1->sym->name);
+ return false;
+ }
}
}
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index 093864b..ee84a0b 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -1793,13 +1793,17 @@ if @option{-ffrontend-optimize} is in effect.
@opindex @code{frontend-optimize}
@cindex Front-end optimization
This option performs front-end optimization, based on manipulating
-parts the Fortran parse tree. Enabled by default by any @option{-O}
-option. Optimizations enabled by this option include inlining calls
-to @code{MATMUL}, elimination of identical function calls within
-expressions, removing unnecessary calls to @code{TRIM} in comparisons
-and assignments and replacing @code{TRIM(a)} with
-@code{a(1:LEN_TRIM(a))}. It can be deselected by specifying
-@option{-fno-frontend-optimize}.
+parts the Fortran parse tree. Enabled by default by any @option{-O} option
+except @option{-O0} and @option{-Og}. Optimizations enabled by this option
+include:
+@itemize @bullet
+@item inlining calls to @code{MATMUL},
+@item elimination of identical function calls within expressions,
+@item removing unnecessary calls to @code{TRIM} in comparisons and assignments,
+@item replacing @code{TRIM(a)} with @code{a(1:LEN_TRIM(a))} and
+@item short-circuiting of logical operators (@code{.AND.} and @code{.OR.}).
+@end itemize
+It can be deselected by specifying @option{-fno-frontend-optimize}.
@item -ffrontend-loop-interchange
@opindex @code{frontend-loop-interchange}
diff --git a/gcc/fortran/iresolve.c b/gcc/fortran/iresolve.c
index 2eb8f7c..f2d6bba 100644
--- a/gcc/fortran/iresolve.c
+++ b/gcc/fortran/iresolve.c
@@ -698,7 +698,7 @@ is_trig_resolved (gfc_expr *f)
/* We know we've already resolved the function if we see the lib call
starting with '__'. */
return (f->value.function.name != NULL
- && strncmp ("__", f->value.function.name, 2) == 0);
+ && gfc_str_startswith (f->value.function.name, "__"));
}
/* Return a shallow copy of the function expression f. The original expression
diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c
index 1ab0e0f..badd3c4 100644
--- a/gcc/fortran/match.c
+++ b/gcc/fortran/match.c
@@ -1366,6 +1366,9 @@ gfc_match_assignment (void)
gfc_check_do_variable (lvalue->symtree);
+ if (lvalue->ts.type == BT_CLASS)
+ gfc_find_vtab (&rvalue->ts);
+
return MATCH_YES;
}
@@ -1889,17 +1892,21 @@ gfc_match_associate (void)
gfc_association_list* a;
/* Match the next association. */
- if (gfc_match (" %n => %e", newAssoc->name, &newAssoc->target)
- != MATCH_YES)
+ if (gfc_match (" %n =>", newAssoc->name) != MATCH_YES)
+ {
+ gfc_error ("Expected association at %C");
+ goto assocListError;
+ }
+
+ if (gfc_match (" %e", &newAssoc->target) != MATCH_YES)
{
/* Have another go, allowing for procedure pointer selectors. */
gfc_matching_procptr_assignment = 1;
- if (gfc_match (" %n => %e", newAssoc->name, &newAssoc->target)
- != MATCH_YES)
- {
- gfc_error ("Expected association at %C");
- goto assocListError;
- }
+ if (gfc_match (" %e", &newAssoc->target) != MATCH_YES)
+ {
+ gfc_error ("Invalid association target at %C");
+ goto assocListError;
+ }
gfc_matching_procptr_assignment = 0;
}
newAssoc->where = gfc_current_locus;
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index 196da9c..7b8e863 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -4559,9 +4559,6 @@ load_generic_interfaces (void)
/* Decide if we need to load this one or not. */
p = find_use_name_n (name, &i, false);
- st = find_symbol (gfc_current_ns->sym_root,
- name, module_name, 1);
-
if (!p || gfc_find_symbol (p, NULL, 0, &sym))
{
/* Skip the specific names for these cases. */
@@ -4570,6 +4567,9 @@ load_generic_interfaces (void)
continue;
}
+ st = find_symbol (gfc_current_ns->sym_root,
+ name, module_name, 1);
+
/* If the symbol exists already and is being USEd without being
in an ONLY clause, do not load a new symtree(11.3.2). */
if (!only_flag && st)
@@ -4791,7 +4791,7 @@ load_omp_udrs (void)
mio_pool_string (&name);
gfc_clear_ts (&ts);
mio_typespec (&ts);
- if (strncmp (name, "operator ", sizeof ("operator ") - 1) == 0)
+ if (gfc_str_startswith (name, "operator "))
{
const char *p = name + sizeof ("operator ") - 1;
if (strcmp (p, "+") == 0)
@@ -5233,8 +5233,8 @@ read_module (void)
/* Exception: Always import vtabs & vtypes. */
if (p == NULL && name[0] == '_'
- && (strncmp (name, "__vtab_", 5) == 0
- || strncmp (name, "__vtype_", 6) == 0))
+ && (gfc_str_startswith (name, "__vtab_")
+ || gfc_str_startswith (name, "__vtype_")))
p = name;
/* Skip symtree nodes not in an ONLY clause, unless there
@@ -5319,8 +5319,8 @@ read_module (void)
sym->attr.use_rename = 1;
if (name[0] != '_'
- || (strncmp (name, "__vtab_", 5) != 0
- && strncmp (name, "__vtype_", 6) != 0))
+ || (!gfc_str_startswith (name, "__vtab_")
+ && !gfc_str_startswith (name, "__vtype_")))
sym->attr.use_only = only_flag;
/* Store the symtree pointing to this symbol. */
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index 94a7f7e..bd83733 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -5853,7 +5853,7 @@ resolve_oacc_loop_blocks (gfc_code *code)
&code->loc);
if (c->code->ext.omp_clauses->vector)
gfc_error ("Loop parallelized across gangs is not allowed "
- "inside loop parallelized across workers at %L",
+ "inside loop parallelized across vectors at %L",
&code->loc);
}
if (code->ext.omp_clauses->worker)
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index af93751..73f5389 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -417,7 +417,7 @@ gfc_post_options (const char **pfilename)
specified it directly. */
if (flag_frontend_optimize == -1)
- flag_frontend_optimize = optimize;
+ flag_frontend_optimize = optimize && !optimize_debug;
/* Same for front end loop interchange. */
@@ -565,7 +565,7 @@ gfc_handle_runtime_check_option (const char *arg)
result = 1;
break;
}
- else if (optname[n] && pos > 3 && strncmp ("no-", arg, 3) == 0
+ else if (optname[n] && pos > 3 && gfc_str_startswith (arg, "no-")
&& strncmp (optname[n], arg+3, pos-3) == 0)
{
gfc_option.rtcheck &= ~optmask[n];
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index 094f210..6f45afa 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -1713,21 +1713,21 @@ match_arg_list_function (gfc_actual_arglist *result)
switch (name[0])
{
case 'l':
- if (strncmp (name, "loc", 3) == 0)
+ if (gfc_str_startswith (name, "loc"))
{
result->name = "%LOC";
break;
}
/* FALLTHRU */
case 'r':
- if (strncmp (name, "ref", 3) == 0)
+ if (gfc_str_startswith (name, "ref"))
{
result->name = "%REF";
break;
}
/* FALLTHRU */
case 'v':
- if (strncmp (name, "val", 3) == 0)
+ if (gfc_str_startswith (name, "val"))
{
result->name = "%VAL";
break;
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 3035e02..a2beb7f 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -2061,7 +2061,7 @@ resolve_actual_arglist (gfc_actual_arglist *arg, procedure_type ptype,
nothing to do for %REF. */
if (arg->name && arg->name[0] == '%')
{
- if (strncmp ("%VAL", arg->name, 4) == 0)
+ if (strcmp ("%VAL", arg->name) == 0)
{
if (e->ts.type == BT_CHARACTER || e->ts.type == BT_DERIVED)
{
@@ -2093,7 +2093,7 @@ resolve_actual_arglist (gfc_actual_arglist *arg, procedure_type ptype,
}
/* Statement functions have already been excluded above. */
- else if (strncmp ("%LOC", arg->name, 4) == 0
+ else if (strcmp ("%LOC", arg->name) == 0
&& e->ts.type == BT_PROCEDURE)
{
if (e->symtree->n.sym->attr.proc == PROC_INTERNAL)
@@ -3265,7 +3265,7 @@ resolve_function (gfc_expr *expr)
if (arg->next->expr->expr_type != EXPR_CONSTANT)
break;
- if (arg->next->name && strncmp (arg->next->name, "kind", 4) == 0)
+ if (arg->next->name && strcmp (arg->next->name, "kind") == 0)
break;
if ((int)mpz_get_si (arg->next->expr->value.integer)
@@ -3982,7 +3982,8 @@ resolve_operator (gfc_expr *e)
else if (op2->ts.kind < e->ts.kind)
gfc_convert_type (op2, &e->ts, 2);
- if (e->value.op.op == INTRINSIC_AND || e->value.op.op == INTRINSIC_OR)
+ if (flag_frontend_optimize &&
+ (e->value.op.op == INTRINSIC_AND || e->value.op.op == INTRINSIC_OR))
{
/* Warn about short-circuiting
with impure function as second operand. */
@@ -6265,9 +6266,17 @@ resolve_typebound_call (gfc_code* c, const char **name, bool *overridable)
/* Check that's really a SUBROUTINE. */
if (!c->expr1->value.compcall.tbp->subroutine)
{
- gfc_error ("%qs at %L should be a SUBROUTINE",
- c->expr1->value.compcall.name, &c->loc);
- return false;
+ if (!c->expr1->value.compcall.tbp->is_generic
+ && c->expr1->value.compcall.tbp->u.specific
+ && c->expr1->value.compcall.tbp->u.specific->n.sym
+ && c->expr1->value.compcall.tbp->u.specific->n.sym->attr.subroutine)
+ c->expr1->value.compcall.tbp->subroutine = 1;
+ else
+ {
+ gfc_error ("%qs at %L should be a SUBROUTINE",
+ c->expr1->value.compcall.name, &c->loc);
+ return false;
+ }
}
if (!check_typebound_baseobject (c->expr1))
@@ -8735,6 +8744,14 @@ resolve_assoc_var (gfc_symbol* sym, bool resolve_target)
if (!sym->ts.u.cl)
sym->ts.u.cl = target->ts.u.cl;
+ if (sym->ts.deferred && target->expr_type == EXPR_VARIABLE
+ && target->symtree->n.sym->attr.dummy
+ && sym->ts.u.cl == target->ts.u.cl)
+ {
+ sym->ts.u.cl = gfc_new_charlen (sym->ns, NULL);
+ sym->ts.deferred = 1;
+ }
+
if (!sym->ts.u.cl->length
&& !sym->ts.deferred
&& target->expr_type == EXPR_CONSTANT)
@@ -8747,7 +8764,7 @@ resolve_assoc_var (gfc_symbol* sym, bool resolve_target)
|| sym->ts.u.cl->length->expr_type != EXPR_CONSTANT)
&& target->expr_type != EXPR_VARIABLE)
{
- sym->ts.u.cl = gfc_get_charlen();
+ sym->ts.u.cl = gfc_new_charlen (sym->ns, NULL);
sym->ts.deferred = 1;
/* This is reset in trans-stmt.c after the assignment
@@ -9271,7 +9288,6 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns)
static void
resolve_transfer (gfc_code *code)
{
- gfc_typespec *ts;
gfc_symbol *sym, *derived;
gfc_ref *ref;
gfc_expr *exp;
@@ -9307,7 +9323,9 @@ resolve_transfer (gfc_code *code)
_("item in READ")))
return;
- ts = exp->expr_type == EXPR_STRUCTURE ? &exp->ts : &exp->symtree->n.sym->ts;
+ const gfc_typespec *ts = exp->expr_type == EXPR_STRUCTURE
+ || exp->expr_type == EXPR_FUNCTION
+ ? &exp->ts : &exp->symtree->n.sym->ts;
/* Go to actual component transferred. */
for (ref = exp->ref; ref; ref = ref->next)
@@ -12130,6 +12148,7 @@ resolve_fl_variable_derived (gfc_symbol *sym, int no_init_flag)
namespace. 14.6.1.3 of the standard and the discussion on
comp.lang.fortran. */
if (sym->ns != sym->ts.u.derived->ns
+ && !sym->ts.u.derived->attr.use_assoc
&& sym->ns->proc_name->attr.if_source != IFSRC_IFBODY)
{
gfc_symbol *s;
@@ -13999,28 +14018,6 @@ resolve_component (gfc_component *c, gfc_symbol *sym)
CLASS_DATA (c)->ts.u.derived
= gfc_find_dt_in_generic (CLASS_DATA (c)->ts.u.derived);
- if (!sym->attr.is_class && c->ts.type == BT_DERIVED && !sym->attr.vtype
- && c->attr.pointer && c->ts.u.derived->components == NULL
- && !c->ts.u.derived->attr.zero_comp)
- {
- gfc_error ("The pointer component %qs of %qs at %L is a type "
- "that has not been declared", c->name, sym->name,
- &c->loc);
- return false;
- }
-
- if (c->ts.type == BT_CLASS && c->attr.class_ok
- && CLASS_DATA (c)->attr.class_pointer
- && CLASS_DATA (c)->ts.u.derived->components == NULL
- && !CLASS_DATA (c)->ts.u.derived->attr.zero_comp
- && !UNLIMITED_POLY (c))
- {
- gfc_error ("The pointer component %qs of %qs at %L is a type "
- "that has not been declared", c->name, sym->name,
- &c->loc);
- return false;
- }
-
/* If an allocatable component derived type is of the same type as
the enclosing derived type, we need a vtable generating so that
the __deallocate procedure is created. */
@@ -14256,6 +14253,13 @@ resolve_fl_derived (gfc_symbol *sym)
&sym->declared_at))
return false;
+ if (sym->components == NULL && !sym->attr.zero_comp && !sym->attr.use_assoc)
+ {
+ gfc_error ("Derived type %qs at %L has not been declared",
+ sym->name, &sym->declared_at);
+ return false;
+ }
+
/* Resolve the finalizer procedures. */
if (!gfc_resolve_finalizers (sym, NULL))
return false;
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index 4199736..d35bbba 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -5525,54 +5525,57 @@ gfc_simplify_modulo (gfc_expr *a, gfc_expr *p)
gfc_expr *result;
int kind;
- if (a->expr_type != EXPR_CONSTANT || p->expr_type != EXPR_CONSTANT)
+ /* First check p. */
+ if (p->expr_type != EXPR_CONSTANT)
return NULL;
- kind = a->ts.kind > p->ts.kind ? a->ts.kind : p->ts.kind;
- result = gfc_get_constant_expr (a->ts.type, kind, &a->where);
-
- switch (a->ts.type)
+ /* p shall not be 0. */
+ switch (p->ts.type)
{
case BT_INTEGER:
if (mpz_cmp_ui (p->value.integer, 0) == 0)
{
- /* Result is processor-dependent. This processor just opts
- to not handle it at all. */
- gfc_error ("Second argument of MODULO at %L is zero", &a->where);
- gfc_free_expr (result);
+ gfc_error ("Argument %qs of MODULO at %L shall not be zero",
+ "P", &p->where);
return &gfc_bad_expr;
}
- mpz_fdiv_r (result->value.integer, a->value.integer, p->value.integer);
-
break;
-
case BT_REAL:
if (mpfr_cmp_ui (p->value.real, 0) == 0)
{
- /* Result is processor-dependent. */
- gfc_error ("Second argument of MODULO at %L is zero", &p->where);
- gfc_free_expr (result);
+ gfc_error ("Argument %qs of MODULO at %L shall not be zero",
+ "P", &p->where);
return &gfc_bad_expr;
}
-
- gfc_set_model_kind (kind);
- mpfr_fmod (result->value.real, a->value.real, p->value.real,
- GFC_RND_MODE);
- if (mpfr_cmp_ui (result->value.real, 0) != 0)
- {
- if (mpfr_signbit (a->value.real) != mpfr_signbit (p->value.real))
- mpfr_add (result->value.real, result->value.real, p->value.real,
- GFC_RND_MODE);
- }
- else
- mpfr_copysign (result->value.real, result->value.real,
- p->value.real, GFC_RND_MODE);
break;
-
default:
gfc_internal_error ("gfc_simplify_modulo(): Bad arguments");
}
+ if (a->expr_type != EXPR_CONSTANT)
+ return NULL;
+
+ kind = a->ts.kind > p->ts.kind ? a->ts.kind : p->ts.kind;
+ result = gfc_get_constant_expr (a->ts.type, kind, &a->where);
+
+ if (a->ts.type == BT_INTEGER)
+ mpz_fdiv_r (result->value.integer, a->value.integer, p->value.integer);
+ else
+ {
+ gfc_set_model_kind (kind);
+ mpfr_fmod (result->value.real, a->value.real, p->value.real,
+ GFC_RND_MODE);
+ if (mpfr_cmp_ui (result->value.real, 0) != 0)
+ {
+ if (mpfr_signbit (a->value.real) != mpfr_signbit (p->value.real))
+ mpfr_add (result->value.real, result->value.real, p->value.real,
+ GFC_RND_MODE);
+ }
+ else
+ mpfr_copysign (result->value.real, result->value.real,
+ p->value.real, GFC_RND_MODE);
+ }
+
return range_check (result, "MODULO");
}
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 8133794..0d699ed 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -849,10 +849,22 @@ gfc_get_array_span (tree desc, gfc_expr *expr)
else
{
/* If none of the fancy stuff works, the span is the element
- size of the array. */
+ size of the array. Attempt to deal with unbounded character
+ types if possible. Otherwise, return NULL_TREE. */
tmp = gfc_get_element_type (TREE_TYPE (desc));
- tmp = fold_convert (gfc_array_index_type,
- size_in_bytes (tmp));
+ if (tmp && TREE_CODE (tmp) == ARRAY_TYPE
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (tmp)) == NULL_TREE)
+ {
+ if (expr->expr_type == EXPR_VARIABLE
+ && expr->ts.type == BT_CHARACTER)
+ tmp = fold_convert (gfc_array_index_type,
+ gfc_get_expr_charlen (expr));
+ else
+ tmp = NULL_TREE;
+ }
+ else
+ tmp = fold_convert (gfc_array_index_type,
+ size_in_bytes (tmp));
}
return tmp;
}
@@ -3414,11 +3426,7 @@ gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
if (is_pointer_array (info->descriptor))
{
if (TREE_CODE (info->descriptor) == COMPONENT_REF)
- {
- decl = gfc_evaluate_now (info->descriptor, &se->pre);
- GFC_DECL_PTR_ARRAY_P (decl) = 1;
- TREE_USED (decl) = 1;
- }
+ decl = info->descriptor;
else if (TREE_CODE (info->descriptor) == INDIRECT_REF)
decl = TREE_OPERAND (info->descriptor, 0);
@@ -3659,11 +3667,7 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_expr *expr,
&& is_pointer_array (se->expr))
{
if (TREE_CODE (se->expr) == COMPONENT_REF)
- {
- decl = gfc_evaluate_now (se->expr, &se->pre);
- GFC_DECL_PTR_ARRAY_P (decl) = 1;
- TREE_USED (decl) = 1;
- }
+ decl = se->expr;
else if (TREE_CODE (se->expr) == INDIRECT_REF)
decl = TREE_OPERAND (se->expr, 0);
else
@@ -5964,6 +5968,26 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr)
{
case EXPR_CONSTANT:
gfc_conv_constant (&se, c->expr);
+
+ /* See gfortran.dg/charlen_15.f90 for instance. */
+ if (TREE_CODE (se.expr) == STRING_CST
+ && TREE_CODE (type) == ARRAY_TYPE)
+ {
+ tree atype = type;
+ while (TREE_CODE (TREE_TYPE (atype)) == ARRAY_TYPE)
+ atype = TREE_TYPE (atype);
+ if (TREE_CODE (TREE_TYPE (atype)) == INTEGER_TYPE
+ && tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (se.expr)))
+ > tree_to_uhwi (TYPE_SIZE_UNIT (atype)))
+ {
+ unsigned HOST_WIDE_INT size
+ = tree_to_uhwi (TYPE_SIZE_UNIT (atype));
+ const char *p = TREE_STRING_POINTER (se.expr);
+
+ se.expr = build_string (size, p);
+ TREE_TYPE (se.expr) = atype;
+ }
+ }
break;
case EXPR_STRUCTURE:
@@ -7062,7 +7086,8 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
/* ....and set the span field. */
tmp = gfc_get_array_span (desc, expr);
- gfc_conv_descriptor_span_set (&se->pre, se->expr, tmp);
+ if (tmp != NULL_TREE)
+ gfc_conv_descriptor_span_set (&se->pre, se->expr, tmp);
}
else if (se->want_pointer)
{
@@ -7332,13 +7357,9 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
desc = info->descriptor;
if (se->direct_byref && !se->byref_noassign)
{
- /* For pointer assignments we fill in the destination.... */
+ /* For pointer assignments we fill in the destination. */
parm = se->expr;
parmtype = TREE_TYPE (parm);
-
- /* ....and set the span field. */
- tmp = gfc_get_array_span (desc, expr);
- gfc_conv_descriptor_span_set (&loop.pre, parm, tmp);
}
else
{
@@ -7376,6 +7397,11 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
}
}
+ /* Set the span field. */
+ tmp = gfc_get_array_span (desc, expr);
+ if (tmp != NULL_TREE)
+ gfc_conv_descriptor_span_set (&loop.pre, parm, tmp);
+
offset = gfc_index_zero_node;
/* The following can be somewhat confusing. We have two
@@ -9508,6 +9534,9 @@ gfc_is_reallocatable_lhs (gfc_expr *expr)
sym = expr->symtree->n.sym;
+ if (sym->attr.associate_var)
+ return false;
+
/* An allocatable class variable with no reference. */
if (sym->ts.type == BT_CLASS
&& CLASS_DATA (sym)->attr.allocatable
@@ -9921,7 +9950,8 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
{
if (expr2->ts.deferred)
{
- if (VAR_P (expr2->ts.u.cl->backend_decl))
+ if (expr2->ts.u.cl->backend_decl
+ && VAR_P (expr2->ts.u.cl->backend_decl))
tmp = expr2->ts.u.cl->backend_decl;
else
tmp = rss->info->string_length;
@@ -9935,6 +9965,15 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
tmp = concat_str_length (expr2);
expr2->ts.u.cl->backend_decl = gfc_evaluate_now (tmp, &fblock);
}
+ else if (!tmp && expr2->ts.u.cl->length)
+ {
+ gfc_se tmpse;
+ gfc_init_se (&tmpse, NULL);
+ gfc_conv_expr_type (&tmpse, expr2->ts.u.cl->length,
+ gfc_charlen_type_node);
+ tmp = tmpse.expr;
+ expr2->ts.u.cl->backend_decl = gfc_evaluate_now (tmp, &fblock);
+ }
tmp = fold_convert (TREE_TYPE (expr1->ts.u.cl->backend_decl), tmp);
}
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 08c1ebd..159c3dbb 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -698,7 +698,8 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym)
&& CLASS_DATA (sym)->ts.u.derived->attr.has_dtio_procs)))
TREE_STATIC (decl) = 1;
- if (sym->attr.volatile_)
+ /* Treat asynchronous variables the same as volatile, for now. */
+ if (sym->attr.volatile_ || sym->attr.asynchronous)
{
TREE_THIS_VOLATILE (decl) = 1;
TREE_SIDE_EFFECTS (decl) = 1;
@@ -1509,6 +1510,13 @@ gfc_get_symbol_decl (gfc_symbol * sym)
/* Dummy variables should already have been created. */
gcc_assert (sym->backend_decl);
+ /* However, the string length of deferred arrays must be set. */
+ if (sym->ts.type == BT_CHARACTER
+ && sym->ts.deferred
+ && sym->attr.dimension
+ && sym->attr.allocatable)
+ gfc_defer_symbol_init (sym);
+
if (sym->attr.pointer && sym->attr.dimension && sym->ts.type != BT_CLASS)
GFC_DECL_PTR_ARRAY_P (sym->backend_decl) = 1;
@@ -1737,6 +1745,13 @@ gfc_get_symbol_decl (gfc_symbol * sym)
&& !(sym->attr.use_assoc && !intrinsic_array_parameter)))
gfc_defer_symbol_init (sym);
+ if (sym->ts.type == BT_CHARACTER
+ && sym->attr.allocatable
+ && !sym->attr.dimension
+ && sym->ts.u.cl && sym->ts.u.cl->length
+ && sym->ts.u.cl->length->expr_type == EXPR_VARIABLE)
+ gfc_defer_symbol_init (sym);
+
/* Associate names can use the hidden string length variable
of their associated target. */
if (sym->ts.type == BT_CHARACTER
@@ -1813,7 +1828,7 @@ gfc_get_symbol_decl (gfc_symbol * sym)
GFC_DECL_ASSOCIATE_VAR_P (decl) = 1;
if (sym->attr.vtab
- || (sym->name[0] == '_' && strncmp ("__def_init", sym->name, 10) == 0))
+ || (sym->name[0] == '_' && gfc_str_startswith (sym->name, "__def_init")))
TREE_READONLY (decl) = 1;
return decl;
@@ -4595,6 +4610,13 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
gfc_set_backend_locus (&sym->declared_at);
gfc_start_block (&init);
+ if (sym->ts.type == BT_CHARACTER
+ && sym->attr.allocatable
+ && !sym->attr.dimension
+ && sym->ts.u.cl && sym->ts.u.cl->length
+ && sym->ts.u.cl->length->expr_type == EXPR_VARIABLE)
+ gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
+
if (!sym->attr.pointer)
{
/* Nullify and automatic deallocation of allocatable
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index dfc44f7..04210a4 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -1505,7 +1505,6 @@ gfc_trans_class_init_assign (gfc_code *code)
gfc_start_block (&block);
lhs = gfc_copy_expr (code->expr1);
- gfc_add_data_component (lhs);
rhs = gfc_copy_expr (code->expr1);
gfc_add_vptr_component (rhs);
@@ -1523,11 +1522,15 @@ gfc_trans_class_init_assign (gfc_code *code)
{
gfc_array_spec *tmparr = gfc_get_array_spec ();
*tmparr = *CLASS_DATA (code->expr1)->as;
+ /* Adding the array ref to the class expression results in correct
+ indexing to the dynamic type. */
gfc_add_full_array_ref (lhs, tmparr);
tmp = gfc_trans_class_array_init_assign (rhs, lhs, code->expr1);
}
else
{
+ /* Scalar initialization needs the _data component. */
+ gfc_add_data_component (lhs);
sz = gfc_copy_expr (code->expr1);
gfc_add_vptr_component (sz);
gfc_add_size_component (sz);
@@ -2092,60 +2095,56 @@ gfc_caf_get_image_index (stmtblock_t *block, gfc_expr *e, tree desc)
integer_zero_node);
}
- img_idx = integer_zero_node;
- extent = integer_one_node;
+ img_idx = build_zero_cst (gfc_array_index_type);
+ extent = build_one_cst (gfc_array_index_type);
if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
for (i = ref->u.ar.dimen; i < ref->u.ar.dimen + ref->u.ar.codimen; i++)
{
gfc_init_se (&se, NULL);
- gfc_conv_expr_type (&se, ref->u.ar.start[i], integer_type_node);
+ gfc_conv_expr_type (&se, ref->u.ar.start[i], gfc_array_index_type);
gfc_add_block_to_block (block, &se.pre);
lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
tmp = fold_build2_loc (input_location, MINUS_EXPR,
- integer_type_node, se.expr,
- fold_convert(integer_type_node, lbound));
- tmp = fold_build2_loc (input_location, MULT_EXPR, integer_type_node,
+ TREE_TYPE (lbound), se.expr, lbound);
+ tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
extent, tmp);
- img_idx = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
- img_idx, tmp);
+ img_idx = fold_build2_loc (input_location, PLUS_EXPR,
+ TREE_TYPE (tmp), img_idx, tmp);
if (i < ref->u.ar.dimen + ref->u.ar.codimen - 1)
{
ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
- tmp = fold_convert (integer_type_node, tmp);
extent = fold_build2_loc (input_location, MULT_EXPR,
- integer_type_node, extent, tmp);
+ TREE_TYPE (tmp), extent, tmp);
}
}
else
for (i = ref->u.ar.dimen; i < ref->u.ar.dimen + ref->u.ar.codimen; i++)
{
gfc_init_se (&se, NULL);
- gfc_conv_expr_type (&se, ref->u.ar.start[i], integer_type_node);
+ gfc_conv_expr_type (&se, ref->u.ar.start[i], gfc_array_index_type);
gfc_add_block_to_block (block, &se.pre);
lbound = GFC_TYPE_ARRAY_LBOUND (TREE_TYPE (desc), i);
- lbound = fold_convert (integer_type_node, lbound);
tmp = fold_build2_loc (input_location, MINUS_EXPR,
- integer_type_node, se.expr, lbound);
- tmp = fold_build2_loc (input_location, MULT_EXPR, integer_type_node,
+ TREE_TYPE (lbound), se.expr, lbound);
+ tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
extent, tmp);
- img_idx = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
+ img_idx = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
img_idx, tmp);
if (i < ref->u.ar.dimen + ref->u.ar.codimen - 1)
{
ubound = GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (desc), i);
- ubound = fold_convert (integer_type_node, ubound);
tmp = fold_build2_loc (input_location, MINUS_EXPR,
- integer_type_node, ubound, lbound);
- tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
- tmp, integer_one_node);
+ TREE_TYPE (ubound), ubound, lbound);
+ tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
+ tmp, build_one_cst (TREE_TYPE (tmp)));
extent = fold_build2_loc (input_location, MULT_EXPR,
- integer_type_node, extent, tmp);
+ TREE_TYPE (tmp), extent, tmp);
}
}
- img_idx = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
- img_idx, integer_one_node);
- return img_idx;
+ img_idx = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (img_idx),
+ img_idx, build_one_cst (TREE_TYPE (img_idx)));
+ return fold_convert (integer_type_node, img_idx);
}
@@ -2234,7 +2233,8 @@ gfc_conv_string_length (gfc_charlen * cl, gfc_expr * expr, stmtblock_t * pblock)
if (!cl->length)
{
gfc_expr* expr_flat;
- gcc_assert (expr);
+ if (!expr)
+ return;
expr_flat = gfc_copy_expr (expr);
flatten_array_ctors_without_strlen (expr_flat);
gfc_resolve_expr (expr_flat);
@@ -3348,12 +3348,12 @@ gfc_conv_expr_op (gfc_se * se, gfc_expr * expr)
return;
case INTRINSIC_AND:
- code = TRUTH_ANDIF_EXPR;
+ code = flag_frontend_optimize ? TRUTH_ANDIF_EXPR : TRUTH_AND_EXPR;
lop = 1;
break;
case INTRINSIC_OR:
- code = TRUTH_ORIF_EXPR;
+ code = flag_frontend_optimize ? TRUTH_ORIF_EXPR : TRUTH_OR_EXPR;
lop = 1;
break;
@@ -4701,14 +4701,14 @@ conv_arglist_function (gfc_se *se, gfc_expr *expr, const char *name)
indirectly for %LOC, else by reference. Thus %REF
is a "do-nothing" and %LOC is the same as an F95
pointer. */
- if (strncmp (name, "%VAL", 4) == 0)
+ if (strcmp (name, "%VAL") == 0)
gfc_conv_expr (se, expr);
- else if (strncmp (name, "%LOC", 4) == 0)
+ else if (strcmp (name, "%LOC") == 0)
{
gfc_conv_expr_reference (se, expr);
se->expr = gfc_build_addr_expr (NULL, se->expr);
}
- else if (strncmp (name, "%REF", 4) == 0)
+ else if (strcmp (name, "%REF") == 0)
gfc_conv_expr_reference (se, expr);
else
gfc_error ("Unknown argument list function at %L", &expr->where);
@@ -4886,6 +4886,8 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
for (arg = args, argc = 0; arg != NULL;
arg = arg->next, formal = formal ? formal->next : NULL, ++argc)
{
+ bool finalized = false;
+
e = arg->expr;
fsym = formal ? formal->sym : NULL;
parm_kind = MISSING;
@@ -5270,8 +5272,22 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
}
}
else
- gfc_conv_expr_reference (&parmse, e);
-
+ {
+ bool add_clobber;
+ add_clobber = fsym && fsym->attr.intent == INTENT_OUT
+ && !fsym->attr.allocatable && !fsym->attr.pointer
+ && !e->symtree->n.sym->attr.dimension
+ && !e->symtree->n.sym->attr.pointer
+ /* See PR 41453. */
+ && !e->symtree->n.sym->attr.dummy
+ /* FIXME - PR 87395 and PR 41453 */
+ && e->symtree->n.sym->attr.save == SAVE_NONE
+ && !e->symtree->n.sym->attr.associate_var
+ && e->ts.type != BT_CHARACTER && e->ts.type != BT_DERIVED
+ && e->ts.type != BT_CLASS && !sym->attr.elemental;
+
+ gfc_conv_expr_reference (&parmse, e, add_clobber);
+ }
/* Catch base objects that are not variables. */
if (e->ts.type == BT_CLASS
&& e->expr_type != EXPR_VARIABLE
@@ -5360,7 +5376,42 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
&& e->ts.type == BT_CLASS
&& !CLASS_DATA (e)->attr.dimension
&& !CLASS_DATA (e)->attr.codimension)
- parmse.expr = gfc_class_data_get (parmse.expr);
+ {
+ parmse.expr = gfc_class_data_get (parmse.expr);
+ /* The result is a class temporary, whose _data component
+ must be freed to avoid a memory leak. */
+ if (e->expr_type == EXPR_FUNCTION
+ && CLASS_DATA (e)->attr.allocatable)
+ {
+ tree zero;
+
+ gfc_expr *var;
+
+ /* Borrow the function symbol to make a call to
+ gfc_add_finalizer_call and then restore it. */
+ tmp = e->symtree->n.sym->backend_decl;
+ e->symtree->n.sym->backend_decl
+ = TREE_OPERAND (parmse.expr, 0);
+ e->symtree->n.sym->attr.flavor = FL_VARIABLE;
+ var = gfc_lval_expr_from_sym (e->symtree->n.sym);
+ finalized = gfc_add_finalizer_call (&parmse.post,
+ var);
+ gfc_free_expr (var);
+ e->symtree->n.sym->backend_decl = tmp;
+ e->symtree->n.sym->attr.flavor = FL_PROCEDURE;
+
+ /* Then free the class _data. */
+ zero = build_int_cst (TREE_TYPE (parmse.expr), 0);
+ tmp = fold_build2_loc (input_location, NE_EXPR,
+ logical_type_node,
+ parmse.expr, zero);
+ tmp = build3_v (COND_EXPR, tmp,
+ gfc_call_free (parmse.expr),
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&parmse.post, tmp);
+ gfc_add_modify (&parmse.post, parmse.expr, zero);
+ }
+ }
/* Wrap scalar variable in a descriptor. We need to convert
the address of a pointer back to the pointer itself before,
@@ -5687,9 +5738,18 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
tmp = build_fold_indirect_ref_loc (input_location, tmp);
}
- tmp = gfc_deallocate_alloc_comp (e->ts.u.derived, tmp, parm_rank);
-
- gfc_prepend_expr_to_block (&post, tmp);
+ if (!finalized && !e->must_finalize)
+ {
+ if ((e->ts.type == BT_CLASS
+ && GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
+ || e->ts.type == BT_DERIVED)
+ tmp = gfc_deallocate_alloc_comp (e->ts.u.derived, tmp,
+ parm_rank);
+ else if (e->ts.type == BT_CLASS)
+ tmp = gfc_deallocate_alloc_comp (CLASS_DATA (e)->ts.u.derived,
+ tmp, parm_rank);
+ gfc_prepend_expr_to_block (&post, tmp);
+ }
}
/* Add argument checking of passing an unallocated/NULL actual to
@@ -5819,7 +5879,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
/* When calling __copy for character expressions to unlimited
polymorphic entities, the dst argument needs a string length. */
if (sym->name[0] == '_' && e && e->ts.type == BT_CHARACTER
- && strncmp (sym->name, "__vtab_CHARACTER", 16) == 0
+ && gfc_str_startswith (sym->name, "__vtab_CHARACTER")
&& arg->next && arg->next->expr
&& (arg->next->expr->ts.type == BT_DERIVED
|| arg->next->expr->ts.type == BT_CLASS)
@@ -6410,7 +6470,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
final_fndecl = gfc_class_vtab_final_get (se->expr);
is_final = fold_build2_loc (input_location, NE_EXPR,
logical_type_node,
- final_fndecl,
+ final_fndecl,
fold_convert (TREE_TYPE (final_fndecl),
null_pointer_node));
final_fndecl = build_fold_indirect_ref_loc (input_location,
@@ -6420,28 +6480,43 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
gfc_build_addr_expr (NULL, tmp),
gfc_class_vtab_size_get (se->expr),
boolean_false_node);
- tmp = fold_build3_loc (input_location, COND_EXPR,
+ tmp = fold_build3_loc (input_location, COND_EXPR,
void_type_node, is_final, tmp,
build_empty_stmt (input_location));
if (se->ss && se->ss->loop)
{
- gfc_add_expr_to_block (&se->ss->loop->post, tmp);
- tmp = gfc_call_free (info->data);
+ gfc_prepend_expr_to_block (&se->ss->loop->post, tmp);
+ tmp = fold_build2_loc (input_location, NE_EXPR,
+ logical_type_node,
+ info->data,
+ fold_convert (TREE_TYPE (info->data),
+ null_pointer_node));
+ tmp = fold_build3_loc (input_location, COND_EXPR,
+ void_type_node, tmp,
+ gfc_call_free (info->data),
+ build_empty_stmt (input_location));
gfc_add_expr_to_block (&se->ss->loop->post, tmp);
}
else
{
- gfc_add_expr_to_block (&se->post, tmp);
- tmp = gfc_class_data_get (se->expr);
- tmp = gfc_call_free (tmp);
+ tree classdata;
+ gfc_prepend_expr_to_block (&se->post, tmp);
+ classdata = gfc_class_data_get (se->expr);
+ tmp = fold_build2_loc (input_location, NE_EXPR,
+ logical_type_node,
+ classdata,
+ fold_convert (TREE_TYPE (classdata),
+ null_pointer_node));
+ tmp = fold_build3_loc (input_location, COND_EXPR,
+ void_type_node, tmp,
+ gfc_call_free (classdata),
+ build_empty_stmt (input_location));
gfc_add_expr_to_block (&se->post, tmp);
}
-
-no_finalization:
- expr->must_finalize = 0;
}
+no_finalization:
gfc_add_block_to_block (&se->post, &post);
}
@@ -7668,7 +7743,7 @@ gfc_trans_structure_assign (tree dest, gfc_expr * expr, bool init, bool coarray)
suffices to recognize the data as array. */
if (rank < 0)
rank = 1;
- size = integer_zero_node;
+ size = build_zero_cst (size_type_node);
desc = field;
gfc_add_modify (&block, gfc_conv_descriptor_rank (desc),
build_int_cst (signed_char_type_node, rank));
@@ -7995,7 +8070,7 @@ gfc_conv_expr_type (gfc_se * se, gfc_expr * expr, tree type)
values only. */
void
-gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr)
+gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr, bool add_clobber)
{
gfc_ss *ss;
tree var;
@@ -8035,6 +8110,16 @@ gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr)
gfc_add_block_to_block (&se->pre, &se->post);
se->expr = var;
}
+ else if (add_clobber)
+ {
+ tree clobber;
+ tree var;
+ /* FIXME: This fails if var is passed by reference, see PR
+ 41453. */
+ var = expr->symtree->n.sym->backend_decl;
+ clobber = build_clobber (TREE_TYPE (var));
+ gfc_add_modify (&se->pre, var, clobber);
+ }
return;
}
@@ -8072,7 +8157,9 @@ gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr)
var = gfc_create_var (TREE_TYPE (se->expr), NULL);
gfc_add_modify (&se->pre, var, se->expr);
}
- gfc_add_block_to_block (&se->pre, &se->post);
+
+ if (!expr->must_finalize)
+ gfc_add_block_to_block (&se->pre, &se->post);
/* Take the address of that value. */
se->expr = gfc_build_addr_expr (NULL_TREE, var);
@@ -9262,10 +9349,12 @@ gfc_trans_arrayfunc_assign (gfc_expr * expr1, gfc_expr * expr2)
/* The frontend doesn't seem to bother filling in expr->symtree for intrinsic
functions. */
comp = gfc_get_proc_ptr_comp (expr2);
- gcc_assert (expr2->value.function.isym
+
+ if (!(expr2->value.function.isym
|| (comp && comp->attr.dimension)
|| (!comp && gfc_return_by_reference (expr2->value.function.esym)
- && expr2->value.function.esym->result->attr.dimension));
+ && expr2->value.function.esym->result->attr.dimension)))
+ return NULL;
gfc_init_se (&se, NULL);
gfc_start_block (&se.pre);
@@ -10206,19 +10295,27 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
/* When assigning a character function result to a deferred-length variable,
the function call must happen before the (re)allocation of the lhs -
otherwise the character length of the result is not known.
- NOTE: This relies on having the exact dependence of the length type
+ NOTE 1: This relies on having the exact dependence of the length type
parameter available to the caller; gfortran saves it in the .mod files.
- NOTE ALSO: The concatenation operation generates a temporary pointer,
+ NOTE 2: Vector array references generate an index temporary that must
+ not go outside the loop. Otherwise, variables should not generate
+ a pre block.
+ NOTE 3: The concatenation operation generates a temporary pointer,
whose allocation must go to the innermost loop.
- NOTE ALSO (2): A character conversion may generate a temporary, too. */
+ NOTE 4: Elemental functions may generate a temporary, too. */
if (flag_realloc_lhs
&& expr2->ts.type == BT_CHARACTER && expr1->ts.deferred
&& !(lss != gfc_ss_terminator
- && ((expr2->expr_type == EXPR_OP
- && expr2->value.op.op == INTRINSIC_CONCAT)
+ && rss != gfc_ss_terminator
+ && ((expr2->expr_type == EXPR_VARIABLE && expr2->rank)
+ || (expr2->expr_type == EXPR_FUNCTION
+ && expr2->value.function.esym != NULL
+ && expr2->value.function.esym->attr.elemental)
|| (expr2->expr_type == EXPR_FUNCTION
&& expr2->value.function.isym != NULL
- && expr2->value.function.isym->id == GFC_ISYM_CONVERSION))))
+ && expr2->value.function.isym->elemental)
+ || (expr2->expr_type == EXPR_OP
+ && expr2->value.op.op == INTRINSIC_CONCAT))))
gfc_add_block_to_block (&block, &rse.pre);
/* Nullify the allocatable components corresponding to those of the lhs
@@ -10238,6 +10335,8 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
gfc_add_block_to_block (&loop.post, &rse.post);
}
+ tmp = NULL_TREE;
+
if (is_poly_assign)
tmp = trans_class_assignment (&body, expr1, expr2, &lse, &rse,
use_vptr_copy || (lhs_attr.allocatable
@@ -10266,13 +10365,35 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
code.resolved_isym = gfc_intrinsic_subroutine_by_id (GFC_ISYM_CAF_SEND);
tmp = gfc_conv_intrinsic_subroutine (&code);
}
- else
+ else if (!is_poly_assign && expr2->must_finalize
+ && expr1->ts.type == BT_CLASS
+ && expr2->ts.type == BT_CLASS)
+ {
+ /* This case comes about when the scalarizer provides array element
+ references. Use the vptr copy function, since this does a deep
+ copy of allocatable components, without which the finalizer call */
+ tmp = gfc_get_vptr_from_expr (rse.expr);
+ if (tmp != NULL_TREE)
+ {
+ tree fcn = gfc_vptr_copy_get (tmp);
+ if (POINTER_TYPE_P (TREE_TYPE (fcn)))
+ fcn = build_fold_indirect_ref_loc (input_location, fcn);
+ tmp = build_call_expr_loc (input_location,
+ fcn, 2,
+ gfc_build_addr_expr (NULL, rse.expr),
+ gfc_build_addr_expr (NULL, lse.expr));
+ }
+ }
+
+ /* If nothing else works, do it the old fashioned way! */
+ if (tmp == NULL_TREE)
tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
gfc_expr_is_variable (expr2)
|| scalar_to_array
|| expr2->expr_type == EXPR_ARRAY,
!(l_is_temp || init_flag) && dealloc,
expr1->symtree->n.sym->attr.codimension);
+
/* Add the pre blocks to the body. */
gfc_add_block_to_block (&body, &rse.pre);
gfc_add_block_to_block (&body, &lse.pre);
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index c9b5479..639175a 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -3664,8 +3664,8 @@ conv_intrinsic_random_init (gfc_code *code)
gfc_add_block_to_block (&block, &se.post);
/* Create the hidden argument. For non-coarray codes and -fcoarray=single,
- simply set this to 0. For -fcoarray=lib, generate a call to
- THIS_IMAGE() without arguments. */
+ simply set this to 0. For -fcoarray=lib, generate a call to
+ THIS_IMAGE() without arguments. */
arg3 = build_int_cst (gfc_get_int_type (4), 0);
if (flag_coarray == GFC_FCOARRAY_LIB)
{
@@ -3677,7 +3677,7 @@ conv_intrinsic_random_init (gfc_code *code)
tmp = build_call_expr_loc (input_location, gfor_fndecl_random_init, 3,
arg1, arg2, arg3);
gfc_add_expr_to_block (&block, tmp);
-
+
return gfc_finish_block (&block);
}
@@ -3914,8 +3914,6 @@ gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
mvar = gfc_create_var (type, "M");
gfc_add_modify (&se->pre, mvar, args[0]);
- internal_fn ifn = op == GT_EXPR ? IFN_FMAX : IFN_FMIN;
-
for (i = 1, argexpr = argexpr->next; i < nargs; i++, argexpr = argexpr->next)
{
tree cond = NULL_TREE;
@@ -3936,49 +3934,16 @@ gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
val = gfc_evaluate_now (val, &se->pre);
tree calc;
- /* If we dealing with integral types or we don't care about NaNs
- just do a MIN/MAX_EXPR. */
- if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
- {
-
- tree_code code = op == GT_EXPR ? MAX_EXPR : MIN_EXPR;
- calc = fold_build2_loc (input_location, code, type,
- convert (type, val), mvar);
- tmp = build2_v (MODIFY_EXPR, mvar, calc);
-
- }
- /* If we care about NaNs and we have internal functions available for
- fmin/fmax to perform the comparison, use those. */
- else if (SCALAR_FLOAT_TYPE_P (type)
- && direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED))
- {
- calc = build_call_expr_internal_loc (input_location, ifn, type,
- 2, mvar, convert (type, val));
- tmp = build2_v (MODIFY_EXPR, mvar, calc);
-
- }
- /* Otherwise expand to:
- mvar = a1;
- if (a2 .op. mvar || isnan (mvar))
- mvar = a2;
- if (a3 .op. mvar || isnan (mvar))
- mvar = a3;
- ... */
- else
- {
- tree isnan = build_call_expr_loc (input_location,
- builtin_decl_explicit (BUILT_IN_ISNAN),
- 1, mvar);
- tmp = fold_build2_loc (input_location, op, logical_type_node,
- convert (type, val), mvar);
-
- tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR,
- logical_type_node, tmp,
- fold_convert (logical_type_node, isnan));
- tmp = build3_v (COND_EXPR, tmp,
- build2_v (MODIFY_EXPR, mvar, convert (type, val)),
- build_empty_stmt (input_location));
- }
+ /* For floating point types, the question is what MAX(a, NaN) or
+ MIN(a, NaN) should return (where "a" is a normal number).
+ There are valid usecase for returning either one, but the
+ Fortran standard doesn't specify which one should be chosen.
+ Also, there is no consensus among other tested compilers. In
+ short, it's a mess. So lets just do whatever is fastest. */
+ tree_code code = op == GT_EXPR ? MAX_EXPR : MIN_EXPR;
+ calc = fold_build2_loc (input_location, code, type,
+ convert (type, val), mvar);
+ tmp = build2_v (MODIFY_EXPR, mvar, calc);
if (cond != NULL_TREE)
tmp = build3_v (COND_EXPR, cond, tmp,
@@ -4090,6 +4055,7 @@ gfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr)
to be able to call the BLAS ?gemm functions if required and possible. */
append_args = NULL;
if (expr->value.function.isym->id == GFC_ISYM_MATMUL
+ && !expr->external_blas
&& sym->ts.type != BT_LOGICAL)
{
tree cint = gfc_get_int_type (gfc_c_int_kind);
@@ -5546,22 +5512,10 @@ gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
{
/* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
signed zeros. */
- if (HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
- {
- tmp = fold_build2_loc (input_location, op, logical_type_node,
- arrayse.expr, limit);
- ifbody = build2_v (MODIFY_EXPR, limit, arrayse.expr);
- tmp = build3_v (COND_EXPR, tmp, ifbody,
- build_empty_stmt (input_location));
- gfc_add_expr_to_block (&block2, tmp);
- }
- else
- {
- tmp = fold_build2_loc (input_location,
- op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
- type, arrayse.expr, limit);
- gfc_add_modify (&block2, limit, tmp);
- }
+ tmp = fold_build2_loc (input_location,
+ op == GT_EXPR ? MAX_EXPR : MIN_EXPR,
+ type, arrayse.expr, limit);
+ gfc_add_modify (&block2, limit, tmp);
}
if (fast)
@@ -5570,8 +5524,7 @@ gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
/* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
signed zeros. */
- if (HONOR_NANS (DECL_MODE (limit))
- || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
+ if (HONOR_NANS (DECL_MODE (limit)))
{
tmp = fold_build2_loc (input_location, op, logical_type_node,
arrayse.expr, limit);
@@ -5633,8 +5586,7 @@ gfc_conv_intrinsic_minmaxval (gfc_se * se, gfc_expr * expr, enum tree_code op)
/* MIN_EXPR/MAX_EXPR has unspecified behavior with NaNs or
signed zeros. */
- if (HONOR_NANS (DECL_MODE (limit))
- || HONOR_SIGNED_ZEROS (DECL_MODE (limit)))
+ if (HONOR_NANS (DECL_MODE (limit)))
{
tmp = fold_build2_loc (input_location, op, logical_type_node,
arrayse.expr, limit);
@@ -7369,13 +7321,14 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
tree upper;
tree lower;
tree stmt;
+ tree class_ref = NULL_TREE;
gfc_actual_arglist *arg;
gfc_se argse;
gfc_array_info *info;
stmtblock_t block;
int n;
bool scalar_mold;
- gfc_expr *source_expr, *mold_expr;
+ gfc_expr *source_expr, *mold_expr, *class_expr;
info = NULL;
if (se->loop)
@@ -7406,7 +7359,24 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
{
gfc_conv_expr_reference (&argse, arg->expr);
if (arg->expr->ts.type == BT_CLASS)
- source = gfc_class_data_get (argse.expr);
+ {
+ tmp = build_fold_indirect_ref_loc (input_location, argse.expr);
+ if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
+ source = gfc_class_data_get (tmp);
+ else
+ {
+ /* Array elements are evaluated as a reference to the data.
+ To obtain the vptr for the element size, the argument
+ expression must be stripped to the class reference and
+ re-evaluated. The pre and post blocks are not needed. */
+ gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
+ source = argse.expr;
+ class_expr = gfc_find_and_cut_at_last_class_ref (arg->expr);
+ gfc_init_se (&argse, NULL);
+ gfc_conv_expr (&argse, class_expr);
+ class_ref = argse.expr;
+ }
+ }
else
source = argse.expr;
@@ -7418,7 +7388,10 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
argse.string_length);
break;
case BT_CLASS:
- tmp = gfc_class_vtab_size_get (argse.expr);
+ if (class_ref != NULL_TREE)
+ tmp = gfc_class_vtab_size_get (class_ref);
+ else
+ tmp = gfc_class_vtab_size_get (argse.expr);
break;
default:
source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location,
@@ -8965,37 +8938,33 @@ gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
{
const char *name = expr->value.function.name;
-#define STARTS_WITH(A,B) (strncmp((A), (B), strlen(B)) == 0)
-
- if (STARTS_WITH (name, "_gfortran_ieee_is_nan"))
+ if (gfc_str_startswith (name, "_gfortran_ieee_is_nan"))
conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISNAN, 1);
- else if (STARTS_WITH (name, "_gfortran_ieee_is_finite"))
+ else if (gfc_str_startswith (name, "_gfortran_ieee_is_finite"))
conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISFINITE, 1);
- else if (STARTS_WITH (name, "_gfortran_ieee_unordered"))
+ else if (gfc_str_startswith (name, "_gfortran_ieee_unordered"))
conv_intrinsic_ieee_builtin (se, expr, BUILT_IN_ISUNORDERED, 2);
- else if (STARTS_WITH (name, "_gfortran_ieee_is_normal"))
+ else if (gfc_str_startswith (name, "_gfortran_ieee_is_normal"))
conv_intrinsic_ieee_is_normal (se, expr);
- else if (STARTS_WITH (name, "_gfortran_ieee_is_negative"))
+ else if (gfc_str_startswith (name, "_gfortran_ieee_is_negative"))
conv_intrinsic_ieee_is_negative (se, expr);
- else if (STARTS_WITH (name, "_gfortran_ieee_copy_sign"))
+ else if (gfc_str_startswith (name, "_gfortran_ieee_copy_sign"))
conv_intrinsic_ieee_copy_sign (se, expr);
- else if (STARTS_WITH (name, "_gfortran_ieee_scalb"))
+ else if (gfc_str_startswith (name, "_gfortran_ieee_scalb"))
conv_intrinsic_ieee_scalb (se, expr);
- else if (STARTS_WITH (name, "_gfortran_ieee_next_after"))
+ else if (gfc_str_startswith (name, "_gfortran_ieee_next_after"))
conv_intrinsic_ieee_next_after (se, expr);
- else if (STARTS_WITH (name, "_gfortran_ieee_rem"))
+ else if (gfc_str_startswith (name, "_gfortran_ieee_rem"))
conv_intrinsic_ieee_rem (se, expr);
- else if (STARTS_WITH (name, "_gfortran_ieee_logb"))
+ else if (gfc_str_startswith (name, "_gfortran_ieee_logb"))
conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
- else if (STARTS_WITH (name, "_gfortran_ieee_rint"))
+ else if (gfc_str_startswith (name, "_gfortran_ieee_rint"))
conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT);
else
/* It is not among the functions we translate directly. We return
false, so a library function call is emitted. */
return false;
-#undef STARTS_WITH
-
return true;
}
@@ -10694,7 +10663,7 @@ conv_intrinsic_event_query (gfc_code *code)
if (flag_coarray == GFC_FCOARRAY_LIB)
{
tree tmp, token, image_index;
- tree index = size_zero_node;
+ tree index = build_zero_cst (gfc_array_index_type);
if (event_expr->expr_type == EXPR_FUNCTION
&& event_expr->value.function.isym
@@ -10747,27 +10716,25 @@ conv_intrinsic_event_query (gfc_code *code)
desc = argse.expr;
*ar = ar2;
- extent = integer_one_node;
+ extent = build_one_cst (gfc_array_index_type);
for (i = 0; i < ar->dimen; i++)
{
gfc_init_se (&argse, NULL);
- gfc_conv_expr_type (&argse, ar->start[i], integer_type_node);
+ gfc_conv_expr_type (&argse, ar->start[i], gfc_array_index_type);
gfc_add_block_to_block (&argse.pre, &argse.pre);
lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
tmp = fold_build2_loc (input_location, MINUS_EXPR,
- integer_type_node, argse.expr,
- fold_convert(integer_type_node, lbound));
+ TREE_TYPE (lbound), argse.expr, lbound);
tmp = fold_build2_loc (input_location, MULT_EXPR,
- integer_type_node, extent, tmp);
+ TREE_TYPE (tmp), extent, tmp);
index = fold_build2_loc (input_location, PLUS_EXPR,
- integer_type_node, index, tmp);
+ TREE_TYPE (tmp), index, tmp);
if (i < ar->dimen - 1)
{
ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
- tmp = fold_convert (integer_type_node, tmp);
extent = fold_build2_loc (input_location, MULT_EXPR,
- integer_type_node, extent, tmp);
+ TREE_TYPE (tmp), extent, tmp);
}
}
}
@@ -10784,6 +10751,7 @@ conv_intrinsic_event_query (gfc_code *code)
stat = gfc_create_var (integer_type_node, "stat");
}
+ index = fold_convert (size_type_node, index);
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_query, 5,
token, index, image_index, count
? gfc_build_addr_expr (NULL, count) : count,
diff --git a/gcc/fortran/trans-io.c b/gcc/fortran/trans-io.c
index 2626c46..88dbcb8 100644
--- a/gcc/fortran/trans-io.c
+++ b/gcc/fortran/trans-io.c
@@ -438,10 +438,9 @@ gfc_build_io_library_fndecls (void)
get_identifier (PREFIX("st_iolength")), ".w",
void_type_node, 1, dt_parm_type);
- /* TODO: Change when asynchronous I/O is implemented. */
parm_type = build_pointer_type (st_parameter[IOPARM_ptype_wait].type);
iocall[IOCALL_WAIT] = gfc_build_library_function_decl_with_spec (
- get_identifier (PREFIX("st_wait")), ".X",
+ get_identifier (PREFIX("st_wait_async")), ".w",
void_type_node, 1, parm_type);
parm_type = build_pointer_type (st_parameter[IOPARM_ptype_filepos].type);
@@ -1527,7 +1526,7 @@ gfc_trans_wait (gfc_code * code)
mask |= IOPARM_common_err;
if (p->id)
- mask |= set_parameter_value (&block, var, IOPARM_wait_id, p->id);
+ mask |= set_parameter_ref (&block, &post_block, var, IOPARM_wait_id, p->id);
set_parameter_const (&block, var, IOPARM_common_flags, mask);
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index cc1a429..ef9e519 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -841,7 +841,7 @@ gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op op)
if (flag_coarray == GFC_FCOARRAY_LIB)
{
tree tmp, token, image_index, errmsg, errmsg_len;
- tree index = size_zero_node;
+ tree index = build_zero_cst (gfc_array_index_type);
tree caf_decl = gfc_get_tree_for_caf_expr (code->expr1);
if (code->expr1->symtree->n.sym->ts.type != BT_DERIVED
@@ -884,27 +884,25 @@ gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op op)
desc = argse.expr;
*ar = ar2;
- extent = integer_one_node;
+ extent = build_one_cst (gfc_array_index_type);
for (i = 0; i < ar->dimen; i++)
{
gfc_init_se (&argse, NULL);
- gfc_conv_expr_type (&argse, ar->start[i], integer_type_node);
+ gfc_conv_expr_type (&argse, ar->start[i], gfc_array_index_type);
gfc_add_block_to_block (&argse.pre, &argse.pre);
lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
tmp = fold_build2_loc (input_location, MINUS_EXPR,
- integer_type_node, argse.expr,
- fold_convert(integer_type_node, lbound));
+ TREE_TYPE (lbound), argse.expr, lbound);
tmp = fold_build2_loc (input_location, MULT_EXPR,
- integer_type_node, extent, tmp);
+ TREE_TYPE (tmp), extent, tmp);
index = fold_build2_loc (input_location, PLUS_EXPR,
- integer_type_node, index, tmp);
+ TREE_TYPE (tmp), index, tmp);
if (i < ar->dimen - 1)
{
ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
- tmp = fold_convert (integer_type_node, tmp);
extent = fold_build2_loc (input_location, MULT_EXPR,
- integer_type_node, extent, tmp);
+ TREE_TYPE (tmp), extent, tmp);
}
}
}
@@ -938,6 +936,7 @@ gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op op)
lock_acquired = gfc_create_var (integer_type_node, "acquired");
}
+ index = fold_convert (size_type_node, index);
if (op == EXEC_LOCK)
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_lock, 7,
token, index, image_index,
@@ -1038,7 +1037,7 @@ gfc_trans_event_post_wait (gfc_code *code, gfc_exec_op op)
gfc_start_block (&se.pre);
tree tmp, token, image_index, errmsg, errmsg_len;
- tree index = size_zero_node;
+ tree index = build_zero_cst (gfc_array_index_type);
tree caf_decl = gfc_get_tree_for_caf_expr (code->expr1);
if (code->expr1->symtree->n.sym->ts.type != BT_DERIVED
@@ -1083,27 +1082,25 @@ gfc_trans_event_post_wait (gfc_code *code, gfc_exec_op op)
desc = argse.expr;
*ar = ar2;
- extent = integer_one_node;
+ extent = build_one_cst (gfc_array_index_type);
for (i = 0; i < ar->dimen; i++)
{
gfc_init_se (&argse, NULL);
- gfc_conv_expr_type (&argse, ar->start[i], integer_type_node);
+ gfc_conv_expr_type (&argse, ar->start[i], gfc_array_index_type);
gfc_add_block_to_block (&argse.pre, &argse.pre);
lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
tmp = fold_build2_loc (input_location, MINUS_EXPR,
- integer_type_node, argse.expr,
- fold_convert(integer_type_node, lbound));
+ TREE_TYPE (lbound), argse.expr, lbound);
tmp = fold_build2_loc (input_location, MULT_EXPR,
- integer_type_node, extent, tmp);
+ TREE_TYPE (tmp), extent, tmp);
index = fold_build2_loc (input_location, PLUS_EXPR,
- integer_type_node, index, tmp);
+ TREE_TYPE (tmp), index, tmp);
if (i < ar->dimen - 1)
{
ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
- tmp = fold_convert (integer_type_node, tmp);
extent = fold_build2_loc (input_location, MULT_EXPR,
- integer_type_node, extent, tmp);
+ TREE_TYPE (tmp), extent, tmp);
}
}
}
@@ -1130,6 +1127,7 @@ gfc_trans_event_post_wait (gfc_code *code, gfc_exec_op op)
stat = gfc_create_var (integer_type_node, "stat");
}
+ index = fold_convert (size_type_node, index);
if (op == EXEC_EVENT_POST)
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_post, 6,
token, index, image_index,
@@ -5783,6 +5781,7 @@ gfc_trans_allocate (gfc_code * code)
enum { E3_UNSET = 0, E3_SOURCE, E3_MOLD, E3_DESC } e3_is;
stmtblock_t block;
stmtblock_t post;
+ stmtblock_t final_block;
tree nelems;
bool upoly_expr, tmp_expr3_len_flag = false, al_len_needs_set, is_coarray;
bool needs_caf_sync, caf_refs_comp;
@@ -5801,6 +5800,7 @@ gfc_trans_allocate (gfc_code * code)
gfc_init_block (&block);
gfc_init_block (&post);
+ gfc_init_block (&final_block);
/* STAT= (and maybe ERRMSG=) is present. */
if (code->expr1)
@@ -5842,6 +5842,11 @@ gfc_trans_allocate (gfc_code * code)
is_coarray = gfc_is_coarray (code->expr3);
+ if (code->expr3->expr_type == EXPR_FUNCTION && !code->expr3->mold
+ && (gfc_is_class_array_function (code->expr3)
+ || gfc_is_alloc_class_scalar_function (code->expr3)))
+ code->expr3->must_finalize = 1;
+
/* Figure whether we need the vtab from expr3. */
for (al = code->ext.alloc.list; !vtab_needed && al != NULL;
al = al->next)
@@ -5914,7 +5919,10 @@ gfc_trans_allocate (gfc_code * code)
temp_obj_created = temp_var_needed = !VAR_P (se.expr);
}
gfc_add_block_to_block (&block, &se.pre);
- gfc_add_block_to_block (&post, &se.post);
+ if (code->expr3->must_finalize)
+ gfc_add_block_to_block (&final_block, &se.post);
+ else
+ gfc_add_block_to_block (&post, &se.post);
/* Special case when string in expr3 is zero. */
if (code->expr3->ts.type == BT_CHARACTER
@@ -5986,7 +5994,8 @@ gfc_trans_allocate (gfc_code * code)
if ((code->expr3->ts.type == BT_DERIVED
|| code->expr3->ts.type == BT_CLASS)
&& (code->expr3->expr_type != EXPR_VARIABLE || temp_obj_created)
- && code->expr3->ts.u.derived->attr.alloc_comp)
+ && code->expr3->ts.u.derived->attr.alloc_comp
+ && !code->expr3->must_finalize)
{
tmp = gfc_deallocate_alloc_comp (code->expr3->ts.u.derived,
expr3, code->expr3->rank);
@@ -6743,6 +6752,8 @@ gfc_trans_allocate (gfc_code * code)
gfc_add_block_to_block (&block, &se.post);
gfc_add_block_to_block (&block, &post);
+ if (code->expr3 && code->expr3->must_finalize)
+ gfc_add_block_to_block (&block, &final_block);
return gfc_finish_block (&block);
}
diff --git a/gcc/fortran/trans-stmt.h b/gcc/fortran/trans-stmt.h
index c798c80..848c7d9 100644
--- a/gcc/fortran/trans-stmt.h
+++ b/gcc/fortran/trans-stmt.h
@@ -70,8 +70,6 @@ tree gfc_trans_deallocate_array (tree);
/* trans-openmp.c */
tree gfc_trans_omp_directive (gfc_code *);
void gfc_trans_omp_declare_simd (gfc_namespace *);
-
-/* trans-openacc.c */
tree gfc_trans_oacc_directive (gfc_code *);
tree gfc_trans_oacc_declare (gfc_namespace *);
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
index aa10fbb..153bab6 100644
--- a/gcc/fortran/trans.c
+++ b/gcc/fortran/trans.c
@@ -407,7 +407,12 @@ gfc_build_array_ref (tree base, tree offset, tree decl, tree vptr)
if (vptr)
span = gfc_vptr_size_get (vptr);
else if (decl)
- span = get_array_span (type, decl);
+ {
+ if (TREE_CODE (decl) == COMPONENT_REF)
+ span = gfc_conv_descriptor_span_get (decl);
+ else
+ span = get_array_span (type, decl);
+ }
/* If a non-null span has been generated reference the element with
pointer arithmetic. */
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 1813882..4f33a89 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -485,7 +485,8 @@ tree gfc_build_compare_string (tree, tree, tree, tree, int, enum tree_code);
void gfc_conv_expr (gfc_se * se, gfc_expr * expr);
void gfc_conv_expr_val (gfc_se * se, gfc_expr * expr);
void gfc_conv_expr_lhs (gfc_se * se, gfc_expr * expr);
-void gfc_conv_expr_reference (gfc_se * se, gfc_expr *);
+void gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr,
+ bool add_clobber = false);
void gfc_conv_expr_type (gfc_se * se, gfc_expr *, tree);
diff --git a/gcc/function-tests.c b/gcc/function-tests.c
index 1b5ebf3..196b3a3 100644
--- a/gcc/function-tests.c
+++ b/gcc/function-tests.c
@@ -661,6 +661,7 @@ test_expansion_to_rtl ()
ASSERT_STR_CONTAINS (dump, ") ;; function \"test_fn\"\n");
free (dump);
+ free_after_compilation (fun);
}
/* Run all of the selftests within this file. */
diff --git a/gcc/function.c b/gcc/function.c
index dee303c..3024383 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -5180,7 +5180,6 @@ diddle_return_value_1 (void (*doit) (rtx, void *), void *arg, rtx outgoing)
void
diddle_return_value (void (*doit) (rtx, void *), void *arg)
{
- diddle_return_value_1 (doit, arg, crtl->return_bnd);
diddle_return_value_1 (doit, arg, crtl->return_rtx);
}
diff --git a/gcc/gcc-ar.c b/gcc/gcc-ar.c
index 83a9e34..82e0e69 100644
--- a/gcc/gcc-ar.c
+++ b/gcc/gcc-ar.c
@@ -126,7 +126,9 @@ int
main (int ac, char **av)
{
const char *exe_name;
+#if HAVE_LTO_PLUGIN > 0
char *plugin;
+#endif
int k, status, err;
const char *err_msg;
const char **nargv;
@@ -177,7 +179,7 @@ main (int ac, char **av)
break;
}
-
+#if HAVE_LTO_PLUGIN > 0
/* Find the GCC LTO plugin */
plugin = find_a_file (&target_path, LTOPLUGINSONAME, R_OK);
if (!plugin)
@@ -185,6 +187,7 @@ main (int ac, char **av)
fprintf (stderr, "%s: Cannot find plugin '%s'\n", av[0], LTOPLUGINSONAME);
exit (1);
}
+#endif
/* Find the wrapped binutils program. */
exe_name = find_a_file (&target_path, PERSONALITY, X_OK);
@@ -203,9 +206,11 @@ main (int ac, char **av)
}
}
- /* Create new command line with plugin */
+ /* Create new command line with plugin - if we have one, otherwise just
+ copy the command through. */
nargv = XCNEWVEC (const char *, ac + 4);
nargv[0] = exe_name;
+#if HAVE_LTO_PLUGIN > 0
nargv[1] = "--plugin";
nargv[2] = plugin;
if (is_ar && av[1] && av[1][0] != '-')
@@ -213,6 +218,13 @@ main (int ac, char **av)
for (k = 1; k < ac; k++)
nargv[2 + k] = av[k];
nargv[2 + k] = NULL;
+#else
+ if (is_ar && av[1] && av[1][0] != '-')
+ av[1] = concat ("-", av[1], NULL);
+ for (k = 1; k < ac; k++)
+ nargv[k] = av[k];
+ nargv[k] = NULL;
+#endif
/* Run utility */
/* ??? the const is misplaced in pex_one's argv? */
diff --git a/gcc/gcc-rich-location.c b/gcc/gcc-rich-location.c
index 0a0adf9..81beb61 100644
--- a/gcc/gcc-rich-location.c
+++ b/gcc/gcc-rich-location.c
@@ -38,24 +38,26 @@ along with GCC; see the file COPYING3. If not see
#include "cpplib.h"
#include "diagnostic.h"
-/* Add a range to the rich_location, covering expression EXPR. */
+/* Add a range to the rich_location, covering expression EXPR,
+ using LABEL if non-NULL. */
void
-gcc_rich_location::add_expr (tree expr)
+gcc_rich_location::add_expr (tree expr, range_label *label)
{
gcc_assert (expr);
if (CAN_HAVE_RANGE_P (expr))
- add_range (EXPR_LOCATION (expr), false);
+ add_range (EXPR_LOCATION (expr), SHOW_RANGE_WITHOUT_CARET, label);
}
-/* If T is an expression, add a range for it to the rich_location. */
+/* If T is an expression, add a range for it to the rich_location,
+ using LABEL if non-NULL. */
void
-gcc_rich_location::maybe_add_expr (tree t)
+gcc_rich_location::maybe_add_expr (tree t, range_label *label)
{
if (EXPR_P (t))
- add_expr (t);
+ add_expr (t, label);
}
/* Add a fixit hint suggesting replacing the range at MISSPELLED_TOKEN_LOC
diff --git a/gcc/gcc-rich-location.h b/gcc/gcc-rich-location.h
index 9c705c8..e55dd76 100644
--- a/gcc/gcc-rich-location.h
+++ b/gcc/gcc-rich-location.h
@@ -28,15 +28,17 @@ class gcc_rich_location : public rich_location
/* Constructors. */
/* Constructing from a location. */
- gcc_rich_location (source_location loc) :
- rich_location (line_table, loc) {}
+ gcc_rich_location (source_location loc, const range_label *label = NULL)
+ : rich_location (line_table, loc, label)
+ {
+ }
/* Methods for adding ranges via gcc entities. */
void
- add_expr (tree expr);
+ add_expr (tree expr, range_label *label);
void
- maybe_add_expr (tree t);
+ maybe_add_expr (tree t, range_label *label);
void add_fixit_misspelled_id (location_t misspelled_token_loc,
tree hint_id);
@@ -99,4 +101,65 @@ class gcc_rich_location : public rich_location
location_t indent);
};
+/* Concrete subclass of libcpp's range_label.
+ Simple implementation using a string literal. */
+
+class text_range_label : public range_label
+{
+ public:
+ text_range_label (const char *text) : m_text (text) {}
+
+ label_text get_text (unsigned /*range_idx*/) const FINAL OVERRIDE
+ {
+ return label_text (const_cast <char *> (m_text), false);
+ }
+
+ private:
+ const char *m_text;
+};
+
+/* Concrete subclass of libcpp's range_label for use in
+ diagnostics involving mismatched types.
+
+ Each frontend that uses this should supply its own implementation.
+
+ Generate a label describing LABELLED_TYPE. The frontend may use
+ OTHER_TYPE where appropriate for highlighting the differences between
+ the two types (analogous to C++'s use of %H and %I with
+ template types).
+
+ Either or both of LABELLED_TYPE and OTHER_TYPE may be NULL_TREE.
+ If LABELLED_TYPE is NULL_TREE, then there is no label.
+
+ For example, this rich_location could use two instances of
+ range_label_for_type_mismatch:
+
+ printf ("arg0: %i arg1: %s arg2: %i",
+ ^~
+ |
+ const char *
+ 100, 101, 102);
+ ~~~
+ |
+ int
+
+ (a) the label for "%s" with LABELLED_TYPE for "const char*" and
+ (b) the label for "101" with LABELLED TYPE for "int"
+ where each one uses the other's type as OTHER_TYPE. */
+
+class range_label_for_type_mismatch : public range_label
+{
+ public:
+ range_label_for_type_mismatch (tree labelled_type, tree other_type)
+ : m_labelled_type (labelled_type), m_other_type (other_type)
+ {
+ }
+
+ label_text get_text (unsigned range_idx) const OVERRIDE;
+
+ protected:
+ tree m_labelled_type;
+ tree m_other_type;
+};
+
#endif /* GCC_RICH_LOCATION_H */
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 780d485..264204d 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -372,7 +372,6 @@ static void give_switch (int, int);
static int default_arg (const char *, int);
static void set_multilib_dir (void);
static void print_multilib_info (void);
-static void perror_with_name (const char *);
static void display_help (void);
static void add_preprocessor_option (const char *, int);
static void add_assembler_option (const char *, int);
@@ -981,20 +980,20 @@ proper position among the other output files. */
/* Linker command line options for -fsanitize= early on the command line. */
#ifndef SANITIZER_EARLY_SPEC
#define SANITIZER_EARLY_SPEC "\
-%{!nostdlib:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_EARLY_SPEC "} \
+%{!nostdlib:%{!r:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_EARLY_SPEC "} \
%{%:sanitize(thread):" LIBTSAN_EARLY_SPEC "} \
- %{%:sanitize(leak):" LIBLSAN_EARLY_SPEC "}}}"
+ %{%:sanitize(leak):" LIBLSAN_EARLY_SPEC "}}}}"
#endif
/* Linker command line options for -fsanitize= late on the command line. */
#ifndef SANITIZER_SPEC
#define SANITIZER_SPEC "\
-%{!nostdlib:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_SPEC "\
+%{!nostdlib:%{!r:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_SPEC "\
%{static:%ecannot specify -static with -fsanitize=address}}\
%{%:sanitize(thread):" LIBTSAN_SPEC "\
%{static:%ecannot specify -static with -fsanitize=thread}}\
%{%:sanitize(undefined):" LIBUBSAN_SPEC "}\
- %{%:sanitize(leak):" LIBLSAN_SPEC "}}}"
+ %{%:sanitize(leak):" LIBLSAN_SPEC "}}}}"
#endif
#ifndef POST_LINK_SPEC
@@ -1008,8 +1007,8 @@ proper position among the other output files. */
#ifndef VTABLE_VERIFICATION_SPEC
#if ENABLE_VTABLE_VERIFY
#define VTABLE_VERIFICATION_SPEC "\
-%{!nostdlib:%{fvtable-verify=std: -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end}\
- %{fvtable-verify=preinit: -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end}}"
+%{!nostdlib:%{!r:%{fvtable-verify=std: -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end}\
+ %{fvtable-verify=preinit: -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end}}}"
#else
#define VTABLE_VERIFICATION_SPEC "\
%{fvtable-verify=none:} \
@@ -1041,7 +1040,7 @@ proper position among the other output files. */
%{flto} %{fno-lto} %{flto=*} %l " LINK_PIE_SPEC \
"%{fuse-ld=*:-fuse-ld=%*} " LINK_COMPRESS_DEBUG_SPEC \
"%X %{o*} %{e*} %{N} %{n} %{r}\
- %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}} \
+ %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!r:%{!nostartfiles:%S}}} \
%{static|no-pie|static-pie:} %@{L*} %(mfwrap) %(link_libgcc) " \
VTABLE_VERIFICATION_SPEC " " SANITIZER_EARLY_SPEC " %o "" \
%{fopenacc|fopenmp|%:gt(%{ftree-parallelize-loops=*:%*} 1):\
@@ -1049,8 +1048,8 @@ proper position among the other output files. */
%{fgnu-tm:%:include(libitm.spec)%(link_itm)}\
%(mflib) " STACK_SPLIT_SPEC "\
%{fprofile-arcs|fprofile-generate*|coverage:-lgcov} " SANITIZER_SPEC " \
- %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
- %{!nostdlib:%{!nostartfiles:%E}} %{T*} \n%(post_link) }}}}}}"
+ %{!nostdlib:%{!r:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}}\
+ %{!nostdlib:%{!r:%{!nostartfiles:%E}}} %{T*} \n%(post_link) }}}}}}"
#endif
#ifndef LINK_LIBGCC_SPEC
@@ -2100,15 +2099,20 @@ load_specs (const char *filename)
/* Open and stat the file. */
desc = open (filename, O_RDONLY, 0);
if (desc < 0)
- pfatal_with_name (filename);
+ {
+ failed:
+ /* This leaves DESC open, but the OS will save us. */
+ fatal_error (input_location, "cannot read spec file %qs: %m", filename);
+ }
+
if (stat (filename, &statbuf) < 0)
- pfatal_with_name (filename);
+ goto failed;
/* Read contents of file into BUFFER. */
buffer = XNEWVEC (char, statbuf.st_size + 1);
readlen = read (desc, buffer, (unsigned) statbuf.st_size);
if (readlen < 0)
- pfatal_with_name (filename);
+ goto failed;
buffer[readlen] = 0;
close (desc);
@@ -2489,7 +2493,7 @@ do \
if (stat (NAME, &ST) >= 0 && S_ISREG (ST.st_mode)) \
if (unlink (NAME) < 0) \
if (VERBOSE_FLAG) \
- perror_with_name (NAME); \
+ error ("%s: %m", (NAME)); \
} while (0)
#endif
@@ -3168,13 +3172,11 @@ execute (void)
NULL, NULL, &err);
if (errmsg != NULL)
{
- if (err == 0)
- fatal_error (input_location, errmsg);
- else
- {
- errno = err;
- pfatal_with_name (errmsg);
- }
+ errno = err;
+ fatal_error (input_location,
+ err ? G_("cannot execute %qs: %s: %m")
+ : G_("cannot execute %qs: %s"),
+ string, errmsg);
}
if (i && string != commands[i].prog)
@@ -4544,10 +4546,8 @@ process_command (unsigned int decoded_options_count,
if (strcmp (fname, "-") != 0 && access (fname, F_OK) < 0)
{
- if (fname[0] == '@' && access (fname + 1, F_OK) < 0)
- perror_with_name (fname + 1);
- else
- perror_with_name (fname);
+ bool resp = fname[0] == '@' && access (fname + 1, F_OK) < 0;
+ error ("%s: %m", fname + resp);
}
else
add_infile (arg, spec_lang);
@@ -6885,13 +6885,11 @@ run_attempt (const char **new_argv, const char *out_temp,
err_temp, &err);
if (errmsg != NULL)
{
- if (err == 0)
- fatal_error (input_location, errmsg);
- else
- {
- errno = err;
- pfatal_with_name (errmsg);
- }
+ errno = err;
+ fatal_error (input_location,
+ err ? G_ ("cannot execute %qs: %s: %m")
+ : G_ ("cannot execute %qs: %s"),
+ new_argv[0], errmsg);
}
if (!pex_get_status (pex, 1, &exit_status))
@@ -8406,19 +8404,6 @@ save_string (const char *s, int len)
return result;
}
-void
-pfatal_with_name (const char *name)
-{
- perror_with_name (name);
- delete_temp_files ();
- exit (1);
-}
-
-static void
-perror_with_name (const char *name)
-{
- error ("%s: %m", name);
-}
static inline void
validate_switches_from_spec (const char *spec, bool user)
diff --git a/gcc/gcc.h b/gcc/gcc.h
index a760618..7bfa387 100644
--- a/gcc/gcc.h
+++ b/gcc/gcc.h
@@ -71,7 +71,6 @@ struct spec_function
/* These are exported by gcc.c. */
extern int do_spec (const char *);
extern void record_temp_file (const char *, int, int);
-extern void pfatal_with_name (const char *) ATTRIBUTE_NORETURN;
extern void set_input (const char *);
/* Spec files linked with gcc.c must provide definitions for these. */
diff --git a/gcc/gcov-dump.c b/gcc/gcov-dump.c
index 3ff11a6..7762e4e 100644
--- a/gcc/gcov-dump.c
+++ b/gcc/gcov-dump.c
@@ -38,9 +38,6 @@ static void tag_arcs (const char *, unsigned, unsigned, unsigned);
static void tag_lines (const char *, unsigned, unsigned, unsigned);
static void tag_counters (const char *, unsigned, unsigned, unsigned);
static void tag_summary (const char *, unsigned, unsigned, unsigned);
-static void dump_working_sets (const char *filename ATTRIBUTE_UNUSED,
- const gcov_summary *summary,
- unsigned depth);
extern int main (int, char **);
typedef struct tag_format
@@ -52,7 +49,6 @@ typedef struct tag_format
static int flag_dump_contents = 0;
static int flag_dump_positions = 0;
-static int flag_dump_working_sets = 0;
static const struct option options[] =
{
@@ -60,7 +56,6 @@ static const struct option options[] =
{ "version", no_argument, NULL, 'v' },
{ "long", no_argument, NULL, 'l' },
{ "positions", no_argument, NULL, 'o' },
- { "working-sets", no_argument, NULL, 'w' },
{ 0, 0, 0, 0 }
};
@@ -77,7 +72,6 @@ static const tag_format_t tag_table[] =
{GCOV_TAG_ARCS, "ARCS", tag_arcs},
{GCOV_TAG_LINES, "LINES", tag_lines},
{GCOV_TAG_OBJECT_SUMMARY, "OBJECT_SUMMARY", tag_summary},
- {GCOV_TAG_PROGRAM_SUMMARY, "PROGRAM_SUMMARY", tag_summary},
{0, NULL, NULL}
};
@@ -117,9 +111,6 @@ main (int argc ATTRIBUTE_UNUSED, char **argv)
case 'p':
flag_dump_positions = 1;
break;
- case 'w':
- flag_dump_working_sets = 1;
- break;
default:
fprintf (stderr, "unknown flag `%c'\n", opt);
}
@@ -139,7 +130,6 @@ print_usage (void)
printf (" -l, --long Dump record contents too\n");
printf (" -p, --positions Dump record positions\n");
printf (" -v, --version Print version number\n");
- printf (" -w, --working-sets Dump working set computed from summary\n");
printf ("\nFor bug reporting instructions, please see:\n%s.\n",
bug_report_url);
}
@@ -465,75 +455,10 @@ tag_counters (const char *filename ATTRIBUTE_UNUSED,
static void
tag_summary (const char *filename ATTRIBUTE_UNUSED,
unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED,
- unsigned depth)
+ unsigned depth ATTRIBUTE_UNUSED)
{
gcov_summary summary;
- unsigned h_ix;
- gcov_bucket_type *histo_bucket;
-
gcov_read_summary (&summary);
- printf (" checksum=0x%08x", summary.checksum);
-
- printf ("\n");
- print_prefix (filename, depth, 0);
- printf (VALUE_PADDING_PREFIX "counts=%u, runs=%u",
- summary.num, summary.runs);
-
- printf (", sum_all=%" PRId64,
- (int64_t)summary.sum_all);
- printf (", run_max=%" PRId64,
- (int64_t)summary.run_max);
- printf (", sum_max=%" PRId64,
- (int64_t)summary.sum_max);
- printf ("\n");
- print_prefix (filename, depth, 0);
- printf (VALUE_PADDING_PREFIX "counter histogram:");
- for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
- {
- histo_bucket = &summary.histogram[h_ix];
- if (!histo_bucket->num_counters)
- continue;
- printf ("\n");
- print_prefix (filename, depth, 0);
- printf (VALUE_PADDING_PREFIX VALUE_PREFIX "num counts=%u, "
- "min counter=%" PRId64 ", cum_counter=%" PRId64,
- h_ix, histo_bucket->num_counters,
- (int64_t)histo_bucket->min_value,
- (int64_t)histo_bucket->cum_value);
- }
- if (flag_dump_working_sets)
- dump_working_sets (filename, &summary, depth);
-}
-
-static void
-dump_working_sets (const char *filename ATTRIBUTE_UNUSED,
- const gcov_summary *summary,
- unsigned depth)
-{
- gcov_working_set_t gcov_working_sets[NUM_GCOV_WORKING_SETS];
- unsigned ws_ix, pctinc, pct;
- gcov_working_set_t *ws_info;
-
- compute_working_sets (summary, gcov_working_sets);
-
- printf ("\n");
- print_prefix (filename, depth, 0);
- printf (VALUE_PADDING_PREFIX "counter working sets:");
- /* Multiply the percentage by 100 to avoid float. */
- pctinc = 100 * 100 / NUM_GCOV_WORKING_SETS;
- for (ws_ix = 0, pct = pctinc; ws_ix < NUM_GCOV_WORKING_SETS;
- ws_ix++, pct += pctinc)
- {
- if (ws_ix == NUM_GCOV_WORKING_SETS - 1)
- pct = 9990;
- ws_info = &gcov_working_sets[ws_ix];
- /* Print out the percentage using int arithmatic to avoid float. */
- printf ("\n");
- print_prefix (filename, depth + 1, 0);
- printf (VALUE_PADDING_PREFIX "%u.%02u%%: num counts=%u, min counter="
- "%" PRId64,
- pct / 100, pct - (pct / 100 * 100),
- ws_info->num_counters,
- (int64_t)ws_info->min_counter);
- }
+ printf (" runs=%d, sum_max=%" PRId64,
+ summary.runs, summary.sum_max);
}
diff --git a/gcc/gcov-io.c b/gcc/gcov-io.c
index 311e4d0..63cc7fc 100644
--- a/gcc/gcov-io.c
+++ b/gcc/gcov-io.c
@@ -446,39 +446,11 @@ gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length)
GCOV_LINKAGE void
gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary *summary)
{
- unsigned h_ix, bv_ix, h_cnt = 0;
- unsigned histo_bitvector[GCOV_HISTOGRAM_BITVECTOR_SIZE];
-
- /* Count number of non-zero histogram entries, and fill in a bit vector
- of non-zero indices. The histogram is only currently computed for arc
- counters. */
- for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++)
- histo_bitvector[bv_ix] = 0;
- for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
- if (summary->histogram[h_ix].num_counters)
- {
- histo_bitvector[h_ix / 32] |= 1 << (h_ix % 32);
- h_cnt++;
- }
- gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH (h_cnt));
- gcov_write_unsigned (summary->checksum);
-
- gcov_write_unsigned (summary->num);
+ gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH);
gcov_write_unsigned (summary->runs);
- gcov_write_counter (summary->sum_all);
- gcov_write_counter (summary->run_max);
- gcov_write_counter (summary->sum_max);
- for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++)
- gcov_write_unsigned (histo_bitvector[bv_ix]);
- for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
- {
- if (!summary->histogram[h_ix].num_counters)
- continue;
- gcov_write_unsigned (summary->histogram[h_ix].num_counters);
- gcov_write_counter (summary->histogram[h_ix].min_value);
- gcov_write_counter (summary->histogram[h_ix].cum_value);
- }
+ gcov_write_unsigned (summary->sum_max);
}
+
#endif /* IN_LIBGCOV */
#endif /*!IN_GCOV */
@@ -637,65 +609,8 @@ gcov_read_string (void)
GCOV_LINKAGE void
gcov_read_summary (struct gcov_summary *summary)
{
- unsigned h_ix, bv_ix, h_cnt = 0;
- unsigned histo_bitvector[GCOV_HISTOGRAM_BITVECTOR_SIZE];
- unsigned cur_bitvector;
-
- summary->checksum = gcov_read_unsigned ();
- summary->num = gcov_read_unsigned ();
summary->runs = gcov_read_unsigned ();
- summary->sum_all = gcov_read_counter ();
- summary->run_max = gcov_read_counter ();
- summary->sum_max = gcov_read_counter ();
- memset (summary->histogram, 0,
- sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
- for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++)
- {
- histo_bitvector[bv_ix] = gcov_read_unsigned ();
-#if IN_LIBGCOV
- /* When building libgcov we don't include system.h, which includes
- hwint.h (where popcount_hwi is declared). However, libgcov.a
- is built by the bootstrapped compiler and therefore the builtins
- are always available. */
- h_cnt += __builtin_popcount (histo_bitvector[bv_ix]);
-#else
- h_cnt += popcount_hwi (histo_bitvector[bv_ix]);
-#endif
- }
- bv_ix = 0;
- h_ix = 0;
- cur_bitvector = 0;
- while (h_cnt--)
- {
- /* Find the index corresponding to the next entry we will read in.
- First find the next non-zero bitvector and re-initialize
- the histogram index accordingly, then right shift and increment
- the index until we find a set bit. */
- while (!cur_bitvector)
- {
- h_ix = bv_ix * 32;
- if (bv_ix >= GCOV_HISTOGRAM_BITVECTOR_SIZE)
- gcov_error ("corrupted profile info: summary histogram "
- "bitvector is corrupt");
- cur_bitvector = histo_bitvector[bv_ix++];
- }
- while (!(cur_bitvector & 0x1))
- {
- h_ix++;
- cur_bitvector >>= 1;
- }
- if (h_ix >= GCOV_HISTOGRAM_SIZE)
- gcov_error ("corrupted profile info: summary histogram "
- "index is corrupt");
-
- summary->histogram[h_ix].num_counters = gcov_read_unsigned ();
- summary->histogram[h_ix].min_value = gcov_read_counter ();
- summary->histogram[h_ix].cum_value = gcov_read_counter ();
- /* Shift off the index we are done with and increment to the
- corresponding next histogram entry. */
- cur_bitvector >>= 1;
- h_ix++;
- }
+ summary->sum_max = gcov_read_unsigned ();
}
/* We need to expose the below function when compiling for gcov-tool. */
@@ -747,308 +662,3 @@ gcov_time (void)
return status.st_mtime;
}
#endif /* IN_GCOV */
-
-#if !IN_GCOV
-/* Determine the index into histogram for VALUE. */
-
-#if IN_LIBGCOV
-static unsigned
-#else
-GCOV_LINKAGE unsigned
-#endif
-gcov_histo_index (gcov_type value)
-{
- gcov_type_unsigned v = (gcov_type_unsigned)value;
- unsigned r = 0;
- unsigned prev2bits = 0;
-
- /* Find index into log2 scale histogram, where each of the log2
- sized buckets is divided into 4 linear sub-buckets for better
- focus in the higher buckets. */
-
- /* Find the place of the most-significant bit set. */
- if (v > 0)
- {
-#if IN_LIBGCOV
- /* When building libgcov we don't include system.h, which includes
- hwint.h (where floor_log2 is declared). However, libgcov.a
- is built by the bootstrapped compiler and therefore the builtins
- are always available. */
- r = sizeof (long long) * __CHAR_BIT__ - 1 - __builtin_clzll (v);
-#else
- /* We use floor_log2 from hwint.c, which takes a HOST_WIDE_INT
- that is 64 bits and gcov_type_unsigned is 64 bits. */
- r = floor_log2 (v);
-#endif
- }
-
- /* If at most the 2 least significant bits are set (value is
- 0 - 3) then that value is our index into the lowest set of
- four buckets. */
- if (r < 2)
- return (unsigned)value;
-
- gcov_nonruntime_assert (r < 64);
-
- /* Find the two next most significant bits to determine which
- of the four linear sub-buckets to select. */
- prev2bits = (v >> (r - 2)) & 0x3;
- /* Finally, compose the final bucket index from the log2 index and
- the next 2 bits. The minimum r value at this point is 2 since we
- returned above if r was 2 or more, so the minimum bucket at this
- point is 4. */
- return (r - 1) * 4 + prev2bits;
-}
-
-/* Merge SRC_HISTO into TGT_HISTO. The counters are assumed to be in
- the same relative order in both histograms, and are matched up
- and merged in reverse order. Each counter is assigned an equal portion of
- its entry's original cumulative counter value when computing the
- new merged cum_value. */
-
-static void gcov_histogram_merge (gcov_bucket_type *tgt_histo,
- gcov_bucket_type *src_histo)
-{
- int src_i, tgt_i, tmp_i = 0;
- unsigned src_num, tgt_num, merge_num;
- gcov_type src_cum, tgt_cum, merge_src_cum, merge_tgt_cum, merge_cum;
- gcov_type merge_min;
- gcov_bucket_type tmp_histo[GCOV_HISTOGRAM_SIZE];
- int src_done = 0;
-
- memset (tmp_histo, 0, sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
-
- /* Assume that the counters are in the same relative order in both
- histograms. Walk the histograms from largest to smallest entry,
- matching up and combining counters in order. */
- src_num = 0;
- src_cum = 0;
- src_i = GCOV_HISTOGRAM_SIZE - 1;
- for (tgt_i = GCOV_HISTOGRAM_SIZE - 1; tgt_i >= 0 && !src_done; tgt_i--)
- {
- tgt_num = tgt_histo[tgt_i].num_counters;
- tgt_cum = tgt_histo[tgt_i].cum_value;
- /* Keep going until all of the target histogram's counters at this
- position have been matched and merged with counters from the
- source histogram. */
- while (tgt_num > 0 && !src_done)
- {
- /* If this is either the first time through this loop or we just
- exhausted the previous non-zero source histogram entry, look
- for the next non-zero source histogram entry. */
- if (!src_num)
- {
- /* Locate the next non-zero entry. */
- while (src_i >= 0 && !src_histo[src_i].num_counters)
- src_i--;
- /* If source histogram has fewer counters, then just copy over the
- remaining target counters and quit. */
- if (src_i < 0)
- {
- tmp_histo[tgt_i].num_counters += tgt_num;
- tmp_histo[tgt_i].cum_value += tgt_cum;
- if (!tmp_histo[tgt_i].min_value ||
- tgt_histo[tgt_i].min_value < tmp_histo[tgt_i].min_value)
- tmp_histo[tgt_i].min_value = tgt_histo[tgt_i].min_value;
- while (--tgt_i >= 0)
- {
- tmp_histo[tgt_i].num_counters
- += tgt_histo[tgt_i].num_counters;
- tmp_histo[tgt_i].cum_value += tgt_histo[tgt_i].cum_value;
- if (!tmp_histo[tgt_i].min_value ||
- tgt_histo[tgt_i].min_value
- < tmp_histo[tgt_i].min_value)
- tmp_histo[tgt_i].min_value = tgt_histo[tgt_i].min_value;
- }
-
- src_done = 1;
- break;
- }
-
- src_num = src_histo[src_i].num_counters;
- src_cum = src_histo[src_i].cum_value;
- }
-
- /* The number of counters to merge on this pass is the minimum
- of the remaining counters from the current target and source
- histogram entries. */
- merge_num = tgt_num;
- if (src_num < merge_num)
- merge_num = src_num;
-
- /* The merged min_value is the sum of the min_values from target
- and source. */
- merge_min = tgt_histo[tgt_i].min_value + src_histo[src_i].min_value;
-
- /* Compute the portion of source and target entries' cum_value
- that will be apportioned to the counters being merged.
- The total remaining cum_value from each entry is divided
- equally among the counters from that histogram entry if we
- are not merging all of them. */
- merge_src_cum = src_cum;
- if (merge_num < src_num)
- merge_src_cum = merge_num * src_cum / src_num;
- merge_tgt_cum = tgt_cum;
- if (merge_num < tgt_num)
- merge_tgt_cum = merge_num * tgt_cum / tgt_num;
- /* The merged cum_value is the sum of the source and target
- components. */
- merge_cum = merge_src_cum + merge_tgt_cum;
-
- /* Update the remaining number of counters and cum_value left
- to be merged from this source and target entry. */
- src_cum -= merge_src_cum;
- tgt_cum -= merge_tgt_cum;
- src_num -= merge_num;
- tgt_num -= merge_num;
-
- /* The merged counters get placed in the new merged histogram
- at the entry for the merged min_value. */
- tmp_i = gcov_histo_index (merge_min);
- gcov_nonruntime_assert (tmp_i < GCOV_HISTOGRAM_SIZE);
- tmp_histo[tmp_i].num_counters += merge_num;
- tmp_histo[tmp_i].cum_value += merge_cum;
- if (!tmp_histo[tmp_i].min_value ||
- merge_min < tmp_histo[tmp_i].min_value)
- tmp_histo[tmp_i].min_value = merge_min;
-
- /* Ensure the search for the next non-zero src_histo entry starts
- at the next smallest histogram bucket. */
- if (!src_num)
- src_i--;
- }
- }
-
- gcov_nonruntime_assert (tgt_i < 0);
-
- /* In the case where there were more counters in the source histogram,
- accumulate the remaining unmerged cumulative counter values. Add
- those to the smallest non-zero target histogram entry. Otherwise,
- the total cumulative counter values in the histogram will be smaller
- than the sum_all stored in the summary, which will complicate
- computing the working set information from the histogram later on. */
- if (src_num)
- src_i--;
- while (src_i >= 0)
- {
- src_cum += src_histo[src_i].cum_value;
- src_i--;
- }
- /* At this point, tmp_i should be the smallest non-zero entry in the
- tmp_histo. */
- gcov_nonruntime_assert (tmp_i >= 0 && tmp_i < GCOV_HISTOGRAM_SIZE
- && tmp_histo[tmp_i].num_counters > 0);
- tmp_histo[tmp_i].cum_value += src_cum;
-
- /* Finally, copy the merged histogram into tgt_histo. */
- memcpy (tgt_histo, tmp_histo,
- sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
-}
-#endif /* !IN_GCOV */
-
-/* This is used by gcov-dump (IN_GCOV == -1) and in the compiler
- (!IN_GCOV && !IN_LIBGCOV). */
-#if IN_GCOV <= 0 && !IN_LIBGCOV
-/* Compute the working set information from the counter histogram in
- the profile summary. This is an array of information corresponding to a
- range of percentages of the total execution count (sum_all), and includes
- the number of counters required to cover that working set percentage and
- the minimum counter value in that working set. */
-
-GCOV_LINKAGE void
-compute_working_sets (const gcov_summary *summary,
- gcov_working_set_t *gcov_working_sets)
-{
- gcov_type working_set_cum_values[NUM_GCOV_WORKING_SETS];
- gcov_type ws_cum_hotness_incr;
- gcov_type cum, tmp_cum;
- const gcov_bucket_type *histo_bucket;
- unsigned ws_ix, c_num, count;
- int h_ix;
-
- /* Compute the amount of sum_all that the cumulative hotness grows
- by in each successive working set entry, which depends on the
- number of working set entries. */
- ws_cum_hotness_incr = summary->sum_all / NUM_GCOV_WORKING_SETS;
-
- /* Next fill in an array of the cumulative hotness values corresponding
- to each working set summary entry we are going to compute below.
- Skip 0% statistics, which can be extrapolated from the
- rest of the summary data. */
- cum = ws_cum_hotness_incr;
- for (ws_ix = 0; ws_ix < NUM_GCOV_WORKING_SETS;
- ws_ix++, cum += ws_cum_hotness_incr)
- working_set_cum_values[ws_ix] = cum;
- /* The last summary entry is reserved for (roughly) 99.9% of the
- working set. Divide by 1024 so it becomes a shift, which gives
- almost exactly 99.9%. */
- working_set_cum_values[NUM_GCOV_WORKING_SETS-1]
- = summary->sum_all - summary->sum_all/1024;
-
- /* Next, walk through the histogram in decending order of hotness
- and compute the statistics for the working set summary array.
- As histogram entries are accumulated, we check to see which
- working set entries have had their expected cum_value reached
- and fill them in, walking the working set entries in increasing
- size of cum_value. */
- ws_ix = 0; /* The current entry into the working set array. */
- cum = 0; /* The current accumulated counter sum. */
- count = 0; /* The current accumulated count of block counters. */
- for (h_ix = GCOV_HISTOGRAM_SIZE - 1;
- h_ix >= 0 && ws_ix < NUM_GCOV_WORKING_SETS; h_ix--)
- {
- histo_bucket = &summary->histogram[h_ix];
-
- /* If we haven't reached the required cumulative counter value for
- the current working set percentage, simply accumulate this histogram
- entry into the running sums and continue to the next histogram
- entry. */
- if (cum + histo_bucket->cum_value < working_set_cum_values[ws_ix])
- {
- cum += histo_bucket->cum_value;
- count += histo_bucket->num_counters;
- continue;
- }
-
- /* If adding the current histogram entry's cumulative counter value
- causes us to exceed the current working set size, then estimate
- how many of this histogram entry's counter values are required to
- reach the working set size, and fill in working set entries
- as we reach their expected cumulative value. */
- for (c_num = 0, tmp_cum = cum;
- c_num < histo_bucket->num_counters && ws_ix < NUM_GCOV_WORKING_SETS;
- c_num++)
- {
- count++;
- /* If we haven't reached the last histogram entry counter, add
- in the minimum value again. This will underestimate the
- cumulative sum so far, because many of the counter values in this
- entry may have been larger than the minimum. We could add in the
- average value every time, but that would require an expensive
- divide operation. */
- if (c_num + 1 < histo_bucket->num_counters)
- tmp_cum += histo_bucket->min_value;
- /* If we have reached the last histogram entry counter, then add
- in the entire cumulative value. */
- else
- tmp_cum = cum + histo_bucket->cum_value;
-
- /* Next walk through successive working set entries and fill in
- the statistics for any whose size we have reached by accumulating
- this histogram counter. */
- while (ws_ix < NUM_GCOV_WORKING_SETS
- && tmp_cum >= working_set_cum_values[ws_ix])
- {
- gcov_working_sets[ws_ix].num_counters = count;
- gcov_working_sets[ws_ix].min_counter
- = histo_bucket->min_value;
- ws_ix++;
- }
- }
- /* Finally, update the running cumulative value since we were
- using a temporary above. */
- cum += histo_bucket->cum_value;
- }
- gcov_nonruntime_assert (ws_ix == NUM_GCOV_WORKING_SETS);
-}
-#endif /* IN_GCOV <= 0 && !IN_LIBGCOV */
diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h
index 7a11f0a..1fc31f5 100644
--- a/gcc/gcov-io.h
+++ b/gcc/gcov-io.h
@@ -133,17 +133,14 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
blocks they are for.
The data file contains the following records.
- data: {unit summary:object summary:program* function-data*}*
+ data: {unit summary:object function-data*}*
unit: header int32:checksum
- function-data: announce_function present counts
+ function-data: announce_function present counts
announce_function: header int32:ident
int32:lineno_checksum int32:cfg_checksum
present: header int32:present
counts: header int64:count*
- summary: int32:checksum int32:num int32:runs int64:sum
- int64:max int64:sum_max histogram
- histogram: {int32:bitvector}8 histogram-buckets*
- histogram-buckets: int32:num int64:min int64:sum
+ summary: int32:checksum int32:runs int32:sum_max
The ANNOUNCE_FUNCTION record is the same as that in the note file,
but without the source location. The COUNTS gives the
@@ -190,7 +187,7 @@ typedef uint64_t gcov_type_unsigned;
#define ATTRIBUTE_HIDDEN
-#endif /* !IN_LIBGOCV */
+#endif /* !IN_LIBGCOV */
#ifndef GCOV_LINKAGE
#define GCOV_LINKAGE extern
@@ -240,9 +237,9 @@ typedef uint64_t gcov_type_unsigned;
#define GCOV_TAG_COUNTER_BASE ((gcov_unsigned_t)0x01a10000)
#define GCOV_TAG_COUNTER_LENGTH(NUM) ((NUM) * 2)
#define GCOV_TAG_COUNTER_NUM(LENGTH) ((LENGTH) / 2)
-#define GCOV_TAG_OBJECT_SUMMARY ((gcov_unsigned_t)0xa1000000) /* Obsolete */
-#define GCOV_TAG_PROGRAM_SUMMARY ((gcov_unsigned_t)0xa3000000)
-#define GCOV_TAG_SUMMARY_LENGTH(NUM) (1 + (10 + 3 * 2) + (NUM) * 5)
+#define GCOV_TAG_OBJECT_SUMMARY ((gcov_unsigned_t)0xa1000000)
+#define GCOV_TAG_PROGRAM_SUMMARY ((gcov_unsigned_t)0xa3000000) /* Obsolete */
+#define GCOV_TAG_SUMMARY_LENGTH (2)
#define GCOV_TAG_AFDO_FILE_NAMES ((gcov_unsigned_t)0xaa000000)
#define GCOV_TAG_AFDO_FUNCTION ((gcov_unsigned_t)0xac000000)
#define GCOV_TAG_AFDO_WORKING_SET ((gcov_unsigned_t)0xaf000000)
@@ -307,43 +304,12 @@ GCOV_COUNTERS
#define GCOV_ARC_FAKE (1 << 1)
#define GCOV_ARC_FALLTHROUGH (1 << 2)
-/* Structured records. */
-
-/* Structure used for each bucket of the log2 histogram of counter values. */
-typedef struct
-{
- /* Number of counters whose profile count falls within the bucket. */
- gcov_unsigned_t num_counters;
- /* Smallest profile count included in this bucket. */
- gcov_type min_value;
- /* Cumulative value of the profile counts in this bucket. */
- gcov_type cum_value;
-} gcov_bucket_type;
-
-/* For a log2 scale histogram with each range split into 4
- linear sub-ranges, there will be at most 64 (max gcov_type bit size) - 1 log2
- ranges since the lowest 2 log2 values share the lowest 4 linear
- sub-range (values 0 - 3). This is 252 total entries (63*4). */
-
-#define GCOV_HISTOGRAM_SIZE 252
-
-/* How many unsigned ints are required to hold a bit vector of non-zero
- histogram entries when the histogram is written to the gcov file.
- This is essentially a ceiling divide by 32 bits. */
-#define GCOV_HISTOGRAM_BITVECTOR_SIZE (GCOV_HISTOGRAM_SIZE + 31) / 32
-
/* Object & program summary record. */
struct gcov_summary
{
- gcov_unsigned_t checksum; /* Checksum of program. */
- gcov_unsigned_t num; /* Number of counters. */
gcov_unsigned_t runs; /* Number of program runs. */
- gcov_type sum_all; /* Sum of all counters accumulated. */
- gcov_type run_max; /* Maximum value on a single run. */
gcov_type sum_max; /* Sum of individual run max values. */
- gcov_bucket_type histogram[GCOV_HISTOGRAM_SIZE]; /* Histogram of
- counter values. */
};
#if !defined(inhibit_libc)
@@ -380,35 +346,12 @@ GCOV_LINKAGE void gcov_write_unsigned (gcov_unsigned_t) ATTRIBUTE_HIDDEN;
#if !IN_GCOV && !IN_LIBGCOV
/* Available only in compiler */
-GCOV_LINKAGE unsigned gcov_histo_index (gcov_type value);
GCOV_LINKAGE void gcov_write_string (const char *);
GCOV_LINKAGE void gcov_write_filename (const char *);
GCOV_LINKAGE gcov_position_t gcov_write_tag (gcov_unsigned_t);
GCOV_LINKAGE void gcov_write_length (gcov_position_t /*position*/);
#endif
-#if IN_GCOV <= 0 && !IN_LIBGCOV
-/* Available in gcov-dump and the compiler. */
-
-/* Number of data points in the working set summary array. Using 128
- provides information for at least every 1% increment of the total
- profile size. The last entry is hardwired to 99.9% of the total. */
-#define NUM_GCOV_WORKING_SETS 128
-
-/* Working set size statistics for a given percentage of the entire
- profile (sum_all from the counter summary). */
-typedef struct gcov_working_set_info
-{
- /* Number of hot counters included in this working set. */
- unsigned num_counters;
- /* Smallest counter included in this working set. */
- gcov_type min_counter;
-} gcov_working_set_t;
-
-GCOV_LINKAGE void compute_working_sets (const gcov_summary *summary,
- gcov_working_set_t *gcov_working_sets);
-#endif
-
#if IN_GCOV > 0
/* Available in gcov */
GCOV_LINKAGE time_t gcov_time (void);
diff --git a/gcc/gcov-tool.c b/gcc/gcov-tool.c
index 15fd710..88539f9 100644
--- a/gcc/gcov-tool.c
+++ b/gcc/gcov-tool.c
@@ -423,7 +423,6 @@ print_overlap_usage_message (int error_p)
fnotice (file, " -o, --object Print object level info\n");
fnotice (file, " -t <float>, --hot_threshold <float> Set the threshold for hotness\n");
fnotice (file, " -v, --verbose Verbose mode\n");
-
}
static const struct option overlap_options[] =
diff --git a/gcc/gcov.c b/gcc/gcov.c
index 78a3e0e..e255e4e 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -339,13 +339,16 @@ struct source_info
coverage_info coverage;
+ /* Maximum line count in the source file. */
+ unsigned int maximum_count;
+
/* Functions in this source file. These are in ascending line
number order. */
vector <function_info *> functions;
};
source_info::source_info (): index (0), name (NULL), file_time (),
- lines (), coverage (), functions ()
+ lines (), coverage (), maximum_count (0), functions ()
{
}
@@ -408,10 +411,13 @@ static vector<source_info> sources;
/* Mapping of file names to sources */
static vector<name_map> names;
+/* Record all processed files in order to warn about
+ a file being read multiple times. */
+static vector<char *> processed_files;
+
/* This holds data summary information. */
static unsigned object_runs;
-static unsigned program_count;
static unsigned total_lines;
static unsigned total_executed;
@@ -498,6 +504,10 @@ static int flag_verbose = 0;
static int flag_use_colors = 0;
+/* Use perf-like colors to indicate hot lines. */
+
+static int flag_use_hotness_colors = 0;
+
/* Output count information for every basic block, not merely those
that contain line number information. */
@@ -543,6 +553,7 @@ static int process_args (int, char **);
static void print_usage (int) ATTRIBUTE_NORETURN;
static void print_version (void) ATTRIBUTE_NORETURN;
static void process_file (const char *);
+static void process_all_functions (void);
static void generate_results (const char *);
static void create_file_names (const char *);
static char *canonicalize_name (const char *);
@@ -798,6 +809,7 @@ main (int argc, char **argv)
if (flag_intermediate_format || argno == argc - 1)
{
+ process_all_functions ();
generate_results (argv[argno]);
release_structures ();
}
@@ -833,6 +845,7 @@ print_usage (int error_p)
fnotice (file, " -n, --no-output Do not create an output file\n");
fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
+ fnotice (file, " -q, --use-hotness-colors Emit perf-like colored output for hot lines\n");
fnotice (file, " -r, --relative-only Only show data for relative sources\n");
fnotice (file, " -s, --source-prefix DIR Source prefix to elide\n");
fnotice (file, " -t, --stdout Output to stdout instead of a file\n");
@@ -884,6 +897,7 @@ static const struct option options[] =
{ "display-progress", no_argument, NULL, 'd' },
{ "hash-filenames", no_argument, NULL, 'x' },
{ "use-colors", no_argument, NULL, 'k' },
+ { "use-hotness-colors", no_argument, NULL, 'q' },
{ 0, 0, 0, 0 }
};
@@ -894,7 +908,7 @@ process_args (int argc, char **argv)
{
int opt;
- const char *opts = "abcdfhijklmno:prs:tuvwx";
+ const char *opts = "abcdfhijklmno:pqrs:tuvwx";
while ((opt = getopt_long (argc, argv, opts, options, NULL)) != -1)
{
switch (opt)
@@ -923,6 +937,9 @@ process_args (int argc, char **argv)
case 'k':
flag_use_colors = 1;
break;
+ case 'q':
+ flag_use_hotness_colors = 1;
+ break;
case 'm':
flag_demangled_names = 1;
break;
@@ -1079,7 +1096,8 @@ output_intermediate_file (FILE *gcov_file, source_info *src)
}
/* Follow with lines associated with the source file. */
- output_intermediate_line (gcov_file, &src->lines[line_num], line_num);
+ if (line_num < src->lines.size ())
+ output_intermediate_line (gcov_file, &src->lines[line_num], line_num);
}
}
@@ -1144,12 +1162,26 @@ static void
process_file (const char *file_name)
{
create_file_names (file_name);
- read_graph_file ();
- if (functions.empty ())
- return;
+ for (unsigned i = 0; i < processed_files.size (); i++)
+ if (strcmp (da_file_name, processed_files[i]) == 0)
+ {
+ fnotice (stderr, "'%s' file is already processed\n",
+ file_name);
+ return;
+ }
+
+ processed_files.push_back (xstrdup (da_file_name));
+
+ read_graph_file ();
read_count_file ();
+}
+
+/* Process all functions in all files. */
+static void
+process_all_functions (void)
+{
hash_map<function_start_pair_hash, function_info *> fn_map;
/* Identify group functions. */
@@ -1226,7 +1258,6 @@ process_file (const char *file_name)
if (fn->is_group)
fn->lines.resize (fn->end_line - fn->start_line + 1);
-
solve_flow_graph (fn);
if (fn->has_catch)
find_exception_blocks (fn);
@@ -1797,12 +1828,11 @@ read_count_file (void)
unsigned length = gcov_read_unsigned ();
unsigned long base = gcov_position ();
- if (tag == GCOV_TAG_PROGRAM_SUMMARY)
+ if (tag == GCOV_TAG_OBJECT_SUMMARY)
{
struct gcov_summary summary;
gcov_read_summary (&summary);
- object_runs += summary.runs;
- program_count++;
+ object_runs = summary.runs;
}
else if (tag == GCOV_TAG_FUNCTION && !length)
; /* placeholder */
@@ -2197,8 +2227,8 @@ format_count (gcov_type count)
if (count + divisor / 2 < 1000 * divisor)
break;
}
- gcov_type r = (count + divisor / 2) / divisor;
- sprintf (buffer, "%" PRId64 "%c", r, units[i]);
+ float r = 1.0f * count / divisor;
+ sprintf (buffer, "%.1f%c", r, units[i]);
return buffer;
}
@@ -2561,6 +2591,9 @@ static void accumulate_line_info (line_info *line, source_info *src,
/* Now, add the count of loops entirely on this line. */
count += get_cycles_count (*line);
line->count = count;
+
+ if (line->count > src->maximum_count)
+ src->maximum_count = line->count;
}
if (line->exists && add_coverage)
@@ -2737,7 +2770,8 @@ output_line_beginning (FILE *f, bool exists, bool unexceptional,
bool has_unexecuted_block,
gcov_type count, unsigned line_num,
const char *exceptional_string,
- const char *unexceptional_string)
+ const char *unexceptional_string,
+ unsigned int maximum_count)
{
string s;
if (exists)
@@ -2787,7 +2821,23 @@ output_line_beginning (FILE *f, bool exists, bool unexceptional,
pad_count_string (s);
}
- fprintf (f, "%s:%5u", s.c_str (), line_num);
+ /* Format line number in output. */
+ char buffer[16];
+ sprintf (buffer, "%5u", line_num);
+ string linestr (buffer);
+
+ if (flag_use_hotness_colors && maximum_count)
+ {
+ if (count * 2 > maximum_count) /* > 50%. */
+ linestr.insert (0, SGR_SEQ (COLOR_BG_RED));
+ else if (count * 5 > maximum_count) /* > 20%. */
+ linestr.insert (0, SGR_SEQ (COLOR_BG_YELLOW));
+ else if (count * 10 > maximum_count) /* > 10%. */
+ linestr.insert (0, SGR_SEQ (COLOR_BG_GREEN));
+ linestr += SGR_RESET;
+ }
+
+ fprintf (f, "%s:%s", s.c_str (), linestr.c_str ());
}
static void
@@ -2820,7 +2870,7 @@ output_line_details (FILE *f, const line_info *line, unsigned line_num)
output_line_beginning (f, line->exists,
(*it)->exceptional, false,
(*it)->count, line_num,
- "%%%%%", "$$$$$");
+ "%%%%%", "$$$$$", 0);
fprintf (f, "-block %2d", ix++);
if (flag_verbose)
fprintf (f, " (BB %u)", (*it)->id);
@@ -2883,6 +2933,25 @@ output_lines (FILE *gcov_file, const source_info *src)
FILE *source_file;
const char *retval;
+ /* Print colorization legend. */
+ if (flag_use_colors)
+ fprintf (gcov_file, "%s",
+ DEFAULT_LINE_START "Colorization: profile count: " \
+ SGR_SEQ (COLOR_BG_CYAN) "zero coverage (exceptional)" SGR_RESET \
+ " " \
+ SGR_SEQ (COLOR_BG_RED) "zero coverage (unexceptional)" SGR_RESET \
+ " " \
+ SGR_SEQ (COLOR_BG_MAGENTA) "unexecuted block" SGR_RESET "\n");
+
+ if (flag_use_hotness_colors)
+ fprintf (gcov_file, "%s",
+ DEFAULT_LINE_START "Colorization: line numbers: hotness: " \
+ SGR_SEQ (COLOR_BG_RED) "> 50%" SGR_RESET " " \
+ SGR_SEQ (COLOR_BG_YELLOW) "> 20%" SGR_RESET " " \
+ SGR_SEQ (COLOR_BG_GREEN) "> 10%" SGR_RESET "\n");
+
+ fprintf (gcov_file, DEFAULT_LINE_START "Source:%s\n", src->coverage.name);
+
fprintf (gcov_file, DEFAULT_LINE_START "Source:%s\n", src->coverage.name);
if (!multiple_files)
{
@@ -2891,7 +2960,6 @@ output_lines (FILE *gcov_file, const source_info *src)
no_data_file ? "-" : da_file_name);
fprintf (gcov_file, DEFAULT_LINE_START "Runs:%u\n", object_runs);
}
- fprintf (gcov_file, DEFAULT_LINE_START "Programs:%u\n", program_count);
source_file = fopen (src->name, "r");
if (!source_file)
@@ -2945,7 +3013,7 @@ output_lines (FILE *gcov_file, const source_info *src)
line so that tabs won't be messed up. */
output_line_beginning (gcov_file, line->exists, line->unexceptional,
line->has_unexecuted_block, line->count,
- line_num, "=====", "#####");
+ line_num, "=====", "#####", src->maximum_count);
print_source_line (gcov_file, source_lines, line_num);
output_line_details (gcov_file, line, line_num);
@@ -2990,7 +3058,8 @@ output_lines (FILE *gcov_file, const source_info *src)
line->unexceptional,
line->has_unexecuted_block,
line->count,
- l, "=====", "#####");
+ l, "=====", "#####",
+ src->maximum_count);
print_source_line (gcov_file, source_lines, l);
output_line_details (gcov_file, line, l);
diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c
index f9b0bc9..d5cdbf5 100644
--- a/gcc/genattrtab.c
+++ b/gcc/genattrtab.c
@@ -228,7 +228,9 @@ static int *insn_n_alternatives;
/* Stores, for each insn code, a bitmap that has bits on for each possible
alternative. */
-static uint64_t *insn_alternatives;
+/* Keep this in sync with recog.h. */
+typedef uint64_t alternative_mask;
+static alternative_mask *insn_alternatives;
/* Used to simplify expressions. */
@@ -256,7 +258,7 @@ static char *attr_printf (unsigned int, const char *, ...)
ATTRIBUTE_PRINTF_2;
static rtx make_numeric_value (int);
static struct attr_desc *find_attr (const char **, int);
-static rtx mk_attr_alt (uint64_t);
+static rtx mk_attr_alt (alternative_mask);
static char *next_comma_elt (const char **);
static rtx insert_right_side (enum rtx_code, rtx, rtx, int, int);
static rtx copy_boolean (rtx);
@@ -494,26 +496,26 @@ attr_rtx_1 (enum rtx_code code, va_list p)
}
}
else if (GET_RTX_LENGTH (code) == 2
- && GET_RTX_FORMAT (code)[0] == 'i'
- && GET_RTX_FORMAT (code)[1] == 'i')
+ && GET_RTX_FORMAT (code)[0] == 'w'
+ && GET_RTX_FORMAT (code)[1] == 'w')
{
- int arg0 = va_arg (p, int);
- int arg1 = va_arg (p, int);
+ HOST_WIDE_INT arg0 = va_arg (p, HOST_WIDE_INT);
+ HOST_WIDE_INT arg1 = va_arg (p, HOST_WIDE_INT);
hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0) + RTL_HASH (arg1));
for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
if (h->hashcode == hashcode
&& GET_CODE (h->u.rtl) == code
- && XINT (h->u.rtl, 0) == arg0
- && XINT (h->u.rtl, 1) == arg1)
+ && XWINT (h->u.rtl, 0) == arg0
+ && XWINT (h->u.rtl, 1) == arg1)
return h->u.rtl;
if (h == 0)
{
rtl_obstack = hash_obstack;
rt_val = rtx_alloc (code);
- XINT (rt_val, 0) = arg0;
- XINT (rt_val, 1) = arg1;
+ XWINT (rt_val, 0) = arg0;
+ XWINT (rt_val, 1) = arg1;
}
}
else if (code == CONST_INT)
@@ -703,7 +705,8 @@ check_attr_test (file_location loc, rtx exp, attr_desc *attr)
if (attr2 == NULL)
{
if (! strcmp (XSTR (exp, 0), "alternative"))
- return mk_attr_alt (((uint64_t) 1) << atoi (XSTR (exp, 1)));
+ return mk_attr_alt (((alternative_mask) 1)
+ << atoi (XSTR (exp, 1)));
else
fatal_at (loc, "unknown attribute `%s' in definition of"
" attribute `%s'", XSTR (exp, 0), attr->name);
@@ -750,7 +753,7 @@ check_attr_test (file_location loc, rtx exp, attr_desc *attr)
name_ptr = XSTR (exp, 1);
while ((p = next_comma_elt (&name_ptr)) != NULL)
- set |= ((uint64_t) 1) << atoi (p);
+ set |= ((alternative_mask) 1) << atoi (p);
return mk_attr_alt (set);
}
@@ -1224,7 +1227,7 @@ get_attr_value (file_location loc, rtx value, struct attr_desc *attr,
int insn_code)
{
struct attr_value *av;
- uint64_t num_alt = 0;
+ alternative_mask num_alt = 0;
value = make_canonical (loc, attr, value);
if (compares_alternatives_p (value))
@@ -1868,7 +1871,7 @@ insert_right_side (enum rtx_code code, rtx exp, rtx term, int insn_code, int ins
This routine is passed an expression and either AND or IOR. It returns a
bitmask indicating which alternatives are mentioned within EXP. */
-static uint64_t
+static alternative_mask
compute_alternative_mask (rtx exp, enum rtx_code code)
{
const char *string;
@@ -1887,11 +1890,11 @@ compute_alternative_mask (rtx exp, enum rtx_code code)
else if (GET_CODE (exp) == EQ_ATTR_ALT)
{
- if (code == AND && XINT (exp, 1))
- return XINT (exp, 0);
+ if (code == AND && XWINT (exp, 1))
+ return XWINT (exp, 0);
- if (code == IOR && !XINT (exp, 1))
- return XINT (exp, 0);
+ if (code == IOR && !XWINT (exp, 1))
+ return XWINT (exp, 0);
return 0;
}
@@ -1899,15 +1902,15 @@ compute_alternative_mask (rtx exp, enum rtx_code code)
return 0;
if (string[1] == 0)
- return ((uint64_t) 1) << (string[0] - '0');
- return ((uint64_t) 1) << atoi (string);
+ return ((alternative_mask) 1) << (string[0] - '0');
+ return ((alternative_mask) 1) << atoi (string);
}
/* Given I, a single-bit mask, return RTX to compare the `alternative'
attribute with the value represented by that bit. */
static rtx
-make_alternative_compare (uint64_t mask)
+make_alternative_compare (alternative_mask mask)
{
return mk_attr_alt (mask);
}
@@ -2286,19 +2289,19 @@ simplify_test_exp_in_temp (rtx exp, int insn_code, int insn_index)
static bool
attr_alt_subset_p (rtx s1, rtx s2)
{
- switch ((XINT (s1, 1) << 1) | XINT (s2, 1))
+ switch ((XWINT (s1, 1) << 1) | XWINT (s2, 1))
{
case (0 << 1) | 0:
- return !(XINT (s1, 0) &~ XINT (s2, 0));
+ return !(XWINT (s1, 0) &~ XWINT (s2, 0));
case (0 << 1) | 1:
- return !(XINT (s1, 0) & XINT (s2, 0));
+ return !(XWINT (s1, 0) & XWINT (s2, 0));
case (1 << 1) | 0:
return false;
case (1 << 1) | 1:
- return !(XINT (s2, 0) &~ XINT (s1, 0));
+ return !(XWINT (s2, 0) &~ XWINT (s1, 0));
default:
gcc_unreachable ();
@@ -2310,16 +2313,16 @@ attr_alt_subset_p (rtx s1, rtx s2)
static bool
attr_alt_subset_of_compl_p (rtx s1, rtx s2)
{
- switch ((XINT (s1, 1) << 1) | XINT (s2, 1))
+ switch ((XWINT (s1, 1) << 1) | XWINT (s2, 1))
{
case (0 << 1) | 0:
- return !(XINT (s1, 0) & XINT (s2, 0));
+ return !(XWINT (s1, 0) & XWINT (s2, 0));
case (0 << 1) | 1:
- return !(XINT (s1, 0) & ~XINT (s2, 0));
+ return !(XWINT (s1, 0) & ~XWINT (s2, 0));
case (1 << 1) | 0:
- return !(XINT (s2, 0) &~ XINT (s1, 0));
+ return !(XWINT (s2, 0) &~ XWINT (s1, 0));
case (1 << 1) | 1:
return false;
@@ -2334,27 +2337,27 @@ attr_alt_subset_of_compl_p (rtx s1, rtx s2)
static rtx
attr_alt_intersection (rtx s1, rtx s2)
{
- int result;
+ alternative_mask result;
- switch ((XINT (s1, 1) << 1) | XINT (s2, 1))
+ switch ((XWINT (s1, 1) << 1) | XWINT (s2, 1))
{
case (0 << 1) | 0:
- result = XINT (s1, 0) & XINT (s2, 0);
+ result = XWINT (s1, 0) & XWINT (s2, 0);
break;
case (0 << 1) | 1:
- result = XINT (s1, 0) & ~XINT (s2, 0);
+ result = XWINT (s1, 0) & ~XWINT (s2, 0);
break;
case (1 << 1) | 0:
- result = XINT (s2, 0) & ~XINT (s1, 0);
+ result = XWINT (s2, 0) & ~XWINT (s1, 0);
break;
case (1 << 1) | 1:
- result = XINT (s1, 0) | XINT (s2, 0);
+ result = XWINT (s1, 0) | XWINT (s2, 0);
break;
default:
gcc_unreachable ();
}
- return attr_rtx (EQ_ATTR_ALT, result, XINT (s1, 1) & XINT (s2, 1));
+ return attr_rtx (EQ_ATTR_ALT, result, XWINT (s1, 1) & XWINT (s2, 1));
}
/* Return EQ_ATTR_ALT expression representing union of S1 and S2. */
@@ -2362,27 +2365,27 @@ attr_alt_intersection (rtx s1, rtx s2)
static rtx
attr_alt_union (rtx s1, rtx s2)
{
- int result;
+ alternative_mask result;
- switch ((XINT (s1, 1) << 1) | XINT (s2, 1))
+ switch ((XWINT (s1, 1) << 1) | XWINT (s2, 1))
{
case (0 << 1) | 0:
- result = XINT (s1, 0) | XINT (s2, 0);
+ result = XWINT (s1, 0) | XWINT (s2, 0);
break;
case (0 << 1) | 1:
- result = XINT (s2, 0) & ~XINT (s1, 0);
+ result = XWINT (s2, 0) & ~XWINT (s1, 0);
break;
case (1 << 1) | 0:
- result = XINT (s1, 0) & ~XINT (s2, 0);
+ result = XWINT (s1, 0) & ~XWINT (s2, 0);
break;
case (1 << 1) | 1:
- result = XINT (s1, 0) & XINT (s2, 0);
+ result = XWINT (s1, 0) & XWINT (s2, 0);
break;
default:
gcc_unreachable ();
}
- return attr_rtx (EQ_ATTR_ALT, result, XINT (s1, 1) | XINT (s2, 1));
+ return attr_rtx (EQ_ATTR_ALT, result, XWINT (s1, 1) | XWINT (s2, 1));
}
/* Return EQ_ATTR_ALT expression representing complement of S. */
@@ -2390,16 +2393,17 @@ attr_alt_union (rtx s1, rtx s2)
static rtx
attr_alt_complement (rtx s)
{
- return attr_rtx (EQ_ATTR_ALT, XINT (s, 0), 1 - XINT (s, 1));
+ return attr_rtx (EQ_ATTR_ALT, XWINT (s, 0),
+ ((HOST_WIDE_INT) 1) - XWINT (s, 1));
}
/* Return EQ_ATTR_ALT expression representing set containing elements set
in E. */
static rtx
-mk_attr_alt (uint64_t e)
+mk_attr_alt (alternative_mask e)
{
- return attr_rtx (EQ_ATTR_ALT, (int)e, 0);
+ return attr_rtx (EQ_ATTR_ALT, (HOST_WIDE_INT) e, (HOST_WIDE_INT) 0);
}
/* Given an expression, see if it can be simplified for a particular insn
@@ -2419,7 +2423,7 @@ simplify_test_exp (rtx exp, int insn_code, int insn_index)
struct attr_value *av;
struct insn_ent *ie;
struct attr_value_list *iv;
- uint64_t i;
+ alternative_mask i;
rtx newexp = exp;
bool left_alt, right_alt;
@@ -2484,14 +2488,14 @@ simplify_test_exp (rtx exp, int insn_code, int insn_index)
&& XSTR (XEXP (left, 0), 0) == alternative_name);
else
left_alt = (GET_CODE (left) == EQ_ATTR_ALT
- && XINT (left, 1));
+ && XWINT (left, 1));
if (GET_CODE (right) == NOT)
right_alt = (GET_CODE (XEXP (right, 0)) == EQ_ATTR
&& XSTR (XEXP (right, 0), 0) == alternative_name);
else
right_alt = (GET_CODE (right) == EQ_ATTR_ALT
- && XINT (right, 1));
+ && XWINT (right, 1));
if (insn_code >= 0
&& (GET_CODE (left) == AND
@@ -2602,12 +2606,12 @@ simplify_test_exp (rtx exp, int insn_code, int insn_index)
else if (insn_code >= 0
&& (GET_CODE (left) == IOR
|| (GET_CODE (left) == EQ_ATTR_ALT
- && !XINT (left, 1))
+ && !XWINT (left, 1))
|| (GET_CODE (left) == EQ_ATTR
&& XSTR (left, 0) == alternative_name)
|| GET_CODE (right) == IOR
|| (GET_CODE (right) == EQ_ATTR_ALT
- && !XINT (right, 1))
+ && !XWINT (right, 1))
|| (GET_CODE (right) == EQ_ATTR
&& XSTR (right, 0) == alternative_name)))
{
@@ -2688,14 +2692,15 @@ simplify_test_exp (rtx exp, int insn_code, int insn_index)
break;
case EQ_ATTR_ALT:
- if (!XINT (exp, 0))
- return XINT (exp, 1) ? true_rtx : false_rtx;
+ if (!XWINT (exp, 0))
+ return XWINT (exp, 1) ? true_rtx : false_rtx;
break;
case EQ_ATTR:
if (XSTR (exp, 0) == alternative_name)
{
- newexp = mk_attr_alt (((uint64_t) 1) << atoi (XSTR (exp, 1)));
+ newexp = mk_attr_alt (((alternative_mask) 1)
+ << atoi (XSTR (exp, 1)));
break;
}
@@ -3568,7 +3573,8 @@ write_test_expr (FILE *outf, rtx exp, unsigned int attrs_cached, int flags,
case EQ_ATTR_ALT:
{
- int set = XINT (exp, 0), bit = 0;
+ alternative_mask set = XWINT (exp, 0);
+ int bit = 0;
if (flags & FLG_BITWISE)
fatal ("EQ_ATTR_ALT not valid inside comparison");
@@ -3578,6 +3584,11 @@ write_test_expr (FILE *outf, rtx exp, unsigned int attrs_cached, int flags,
if (!(set & (set - 1)))
{
+ if (!(set & 0xffffffff))
+ {
+ bit += 32;
+ set >>= 32;
+ }
if (!(set & 0xffff))
{
bit += 16;
@@ -3602,12 +3613,13 @@ write_test_expr (FILE *outf, rtx exp, unsigned int attrs_cached, int flags,
bit++;
fprintf (outf, "which_alternative %s= %d",
- XINT (exp, 1) ? "!" : "=", bit);
+ XWINT (exp, 1) ? "!" : "=", bit);
}
else
{
- fprintf (outf, "%s((1 << which_alternative) & %#x)",
- XINT (exp, 1) ? "!" : "", set);
+ fprintf (outf, "%s((1ULL << which_alternative) & %#" PRIx64
+ "ULL)",
+ XWINT (exp, 1) ? "!" : "", set);
}
}
break;
@@ -5220,11 +5232,11 @@ main (int argc, const char **argv)
/* Make `insn_alternatives'. */
int num_insn_codes = get_num_insn_codes ();
- insn_alternatives = oballocvec (uint64_t, num_insn_codes);
+ insn_alternatives = oballocvec (alternative_mask, num_insn_codes);
for (id = defs; id; id = id->next)
if (id->insn_code >= 0)
insn_alternatives[id->insn_code]
- = (((uint64_t) 1) << id->num_alternatives) - 1;
+ = (((alternative_mask) 1) << id->num_alternatives) - 1;
/* Make `insn_n_alternatives'. */
insn_n_alternatives = oballocvec (int, num_insn_codes);
diff --git a/gcc/genconfig.c b/gcc/genconfig.c
index c1bfde8..745d537 100644
--- a/gcc/genconfig.c
+++ b/gcc/genconfig.c
@@ -72,6 +72,7 @@ walk_insn_part (rtx part, int recog_p, int non_pc_set_src)
switch (code)
{
case CLOBBER:
+ case CLOBBER_HIGH:
clobbers_seen_this_insn++;
break;
diff --git a/gcc/genemit.c b/gcc/genemit.c
index f4179e2..678b9aa 100644
--- a/gcc/genemit.c
+++ b/gcc/genemit.c
@@ -79,7 +79,7 @@ gen_rtx_scratch (rtx x, enum rtx_code subroutine_type)
substituting any operand references appearing within. */
static void
-gen_exp (rtx x, enum rtx_code subroutine_type, char *used)
+gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info)
{
RTX_CODE code;
int i;
@@ -123,7 +123,7 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used)
for (i = 0; i < XVECLEN (x, 1); i++)
{
printf (",\n\t\t");
- gen_exp (XVECEXP (x, 1, i), subroutine_type, used);
+ gen_exp (XVECEXP (x, 1, i), subroutine_type, used, info);
}
printf (")");
return;
@@ -137,7 +137,7 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used)
for (i = 0; i < XVECLEN (x, 2); i++)
{
printf (",\n\t\t");
- gen_exp (XVECEXP (x, 2, i), subroutine_type, used);
+ gen_exp (XVECEXP (x, 2, i), subroutine_type, used, info);
}
printf (")");
return;
@@ -163,12 +163,21 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used)
case CLOBBER:
if (REG_P (XEXP (x, 0)))
{
- printf ("gen_hard_reg_clobber (%smode, %i)", GET_MODE_NAME (GET_MODE (XEXP (x, 0))),
- REGNO (XEXP (x, 0)));
+ printf ("gen_hard_reg_clobber (%smode, %i)",
+ GET_MODE_NAME (GET_MODE (XEXP (x, 0))),
+ REGNO (XEXP (x, 0)));
return;
}
break;
-
+ case CLOBBER_HIGH:
+ if (!REG_P (XEXP (x, 0)))
+ error ("CLOBBER_HIGH argument is not a register expr, at %s:%d",
+ info->loc.filename, info->loc.lineno);
+ printf ("gen_hard_reg_clobber_high (%smode, %i)",
+ GET_MODE_NAME (GET_MODE (XEXP (x, 0))),
+ REGNO (XEXP (x, 0)));
+ return;
+ break;
case CC0:
printf ("cc0_rtx");
return;
@@ -224,7 +233,7 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used)
switch (fmt[i])
{
case 'e': case 'u':
- gen_exp (XEXP (x, i), subroutine_type, used);
+ gen_exp (XEXP (x, i), subroutine_type, used, info);
break;
case 'i':
@@ -252,7 +261,7 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used)
for (j = 0; j < XVECLEN (x, i); j++)
{
printf (",\n\t\t");
- gen_exp (XVECEXP (x, i, j), subroutine_type, used);
+ gen_exp (XVECEXP (x, i, j), subroutine_type, used, info);
}
printf (")");
break;
@@ -270,7 +279,7 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used)
becoming a separate instruction. USED is as for gen_exp. */
static void
-gen_emit_seq (rtvec vec, char *used)
+gen_emit_seq (rtvec vec, char *used, md_rtx_info *info)
{
for (int i = 0, len = GET_NUM_ELEM (vec); i < len; ++i)
{
@@ -279,7 +288,7 @@ gen_emit_seq (rtvec vec, char *used)
if (const char *name = get_emit_function (next))
{
printf (" %s (", name);
- gen_exp (next, DEFINE_EXPAND, used);
+ gen_exp (next, DEFINE_EXPAND, used, info);
printf (");\n");
if (!last_p && needs_barrier_p (next))
printf (" emit_barrier ();");
@@ -287,7 +296,7 @@ gen_emit_seq (rtvec vec, char *used)
else
{
printf (" emit (");
- gen_exp (next, DEFINE_EXPAND, used);
+ gen_exp (next, DEFINE_EXPAND, used, info);
printf (", %s);\n", last_p ? "false" : "true");
}
}
@@ -334,7 +343,8 @@ gen_insn (md_rtx_info *info)
for (i = XVECLEN (insn, 1) - 1; i > 0; i--)
{
- if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER)
+ if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER
+ && GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER_HIGH)
break;
if (REG_P (XEXP (XVECEXP (insn, 1, i), 0)))
@@ -368,7 +378,8 @@ gen_insn (md_rtx_info *info)
/* OLD and NEW_INSN are the same if both are to be a SCRATCH
of the same mode,
or if both are registers of the same mode and number. */
- if (! (GET_MODE (old_rtx) == GET_MODE (new_rtx)
+ if (! (GET_CODE (old_rtx) == GET_CODE (new_rtx)
+ && GET_MODE (old_rtx) == GET_MODE (new_rtx)
&& ((GET_CODE (old_rtx) == MATCH_SCRATCH
&& GET_CODE (new_rtx) == MATCH_SCRATCH)
|| (REG_P (old_rtx) && REG_P (new_rtx)
@@ -431,7 +442,7 @@ gen_insn (md_rtx_info *info)
? NULL
: XCNEWVEC (char, stats.num_generator_args));
printf (" return ");
- gen_exp (pattern, DEFINE_INSN, used);
+ gen_exp (pattern, DEFINE_INSN, used, info);
printf (";\n}\n\n");
XDELETEVEC (used);
}
@@ -480,7 +491,7 @@ gen_expand (md_rtx_info *info)
&& XVECLEN (expand, 1) == 1)
{
printf (" return ");
- gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL);
+ gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL, info);
printf (";\n}\n\n");
return;
}
@@ -534,7 +545,7 @@ gen_expand (md_rtx_info *info)
}
used = XCNEWVEC (char, stats.num_operand_vars);
- gen_emit_seq (XVEC (expand, 1), used);
+ gen_emit_seq (XVEC (expand, 1), used, info);
XDELETEVEC (used);
/* Call `get_insns' to extract the list of all the
@@ -617,7 +628,7 @@ gen_split (md_rtx_info *info)
printf (" (void) operand%d;\n", i);
}
- gen_emit_seq (XVEC (split, 2), used);
+ gen_emit_seq (XVEC (split, 2), used, info);
/* Call `get_insns' to make a list of all the
insns emitted within this gen_... function. */
@@ -634,7 +645,7 @@ gen_split (md_rtx_info *info)
the end of the vector. */
static void
-output_add_clobbers (void)
+output_add_clobbers (md_rtx_info *info)
{
struct clobber_pat *clobber;
struct clobber_ent *ent;
@@ -654,7 +665,7 @@ output_add_clobbers (void)
{
printf (" XVECEXP (pattern, 0, %d) = ", i);
gen_exp (XVECEXP (clobber->pattern, 1, i),
- GET_CODE (clobber->pattern), NULL);
+ GET_CODE (clobber->pattern), NULL, info);
printf (";\n");
}
@@ -752,6 +763,92 @@ output_peephole2_scratches (rtx split)
}
}
+/* Print "arg<N>" parameter declarations for each argument N of ONAME. */
+
+static void
+print_overload_arguments (overloaded_name *oname)
+{
+ for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+ printf ("%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i);
+}
+
+/* Print code to test whether INSTANCE should be chosen, given that
+ argument N of the overload is available as "arg<N>". */
+
+static void
+print_overload_test (overloaded_instance *instance)
+{
+ for (unsigned int i = 0; i < instance->arg_values.length (); ++i)
+ printf ("%sarg%d == %s", i == 0 ? " if (" : "\n && ",
+ i, instance->arg_values[i]);
+ printf (")\n");
+}
+
+/* Emit a maybe_code_for_* function for ONAME. */
+
+static void
+handle_overloaded_code_for (overloaded_name *oname)
+{
+ /* Print the function prototype. */
+ printf ("\ninsn_code\nmaybe_code_for_%s (", oname->name);
+ print_overload_arguments (oname);
+ printf (")\n{\n");
+
+ /* Use a sequence of "if" statements for each instance. */
+ for (overloaded_instance *instance = oname->first_instance;
+ instance; instance = instance->next)
+ {
+ print_overload_test (instance);
+ printf (" return CODE_FOR_%s;\n", instance->name);
+ }
+
+ /* Return null if no match was found. */
+ printf (" return CODE_FOR_nothing;\n}\n");
+}
+
+/* Emit a maybe_gen_* function for ONAME. */
+
+static void
+handle_overloaded_gen (overloaded_name *oname)
+{
+ /* All patterns must have the same number of operands. */
+ pattern_stats stats;
+ get_pattern_stats (&stats, XVEC (oname->first_instance->insn, 1));
+ for (overloaded_instance *instance = oname->first_instance->next;
+ instance; instance = instance->next)
+ {
+ pattern_stats stats2;
+ get_pattern_stats (&stats2, XVEC (instance->insn, 1));
+ if (stats.num_generator_args != stats2.num_generator_args)
+ fatal_at (get_file_location (instance->insn),
+ "inconsistent number of operands for '%s'; "
+ "this instance has %d, but previous instances had %d",
+ oname->name, stats2.num_generator_args,
+ stats.num_generator_args);
+ }
+
+ /* Print the function prototype. */
+ printf ("\nrtx\nmaybe_gen_%s (", oname->name);
+ print_overload_arguments (oname);
+ for (int i = 0; i < stats.num_generator_args; ++i)
+ printf (", rtx x%d", i);
+ printf (")\n{\n");
+
+ /* Use maybe_code_for_*, instead of duplicating the selection logic here. */
+ printf (" insn_code code = maybe_code_for_%s (", oname->name);
+ for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+ printf ("%sarg%d", i == 0 ? "" : ", ", i);
+ printf (");\n"
+ " if (code != CODE_FOR_nothing)\n"
+ " return GEN_FCN (code) (");
+ for (int i = 0; i < stats.num_generator_args; ++i)
+ printf ("%sx%d", i == 0 ? "" : ", ", i);
+ printf (");\n"
+ " else\n"
+ " return NULL_RTX;\n"
+ "}\n");
+}
+
int
main (int argc, const char **argv)
{
@@ -837,9 +934,16 @@ from the machine description file `md'. */\n\n");
/* Write out the routines to add CLOBBERs to a pattern and say whether they
clobber a hard reg. */
- output_add_clobbers ();
+ output_add_clobbers (&info);
output_added_clobbers_hard_reg_p ();
+ for (overloaded_name *oname = rtx_reader_ptr->get_overloads ();
+ oname; oname = oname->next)
+ {
+ handle_overloaded_code_for (oname);
+ handle_overloaded_gen (oname);
+ }
+
fflush (stdout);
return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
}
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 0db5528..4339456 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -1721,7 +1721,7 @@ open_base_files (void)
"tree-vrp.h", "tree-phinodes.h", "ssa-iterators.h", "stringpool.h",
"tree-ssanames.h", "tree-ssa-loop.h", "tree-ssa-loop-ivopts.h",
"tree-ssa-loop-manip.h", "tree-ssa-loop-niter.h", "tree-into-ssa.h",
- "tree-dfa.h", "tree-ssa.h", "reload.h", "cpp-id-data.h", "tree-chrec.h",
+ "tree-dfa.h", "tree-ssa.h", "reload.h", "cpplib.h", "tree-chrec.h",
"except.h", "output.h", "cfgloop.h", "target.h", "lto-streamer.h",
"target-globals.h", "ipa-ref.h", "cgraph.h", "symbol-summary.h",
"ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h", "omp-offload.h", NULL
diff --git a/gcc/genmatch.c b/gcc/genmatch.c
index 5848722..5f1691a 100644
--- a/gcc/genmatch.c
+++ b/gcc/genmatch.c
@@ -184,7 +184,7 @@ fprintf_indent (FILE *f, unsigned int indent, const char *format, ...)
static void
output_line_directive (FILE *f, source_location location,
- bool dumpfile = false)
+ bool dumpfile = false, bool fnargs = false)
{
const line_map_ordinary *map;
linemap_resolve_location (line_table, location, LRK_SPELLING_LOCATION, &map);
@@ -202,7 +202,11 @@ output_line_directive (FILE *f, source_location location,
file = loc.file;
else
++file;
- fprintf (f, "%s:%d", file, loc.line);
+
+ if (fnargs)
+ fprintf (f, "\"%s\", %d", file, loc.line);
+ else
+ fprintf (f, "%s:%d", file, loc.line);
}
else
/* Other gen programs really output line directives here, at least for
@@ -3305,11 +3309,13 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
}
}
- fprintf_indent (f, indent, "if (dump_file && (dump_flags & TDF_FOLDING)) "
+ fprintf_indent (f, indent, "if (__builtin_expect (dump_file && (dump_flags & TDF_FOLDING), 0)) "
"fprintf (dump_file, \"Applying pattern ");
+ fprintf (f, "%%s:%%d, %%s:%%d\\n\", ");
output_line_directive (f,
- result ? result->location : s->match->location, true);
- fprintf (f, ", %%s:%%d\\n\", __FILE__, __LINE__);\n");
+ result ? result->location : s->match->location, true,
+ true);
+ fprintf (f, ", __FILE__, __LINE__);\n");
if (!result)
{
@@ -4150,7 +4156,7 @@ parser::parse_operation ()
if (active_fors.length() == 0)
record_operlist (id_tok->src_loc, p);
else
- fatal_at (id_tok, "operator-list %s cannot be exapnded inside 'for'", id);
+ fatal_at (id_tok, "operator-list %s cannot be expanded inside 'for'", id);
}
return op;
}
diff --git a/gcc/genmodes.c b/gcc/genmodes.c
index af0d280..6db9ed4 100644
--- a/gcc/genmodes.c
+++ b/gcc/genmodes.c
@@ -340,7 +340,6 @@ complete_mode (struct mode_data *m)
break;
case MODE_INT:
- case MODE_POINTER_BOUNDS:
case MODE_FLOAT:
case MODE_DECIMAL_FLOAT:
case MODE_FRACT:
@@ -572,19 +571,6 @@ make_special_mode (enum mode_class cl, const char *name,
new_mode (cl, name, file, line);
}
-#define POINTER_BOUNDS_MODE(N, Y) \
- make_pointer_bounds_mode (#N, Y, __FILE__, __LINE__)
-
-static void ATTRIBUTE_UNUSED
-make_pointer_bounds_mode (const char *name,
- unsigned int bytesize,
- const char *file, unsigned int line)
-{
- struct mode_data *m = new_mode (MODE_POINTER_BOUNDS, name, file, line);
- m->bytesize = bytesize;
-}
-
-
#define INT_MODE(N, Y) FRACTIONAL_INT_MODE (N, -1U, Y)
#define FRACTIONAL_INT_MODE(N, B, Y) \
make_int_mode (#N, B, Y, __FILE__, __LINE__)
@@ -1213,7 +1199,6 @@ get_mode_class (struct mode_data *mode)
case MODE_UFRACT:
case MODE_ACCUM:
case MODE_UACCUM:
- case MODE_POINTER_BOUNDS:
return "scalar_mode";
case MODE_FLOAT:
diff --git a/gcc/genopinit.c b/gcc/genopinit.c
index 65a38d2..79835cc 100644
--- a/gcc/genopinit.c
+++ b/gcc/genopinit.c
@@ -104,6 +104,63 @@ open_outfile (const char *file_name)
return f;
}
+/* Declare the maybe_code_for_* function for ONAME, and provide
+ an inline definition of the assserting code_for_* wrapper. */
+
+static void
+handle_overloaded_code_for (FILE *file, overloaded_name *oname)
+{
+ fprintf (file, "\nextern insn_code maybe_code_for_%s (", oname->name);
+ for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+ fprintf (file, "%s%s", i == 0 ? "" : ", ", oname->arg_types[i]);
+ fprintf (file, ");\n");
+
+ fprintf (file, "inline insn_code\ncode_for_%s (", oname->name);
+ for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+ fprintf (file, "%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i);
+ fprintf (file, ")\n{\n insn_code code = maybe_code_for_%s (", oname->name);
+ for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+ fprintf (file, "%sarg%d", i == 0 ? "" : ", ", i);
+ fprintf (file,
+ ");\n"
+ " gcc_assert (code != CODE_FOR_nothing);\n"
+ " return code;\n"
+ "}\n");
+}
+
+/* Declare the maybe_gen_* function for ONAME, and provide
+ an inline definition of the assserting gen_* wrapper. */
+
+static void
+handle_overloaded_gen (FILE *file, overloaded_name *oname)
+{
+ pattern_stats stats;
+ get_pattern_stats (&stats, XVEC (oname->first_instance->insn, 1));
+
+ fprintf (file, "\nextern rtx maybe_gen_%s (", oname->name);
+ for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+ fprintf (file, "%s%s", i == 0 ? "" : ", ", oname->arg_types[i]);
+ for (int i = 0; i < stats.num_generator_args; ++i)
+ fprintf (file, ", rtx");
+ fprintf (file, ");\n");
+
+ fprintf (file, "inline rtx\ngen_%s (", oname->name);
+ for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+ fprintf (file, "%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i);
+ for (int i = 0; i < stats.num_generator_args; ++i)
+ fprintf (file, ", rtx x%d", i);
+ fprintf (file, ")\n{\n rtx res = maybe_gen_%s (", oname->name);
+ for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+ fprintf (file, "%sarg%d", i == 0 ? "" : ", ", i);
+ for (int i = 0; i < stats.num_generator_args; ++i)
+ fprintf (file, ", x%d", i);
+ fprintf (file,
+ ");\n"
+ " gcc_assert (res);\n"
+ " return res;\n"
+ "}\n");
+}
+
int
main (int argc, const char **argv)
{
@@ -220,7 +277,16 @@ main (int argc, const char **argv)
"optab_to_code (optab op)\n"
"{\n"
" return optab_to_code_[op];\n"
- "}\n"
+ "}\n");
+
+ for (overloaded_name *oname = rtx_reader_ptr->get_overloads ();
+ oname; oname = oname->next)
+ {
+ handle_overloaded_code_for (h_file, oname);
+ handle_overloaded_gen (h_file, oname);
+ }
+
+ fprintf (h_file,
"#endif\n"
"\n"
"extern const struct convert_optab_libcall_d convlib_def[NUM_CONVLIB_OPTABS];\n"
diff --git a/gcc/genpreds.c b/gcc/genpreds.c
index e0892ff..bb29484 100644
--- a/gcc/genpreds.c
+++ b/gcc/genpreds.c
@@ -152,7 +152,7 @@ write_predicate_subfunction (struct pred_data *p)
p->exp = and_exp;
printf ("static inline int\n"
- "%s_1 (rtx op, machine_mode mode ATTRIBUTE_UNUSED)\n",
+ "%s_1 (rtx op ATTRIBUTE_UNUSED, machine_mode mode ATTRIBUTE_UNUSED)\n",
p->name);
rtx_reader_ptr->print_md_ptr_loc (p->c_block);
if (p->c_block[0] == '{')
diff --git a/gcc/genrecog.c b/gcc/genrecog.c
index 663df8c..629e2dc 100644
--- a/gcc/genrecog.c
+++ b/gcc/genrecog.c
@@ -718,6 +718,7 @@ validate_pattern (rtx pattern, md_rtx_info *info, rtx set, int set_code)
}
case CLOBBER:
+ case CLOBBER_HIGH:
validate_pattern (SET_DEST (pattern), info, pattern, '=');
return;
@@ -5294,7 +5295,7 @@ remove_clobbers (acceptance_type *acceptance_ptr, rtx *pattern_ptr)
for (i = XVECLEN (pattern, 0); i > 0; i--)
{
rtx x = XVECEXP (pattern, 0, i - 1);
- if (GET_CODE (x) != CLOBBER
+ if ((GET_CODE (x) != CLOBBER && GET_CODE (x) != CLOBBER_HIGH)
|| (!REG_P (XEXP (x, 0))
&& GET_CODE (XEXP (x, 0)) != MATCH_SCRATCH))
break;
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index c3fa570..1e84722 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -725,6 +725,8 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
tree srctype, desttype;
unsigned int src_align, dest_align;
tree off0;
+ const char *tmp_str;
+ unsigned HOST_WIDE_INT tmp_len;
/* Build accesses at offset zero with a ref-all character type. */
off0 = build_int_cst (build_pointer_type_for_mode (char_type_node,
@@ -742,7 +744,9 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
confuses the tree-ssa-strlen.c. This doesn't handle
the case in gcc.dg/strlenopt-8.c which is XFAILed for that
reason. */
- && !c_strlen (src, 2))
+ && !c_strlen (src, 2)
+ && !((tmp_str = c_getstr (src, &tmp_len)) != NULL
+ && memchr (tmp_str, 0, tmp_len) == NULL))
{
unsigned ilen = tree_to_uhwi (len);
if (pow2p_hwi (ilen))
@@ -1275,11 +1279,14 @@ gimple_fold_builtin_memset (gimple_stmt_iterator *gsi, tree c, tree len)
Set *FLEXP to true if the range of the string lengths has been
obtained from the upper bound of an array at the end of a struct.
Such an array may hold a string that's longer than its upper bound
- due to it being used as a poor-man's flexible array member. */
+ due to it being used as a poor-man's flexible array member.
+ Pass NONSTR through to children.
+ ELTSIZE is 1 for normal single byte character strings, and 2 or
+ 4 for wide characer strings. ELTSIZE is by default 1. */
static bool
get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
- int fuzzy, bool *flexp)
+ int fuzzy, bool *flexp, unsigned eltsize, tree *nonstr)
{
tree var, val = NULL_TREE;
gimple *def_stmt;
@@ -1300,8 +1307,9 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
tree aop0 = TREE_OPERAND (op, 0);
if (TREE_CODE (aop0) == INDIRECT_REF
&& TREE_CODE (TREE_OPERAND (aop0, 0)) == SSA_NAME)
- return get_range_strlen (TREE_OPERAND (aop0, 0),
- length, visited, type, fuzzy, flexp);
+ return get_range_strlen (TREE_OPERAND (aop0, 0), length,
+ visited, type, fuzzy, flexp,
+ eltsize, nonstr);
}
else if (TREE_CODE (TREE_OPERAND (op, 0)) == COMPONENT_REF && fuzzy)
{
@@ -1329,13 +1337,14 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
return false;
}
else
- val = c_strlen (arg, 1);
+ val = c_strlen (arg, 1, nonstr, eltsize);
if (!val && fuzzy)
{
if (TREE_CODE (arg) == ADDR_EXPR)
return get_range_strlen (TREE_OPERAND (arg, 0), length,
- visited, type, fuzzy, flexp);
+ visited, type, fuzzy, flexp,
+ eltsize, nonstr);
if (TREE_CODE (arg) == ARRAY_REF)
{
@@ -1477,7 +1486,8 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
|| gimple_assign_unary_nop_p (def_stmt))
{
tree rhs = gimple_assign_rhs1 (def_stmt);
- return get_range_strlen (rhs, length, visited, type, fuzzy, flexp);
+ return get_range_strlen (rhs, length, visited, type, fuzzy, flexp,
+ eltsize, nonstr);
}
else if (gimple_assign_rhs_code (def_stmt) == COND_EXPR)
{
@@ -1486,7 +1496,7 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
for (unsigned int i = 0; i < 2; i++)
if (!get_range_strlen (ops[i], length, visited, type, fuzzy,
- flexp))
+ flexp, eltsize, nonstr))
{
if (fuzzy == 2)
*maxlen = build_all_ones_cst (size_type_node);
@@ -1513,7 +1523,8 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
if (arg == gimple_phi_result (def_stmt))
continue;
- if (!get_range_strlen (arg, length, visited, type, fuzzy, flexp))
+ if (!get_range_strlen (arg, length, visited, type, fuzzy, flexp,
+ eltsize, nonstr))
{
if (fuzzy == 2)
*maxlen = build_all_ones_cst (size_type_node);
@@ -1545,19 +1556,31 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
and false if PHIs and COND_EXPRs are to be handled optimistically,
if we can determine string length minimum and maximum; it will use
the minimum from the ones where it can be determined.
- STRICT false should be only used for warning code. */
+ STRICT false should be only used for warning code.
+ When non-null, clear *NONSTR if ARG refers to a constant array
+ that is known not be nul-terminated. Otherwise set it to
+ the declaration of the constant non-terminated array.
+
+ ELTSIZE is 1 for normal single byte character strings, and 2 or
+ 4 for wide characer strings. ELTSIZE is by default 1. */
bool
-get_range_strlen (tree arg, tree minmaxlen[2], bool strict)
+get_range_strlen (tree arg, tree minmaxlen[2], unsigned eltsize,
+ bool strict, tree *nonstr /* = NULL */)
{
bitmap visited = NULL;
minmaxlen[0] = NULL_TREE;
minmaxlen[1] = NULL_TREE;
+ tree nonstrbuf;
+ if (!nonstr)
+ nonstr = &nonstrbuf;
+ *nonstr = NULL_TREE;
+
bool flexarray = false;
if (!get_range_strlen (arg, minmaxlen, &visited, 1, strict ? 1 : 2,
- &flexarray))
+ &flexarray, eltsize, nonstr))
{
minmaxlen[0] = NULL_TREE;
minmaxlen[1] = NULL_TREE;
@@ -1569,19 +1592,39 @@ get_range_strlen (tree arg, tree minmaxlen[2], bool strict)
return flexarray;
}
+/* Return the maximum string length for ARG, counting by TYPE
+ (1, 2 or 4 for normal or wide chars). NONSTR indicates
+ if the caller is prepared to handle unterminated strings.
+
+ If an unterminated string is discovered and our caller handles
+ unterminated strings, then bubble up the offending DECL and
+ return the maximum size. Otherwise return NULL. */
+
tree
-get_maxval_strlen (tree arg, int type)
+get_maxval_strlen (tree arg, int type, tree *nonstr /* = NULL */)
{
bitmap visited = NULL;
tree len[2] = { NULL_TREE, NULL_TREE };
bool dummy;
- if (!get_range_strlen (arg, len, &visited, type, 0, &dummy))
+ /* Set to non-null if ARG refers to an untermianted array. */
+ tree mynonstr = NULL_TREE;
+ if (!get_range_strlen (arg, len, &visited, type, 0, &dummy, 1, &mynonstr))
len[1] = NULL_TREE;
if (visited)
BITMAP_FREE (visited);
- return len[1];
+ if (nonstr)
+ {
+ /* For callers prepared to handle unterminated arrays set
+ *NONSTR to point to the declaration of the array and return
+ the maximum length/size. */
+ *nonstr = mynonstr;
+ return len[1];
+ }
+
+ /* Fail if the constant array isn't nul-terminated. */
+ return mynonstr ? NULL_TREE : len[1];
}
@@ -1624,7 +1667,19 @@ gimple_fold_builtin_strcpy (gimple_stmt_iterator *gsi,
if (!fn)
return false;
- tree len = get_maxval_strlen (src, 0);
+ /* Set to non-null if ARG refers to an unterminated array. */
+ tree nonstr = NULL;
+ tree len = get_maxval_strlen (src, 0, &nonstr);
+
+ if (nonstr)
+ {
+ /* Avoid folding calls with unterminated arrays. */
+ if (!gimple_no_warning_p (stmt))
+ warn_string_no_nul (loc, "strcpy", src, nonstr);
+ gimple_set_no_warning (stmt, true);
+ return false;
+ }
+
if (!len)
return false;
@@ -1657,7 +1712,6 @@ gimple_fold_builtin_strncpy (gimple_stmt_iterator *gsi,
if (!nonstring)
{
tree fndecl = gimple_call_fndecl (stmt);
- gcall *call = as_a <gcall *> (stmt);
/* Warn about the lack of nul termination: the result is not
a (nul-terminated) string. */
@@ -1666,11 +1720,11 @@ gimple_fold_builtin_strncpy (gimple_stmt_iterator *gsi,
warning_at (loc, OPT_Wstringop_truncation,
"%G%qD destination unchanged after copying no bytes "
"from a string of length %E",
- call, fndecl, slen);
+ stmt, fndecl, slen);
else
warning_at (loc, OPT_Wstringop_truncation,
"%G%qD destination unchanged after copying no bytes",
- call, fndecl);
+ stmt, fndecl);
}
replace_call_with_value (gsi, dest);
@@ -1991,7 +2045,7 @@ gimple_fold_builtin_strcat_chk (gimple_stmt_iterator *gsi)
static bool
gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi)
{
- gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
+ gimple *stmt = gsi_stmt (*gsi);
tree dst = gimple_call_arg (stmt, 0);
tree src = gimple_call_arg (stmt, 1);
tree len = gimple_call_arg (stmt, 2);
@@ -2744,7 +2798,7 @@ gimple_fold_builtin_stpcpy (gimple_stmt_iterator *gsi)
location_t loc = gimple_location (stmt);
tree dest = gimple_call_arg (stmt, 0);
tree src = gimple_call_arg (stmt, 1);
- tree fn, len, lenp1;
+ tree fn, lenp1;
/* If the result is unused, replace stpcpy with strcpy. */
if (gimple_call_lhs (stmt) == NULL_TREE)
@@ -2757,10 +2811,25 @@ gimple_fold_builtin_stpcpy (gimple_stmt_iterator *gsi)
return true;
}
- len = c_strlen (src, 1);
+ /* Set to non-null if ARG refers to an unterminated array. */
+ tree nonstr = NULL;
+ tree len = c_strlen (src, 1, &nonstr, 1);
if (!len
|| TREE_CODE (len) != INTEGER_CST)
- return false;
+ {
+ nonstr = unterminated_array (src);
+ if (!nonstr)
+ return false;
+ }
+
+ if (nonstr)
+ {
+ /* Avoid folding calls with unterminated arrays. */
+ if (!gimple_no_warning_p (stmt))
+ warn_string_no_nul (loc, "stpcpy", src, nonstr);
+ gimple_set_no_warning (stmt, true);
+ return false;
+ }
if (optimize_function_for_size_p (cfun)
/* If length is zero it's small enough. */
@@ -3023,6 +3092,12 @@ gimple_fold_builtin_sprintf (gimple_stmt_iterator *gsi)
'format' is known to contain no % formats. */
gimple_seq stmts = NULL;
gimple *repl = gimple_build_call (fn, 2, dest, fmt);
+
+ /* Propagate the NO_WARNING bit to avoid issuing the same
+ warning more than once. */
+ if (gimple_no_warning_p (stmt))
+ gimple_set_no_warning (repl, true);
+
gimple_seq_add_stmt_without_update (&stmts, repl);
if (gimple_call_lhs (stmt))
{
@@ -3071,6 +3146,12 @@ gimple_fold_builtin_sprintf (gimple_stmt_iterator *gsi)
/* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2). */
gimple_seq stmts = NULL;
gimple *repl = gimple_build_call (fn, 2, dest, orig);
+
+ /* Propagate the NO_WARNING bit to avoid issuing the same
+ warning more than once. */
+ if (gimple_no_warning_p (stmt))
+ gimple_set_no_warning (repl, true);
+
gimple_seq_add_stmt_without_update (&stmts, repl);
if (gimple_call_lhs (stmt))
{
@@ -3496,12 +3577,15 @@ static bool
gimple_fold_builtin_strlen (gimple_stmt_iterator *gsi)
{
gimple *stmt = gsi_stmt (*gsi);
+ tree arg = gimple_call_arg (stmt, 0);
wide_int minlen;
wide_int maxlen;
+ /* Set to non-null if ARG refers to an unterminated array. */
+ tree nonstr;
tree lenrange[2];
- if (!get_range_strlen (gimple_call_arg (stmt, 0), lenrange, true)
+ if (!get_range_strlen (arg, lenrange, 1, true, &nonstr)
&& lenrange[0] && TREE_CODE (lenrange[0]) == INTEGER_CST
&& lenrange[1] && TREE_CODE (lenrange[1]) == INTEGER_CST)
{
@@ -4156,7 +4240,8 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
result = fold_builtin_expect (gimple_location (stmt),
gimple_call_arg (stmt, 0),
gimple_call_arg (stmt, 1),
- gimple_call_arg (stmt, 2));
+ gimple_call_arg (stmt, 2),
+ NULL_TREE);
break;
case IFN_UBSAN_OBJECT_SIZE:
{
@@ -6340,8 +6425,7 @@ gimple_fold_stmt_to_constant_1 (gimple *stmt, tree (*valueize) (tree),
fn = (*valueize) (gimple_call_fn (stmt));
if (TREE_CODE (fn) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
- && DECL_BUILT_IN (TREE_OPERAND (fn, 0))
+ && fndecl_built_in_p (TREE_OPERAND (fn, 0))
&& gimple_builtin_call_types_compatible_p (stmt,
TREE_OPERAND (fn, 0)))
{
@@ -6904,12 +6988,13 @@ gimple_get_virt_method_for_vtable (HOST_WIDE_INT token,
access_index = offset / BITS_PER_UNIT / elt_size;
gcc_checking_assert (offset % (elt_size * BITS_PER_UNIT) == 0);
- /* This code makes an assumption that there are no
- indexed fileds produced by C++ FE, so we can directly index the array. */
+ /* The C++ FE can now produce indexed fields, and we check if the indexes
+ match. */
if (access_index < CONSTRUCTOR_NELTS (init))
{
fn = CONSTRUCTOR_ELT (init, access_index)->value;
- gcc_checking_assert (!CONSTRUCTOR_ELT (init, access_index)->index);
+ tree idx = CONSTRUCTOR_ELT (init, access_index)->index;
+ gcc_checking_assert (!idx || tree_to_uhwi (idx) == access_index);
STRIP_NOPS (fn);
}
else
diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h
index 04e9bfa..26e2727 100644
--- a/gcc/gimple-fold.h
+++ b/gcc/gimple-fold.h
@@ -25,8 +25,9 @@ along with GCC; see the file COPYING3. If not see
extern tree create_tmp_reg_or_ssa_name (tree, gimple *stmt = NULL);
extern tree canonicalize_constructor_val (tree, tree);
extern tree get_symbol_constant_value (tree);
-extern bool get_range_strlen (tree, tree[2], bool = false);
-extern tree get_maxval_strlen (tree, int);
+extern bool get_range_strlen (tree, tree[2], unsigned = 1,
+ bool = false, tree * = NULL);
+extern tree get_maxval_strlen (tree, int, tree * = NULL);
extern void gimplify_and_update_call_from_tree (gimple_stmt_iterator *, tree);
extern bool fold_stmt (gimple_stmt_iterator *);
extern bool fold_stmt (gimple_stmt_iterator *, tree (*) (tree));
@@ -61,6 +62,7 @@ extern bool gimple_fold_builtin_snprintf (gimple_stmt_iterator *);
extern bool arith_code_with_undefined_signed_overflow (tree_code);
extern gimple_seq rewrite_to_defined_overflow (gimple *);
extern void replace_call_with_value (gimple_stmt_iterator *, tree);
+extern tree tree_vec_extract (gimple_stmt_iterator *, tree, tree, tree, tree);
/* gimple_build, functionally matching fold_buildN, outputs stmts
int the provided sequence, matching and simplifying them on-the-fly.
diff --git a/gcc/gimple-loop-jam.c b/gcc/gimple-loop-jam.c
index 2ecd1bb..c6bd042 100644
--- a/gcc/gimple-loop-jam.c
+++ b/gcc/gimple-loop-jam.c
@@ -161,7 +161,7 @@ bb_prevents_fusion_p (basic_block bb)
gimple_stmt_iterator gsi;
/* BB is duplicated by outer unrolling and then all N-1 first copies
move into the body of the fused inner loop. If BB exits the outer loop
- the last copy still doess so, and the first N-1 copies are cancelled
+ the last copy still does so, and the first N-1 copies are cancelled
by loop unrolling, so also after fusion it's the exit block.
But there might be other reasons that prevent fusion:
* stores or unknown side-effects prevent fusion
@@ -227,6 +227,33 @@ unroll_jam_possible_p (struct loop *outer, struct loop *loop)
|| !expr_invariant_in_loop_p (outer, niter.niter))
return false;
+ /* If the inner loop produces any values that are used inside the
+ outer loop (except the virtual op) then it can flow
+ back (perhaps indirectly) into the inner loop. This prevents
+ fusion: without fusion the value at the last iteration is used,
+ with fusion the value after the initial iteration is used.
+
+ If all uses are outside the outer loop this doesn't prevent fusion;
+ the value of the last iteration is still used (and the values from
+ all intermediate iterations are dead). */
+ gphi_iterator psi;
+ for (psi = gsi_start_phis (single_exit (loop)->dest);
+ !gsi_end_p (psi); gsi_next (&psi))
+ {
+ imm_use_iterator imm_iter;
+ use_operand_p use_p;
+ tree op = gimple_phi_result (psi.phi ());
+ if (virtual_operand_p (op))
+ continue;
+ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, op)
+ {
+ gimple *use_stmt = USE_STMT (use_p);
+ if (!is_gimple_debug (use_stmt)
+ && flow_bb_inside_loop_p (outer, gimple_bb (use_stmt)))
+ return false;
+ }
+ }
+
/* And check blocks belonging to just outer loop. */
bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun));
n = get_loop_body_with_size (outer, bbs, n_basic_blocks_for_fn (cfun));
@@ -245,7 +272,6 @@ unroll_jam_possible_p (struct loop *outer, struct loop *loop)
body would be the after-iter value of the first body) if it's over
an associative and commutative operation. We wouldn't
be able to handle unknown cycles. */
- gphi_iterator psi;
for (psi = gsi_start_phis (loop->header); !gsi_end_p (psi); gsi_next (&psi))
{
affine_iv iv;
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index 9623fb8..c3777a1 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -355,7 +355,7 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
}
if (decl
- && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
+ && fndecl_built_in_p (decl, BUILT_IN_NORMAL))
{
if (DECL_FUNCTION_CODE (decl) == BUILT_IN_SETJMP)
{
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 19cdb40..83e2273 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -911,8 +911,7 @@ dump_gimple_call (pretty_printer *buffer, gcall *gs, int spc,
if (TREE_CODE (fn) == FUNCTION_DECL && decl_is_tm_clone (fn))
pp_string (buffer, " [tm-clone]");
if (TREE_CODE (fn) == FUNCTION_DECL
- && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (fn) == BUILT_IN_TM_START
+ && fndecl_built_in_p (fn, BUILT_IN_TM_START)
&& gimple_call_num_args (gs) > 0)
{
tree t = gimple_call_arg (gs, 0);
@@ -992,7 +991,7 @@ dump_gimple_switch (pretty_printer *buffer, gswitch *gs, int spc,
if (cfun && cfun->cfg)
{
- basic_block dest = label_to_block (label);
+ basic_block dest = label_to_block (cfun, label);
if (dest)
{
edge label_edge = find_edge (gimple_bb (gs), dest);
@@ -2887,20 +2886,13 @@ gimple_dump_bb_for_graph (pretty_printer *pp, basic_block bb)
/* Handle the %G format for TEXT. Same as %K in handle_K_format in
- tree-pretty-print.c but with a Gimple call statement as an argument. */
+ tree-pretty-print.c but with a Gimple statement as an argument. */
void
percent_G_format (text_info *text)
{
- gcall *stmt = va_arg (*text->args_ptr, gcall*);
+ gimple *stmt = va_arg (*text->args_ptr, gimple*);
- /* Build a call expression from the Gimple call statement and
- pass it to the K formatter that knows how to format it. */
- tree exp = build_vl_exp (CALL_EXPR, gimple_call_num_args (stmt) + 3);
- CALL_EXPR_FN (exp) = gimple_call_fn (stmt);
- TREE_TYPE (exp) = gimple_call_return_type (stmt);
- CALL_EXPR_STATIC_CHAIN (exp) = gimple_call_chain (stmt);
- SET_EXPR_LOCATION (exp, gimple_location (stmt));
-
- percent_K_format (text, exp);
+ tree block = gimple_block (stmt);
+ percent_K_format (text, gimple_location (stmt), block);
}
diff --git a/gcc/gimple-ssa-evrp-analyze.c b/gcc/gimple-ssa-evrp-analyze.c
index b9dcf90..e9afa80 100644
--- a/gcc/gimple-ssa-evrp-analyze.c
+++ b/gcc/gimple-ssa-evrp-analyze.c
@@ -119,12 +119,7 @@ evrp_range_analyzer::set_ssa_range_info (tree lhs, value_range *vr)
wi::to_wide (vr->max));
}
else if (POINTER_TYPE_P (TREE_TYPE (lhs))
- && ((vr->type == VR_RANGE
- && range_includes_zero_p (vr->min,
- vr->max) == 0)
- || (vr->type == VR_ANTI_RANGE
- && range_includes_zero_p (vr->min,
- vr->max) == 1)))
+ && range_includes_zero_p (vr) == 0)
set_ptr_nonnull (lhs);
}
diff --git a/gcc/gimple-ssa-evrp.c b/gcc/gimple-ssa-evrp.c
index b9a054f..50e8adc 100644
--- a/gcc/gimple-ssa-evrp.c
+++ b/gcc/gimple-ssa-evrp.c
@@ -287,6 +287,8 @@ evrp_dom_walker::cleanup (void)
gimple *stmt = stmts_to_fixup.pop ();
fixup_noreturn_call (stmt);
}
+
+ evrp_folder.vr_values->cleanup_edges_and_switches ();
}
/* Main entry point for the early vrp pass which is a simplified non-iterative
diff --git a/gcc/gimple-ssa-isolate-paths.c b/gcc/gimple-ssa-isolate-paths.c
index 131705d..e1fab61 100644
--- a/gcc/gimple-ssa-isolate-paths.c
+++ b/gcc/gimple-ssa-isolate-paths.c
@@ -421,12 +421,15 @@ find_implicit_erroneous_behavior (void)
if (gimple_return_retval (return_stmt) != lhs)
continue;
- if (warning_at (gimple_location (use_stmt),
- OPT_Wreturn_local_addr,
- "function may return address "
- "of local variable"))
- inform (DECL_SOURCE_LOCATION(valbase),
- "declared here");
+ {
+ auto_diagnostic_group d;
+ if (warning_at (gimple_location (use_stmt),
+ OPT_Wreturn_local_addr,
+ "function may return address "
+ "of local variable"))
+ inform (DECL_SOURCE_LOCATION(valbase),
+ "declared here");
+ }
if (gimple_bb (use_stmt) == bb)
{
@@ -543,10 +546,13 @@ find_explicit_erroneous_behavior (void)
else
msg = N_("function may return address of "
"local variable");
-
- if (warning_at (gimple_location (stmt),
- OPT_Wreturn_local_addr, msg))
- inform (DECL_SOURCE_LOCATION(valbase), "declared here");
+ {
+ auto_diagnostic_group d;
+ if (warning_at (gimple_location (stmt),
+ OPT_Wreturn_local_addr, msg))
+ inform (DECL_SOURCE_LOCATION(valbase),
+ "declared here");
+ }
tree zero = build_zero_cst (TREE_TYPE (val));
gimple_return_set_retval (return_stmt, zero);
update_stmt (stmt);
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index bda738d..9b6f6e6 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -211,12 +211,14 @@ struct format_result
the return value optimization. */
bool knownrange;
- /* True if no individual directive resulted in more than 4095 bytes
- of output (the total NUMBER_CHARS_{MIN,MAX} might be greater).
- Implementations are not required to handle directives that produce
- more than 4K bytes (leading to undefined behavior) and so when one
- is found it disables the return value optimization. */
- bool under4k;
+ /* True if no individual directive could fail or result in more than
+ 4095 bytes of output (the total NUMBER_CHARS_{MIN,MAX} might be
+ greater). Implementations are not required to handle directives
+ that produce more than 4K bytes (leading to undefined behavior)
+ and so when one is found it disables the return value optimization.
+ Similarly, directives that can fail (such as wide character
+ directives) disable the optimization. */
+ bool posunder4k;
/* True when a floating point directive has been seen in the format
string. */
@@ -441,156 +443,20 @@ target_strtol10 (const char **ps, const char **erange)
return val;
}
-/* Return the constant initial value of DECL if available or DECL
- otherwise. Same as the synonymous function in c/c-typeck.c. */
-
-static tree
-decl_constant_value (tree decl)
-{
- if (/* Don't change a variable array bound or initial value to a constant
- in a place where a variable is invalid. Note that DECL_INITIAL
- isn't valid for a PARM_DECL. */
- current_function_decl != 0
- && TREE_CODE (decl) != PARM_DECL
- && !TREE_THIS_VOLATILE (decl)
- && TREE_READONLY (decl)
- && DECL_INITIAL (decl) != 0
- && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK
- /* This is invalid if initial value is not constant.
- If it has either a function call, a memory reference,
- or a variable, then re-evaluating it could give different results. */
- && TREE_CONSTANT (DECL_INITIAL (decl))
- /* Check for cases where this is sub-optimal, even though valid. */
- && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR)
- return DECL_INITIAL (decl);
- return decl;
-}
-
/* Given FORMAT, set *PLOC to the source location of the format string
and return the format string if it is known or null otherwise. */
static const char*
get_format_string (tree format, location_t *ploc)
{
- if (VAR_P (format))
- {
- /* Pull out a constant value if the front end didn't. */
- format = decl_constant_value (format);
- STRIP_NOPS (format);
- }
-
- if (integer_zerop (format))
- {
- /* FIXME: Diagnose null format string if it hasn't been diagnosed
- by -Wformat (the latter diagnoses only nul pointer constants,
- this pass can do better). */
- return NULL;
- }
-
- HOST_WIDE_INT offset = 0;
-
- if (TREE_CODE (format) == POINTER_PLUS_EXPR)
- {
- tree arg0 = TREE_OPERAND (format, 0);
- tree arg1 = TREE_OPERAND (format, 1);
- STRIP_NOPS (arg0);
- STRIP_NOPS (arg1);
-
- if (TREE_CODE (arg1) != INTEGER_CST)
- return NULL;
-
- format = arg0;
-
- /* POINTER_PLUS_EXPR offsets are to be interpreted signed. */
- if (!cst_and_fits_in_hwi (arg1))
- return NULL;
-
- offset = int_cst_value (arg1);
- }
-
- if (TREE_CODE (format) != ADDR_EXPR)
- return NULL;
-
*ploc = EXPR_LOC_OR_LOC (format, input_location);
- format = TREE_OPERAND (format, 0);
-
- if (TREE_CODE (format) == ARRAY_REF
- && tree_fits_shwi_p (TREE_OPERAND (format, 1))
- && (offset += tree_to_shwi (TREE_OPERAND (format, 1))) >= 0)
- format = TREE_OPERAND (format, 0);
-
- if (offset < 0)
- return NULL;
-
- tree array_init;
- tree array_size = NULL_TREE;
-
- if (VAR_P (format)
- && TREE_CODE (TREE_TYPE (format)) == ARRAY_TYPE
- && (array_init = decl_constant_value (format)) != format
- && TREE_CODE (array_init) == STRING_CST)
- {
- /* Extract the string constant initializer. Note that this may
- include a trailing NUL character that is not in the array (e.g.
- const char a[3] = "foo";). */
- array_size = DECL_SIZE_UNIT (format);
- format = array_init;
- }
-
- if (TREE_CODE (format) != STRING_CST)
- return NULL;
-
- tree type = TREE_TYPE (format);
-
- scalar_int_mode char_mode;
- if (!is_int_mode (TYPE_MODE (TREE_TYPE (type)), &char_mode)
- || GET_MODE_SIZE (char_mode) != 1)
- {
- /* Wide format string. */
- return NULL;
- }
-
- const char *fmtstr = TREE_STRING_POINTER (format);
- unsigned fmtlen = TREE_STRING_LENGTH (format);
-
- if (array_size)
- {
- /* Variable length arrays can't be initialized. */
- gcc_assert (TREE_CODE (array_size) == INTEGER_CST);
-
- if (tree_fits_shwi_p (array_size))
- {
- HOST_WIDE_INT array_size_value = tree_to_shwi (array_size);
- if (array_size_value > 0
- && array_size_value == (int) array_size_value
- && fmtlen > array_size_value)
- fmtlen = array_size_value;
- }
- }
- if (offset)
- {
- if (offset >= fmtlen)
- return NULL;
-
- fmtstr += offset;
- fmtlen -= offset;
- }
-
- if (fmtlen < 1 || fmtstr[--fmtlen] != 0)
- {
- /* FIXME: Diagnose an unterminated format string if it hasn't been
- diagnosed by -Wformat. Similarly to a null format pointer,
- -Wformay diagnoses only nul pointer constants, this pass can
- do better). */
- return NULL;
- }
-
- return fmtstr;
+ return c_getstr (format);
}
/* For convenience and brevity, shorter named entrypoints of
- format_warning_at_substring and format_warning_at_substring_n.
+ format_string_diagnostic_t::emit_warning_va and
+ format_string_diagnostic_t::emit_warning_n_va.
These have to be functions with the attribute so that exgettext
works properly. */
@@ -599,10 +465,11 @@ ATTRIBUTE_GCC_DIAG (5, 6)
fmtwarn (const substring_loc &fmt_loc, location_t param_loc,
const char *corrected_substring, int opt, const char *gmsgid, ...)
{
+ format_string_diagnostic_t diag (fmt_loc, NULL, param_loc, NULL,
+ corrected_substring);
va_list ap;
va_start (ap, gmsgid);
- bool warned = format_warning_va (fmt_loc, param_loc, corrected_substring,
- opt, gmsgid, &ap);
+ bool warned = diag.emit_warning_va (opt, gmsgid, &ap);
va_end (ap);
return warned;
@@ -614,11 +481,12 @@ fmtwarn_n (const substring_loc &fmt_loc, location_t param_loc,
const char *corrected_substring, int opt, unsigned HOST_WIDE_INT n,
const char *singular_gmsgid, const char *plural_gmsgid, ...)
{
+ format_string_diagnostic_t diag (fmt_loc, NULL, param_loc, NULL,
+ corrected_substring);
va_list ap;
va_start (ap, plural_gmsgid);
- bool warned = format_warning_n_va (fmt_loc, param_loc, corrected_substring,
- opt, n, singular_gmsgid, plural_gmsgid,
- &ap);
+ bool warned = diag.emit_warning_n_va (opt, n, singular_gmsgid, plural_gmsgid,
+ &ap);
va_end (ap);
return warned;
@@ -650,7 +518,7 @@ struct fmtresult
fmtresult (unsigned HOST_WIDE_INT min = HOST_WIDE_INT_MAX)
: argmin (), argmax (),
knownrange (min < HOST_WIDE_INT_MAX),
- nullp ()
+ mayfail (), nullp ()
{
range.min = min;
range.max = min;
@@ -664,7 +532,7 @@ struct fmtresult
unsigned HOST_WIDE_INT likely = HOST_WIDE_INT_MAX)
: argmin (), argmax (),
knownrange (min < HOST_WIDE_INT_MAX && max < HOST_WIDE_INT_MAX),
- nullp ()
+ mayfail (), nullp ()
{
range.min = min;
range.max = max;
@@ -694,6 +562,10 @@ struct fmtresult
heuristics that depend on warning levels. */
bool knownrange;
+ /* True for a directive that may fail (such as wide character
+ directives). */
+ bool mayfail;
+
/* True when the argument is a null pointer. */
bool nullp;
};
@@ -2014,8 +1886,15 @@ format_floating (const directive &dir, tree arg, vr_values *)
res.range.likely = res.range.min;
res.range.max = res.range.min;
- /* The inlikely maximum is "[-/+]infinity" or "[-/+]nan". */
- res.range.unlikely = sign + (real_isinf (rvp) ? 8 : 3);
+ /* The unlikely maximum is "[-/+]infinity" or "[-/+][qs]nan".
+ For NaN, the C/POSIX standards specify two formats:
+ "[-/+]nan"
+ and
+ "[-/+]nan(n-char-sequence)"
+ No known printf implementation outputs the latter format but AIX
+ outputs QNaN and SNaN for quiet and signalling NaN, respectively,
+ so the unlikely maximum reflects that. */
+ res.range.unlikely = sign + (real_isinf (rvp) ? 8 : 4);
/* The range for infinity and NaN is known unless either width
or precision is unknown. Width has the same effect regardless
@@ -2117,25 +1996,18 @@ format_floating (const directive &dir, tree arg, vr_values *)
Used by the format_string function below. */
static fmtresult
-get_string_length (tree str)
+get_string_length (tree str, unsigned eltsize)
{
if (!str)
return fmtresult ();
- if (tree slen = c_strlen (str, 1))
- {
- /* Simply return the length of the string. */
- fmtresult res (tree_to_shwi (slen));
- return res;
- }
-
/* Determine the length of the shortest and longest string referenced
by STR. Strings of unknown lengths are bounded by the sizes of
arrays that subexpressions of STR may refer to. Pointers that
aren't known to point any such arrays result in LENRANGE[1] set
to SIZE_MAX. */
tree lenrange[2];
- bool flexarray = get_range_strlen (str, lenrange);
+ bool flexarray = get_range_strlen (str, lenrange, eltsize);
if (lenrange [0] || lenrange [1])
{
@@ -2187,7 +2059,7 @@ get_string_length (tree str)
return res;
}
- return get_string_length (NULL_TREE);
+ return fmtresult ();
}
/* Return the minimum and maximum number of characters formatted
@@ -2202,7 +2074,8 @@ format_character (const directive &dir, tree arg, vr_values *vr_values)
res.knownrange = true;
- if (dir.modifier == FMT_LEN_l)
+ if (dir.specifier == 'C'
+ || dir.modifier == FMT_LEN_l)
{
/* A wide character can result in as few as zero bytes. */
res.range.min = 0;
@@ -2217,13 +2090,20 @@ format_character (const directive &dir, tree arg, vr_values *vr_values)
res.range.likely = 0;
res.range.unlikely = 0;
}
- else if (min > 0 && min < 128)
+ else if (min >= 0 && min < 128)
{
+ /* Be conservative if the target execution character set
+ is not a 1-to-1 mapping to the source character set or
+ if the source set is not ASCII. */
+ bool one_2_one_ascii
+ = (target_to_host_charmap[0] == 1 && target_to_host ('a') == 97);
+
/* A wide character in the ASCII range most likely results
in a single byte, and only unlikely in up to MB_LEN_MAX. */
- res.range.max = 1;
+ res.range.max = one_2_one_ascii ? 1 : target_mb_len_max ();;
res.range.likely = 1;
res.range.unlikely = target_mb_len_max ();
+ res.mayfail = !one_2_one_ascii;
}
else
{
@@ -2232,6 +2112,8 @@ format_character (const directive &dir, tree arg, vr_values *vr_values)
res.range.max = target_mb_len_max ();
res.range.likely = 2;
res.range.unlikely = res.range.max;
+ /* Converting such a character may fail. */
+ res.mayfail = true;
}
}
else
@@ -2241,6 +2123,7 @@ format_character (const directive &dir, tree arg, vr_values *vr_values)
res.range.max = target_mb_len_max ();
res.range.likely = 2;
res.range.unlikely = res.range.max;
+ res.mayfail = true;
}
}
else
@@ -2266,7 +2149,8 @@ format_string (const directive &dir, tree arg, vr_values *)
fmtresult res;
/* Compute the range the argument's length can be in. */
- fmtresult slen = get_string_length (arg);
+ int count_by = dir.specifier == 'S' || dir.modifier == FMT_LEN_l ? 4 : 1;
+ fmtresult slen = get_string_length (arg, count_by);
if (slen.range.min == slen.range.max
&& slen.range.min < HOST_WIDE_INT_MAX)
{
@@ -2276,7 +2160,8 @@ format_string (const directive &dir, tree arg, vr_values *)
/* A '%s' directive with a string argument with constant length. */
res.range = slen.range;
- if (dir.modifier == FMT_LEN_l)
+ if (dir.specifier == 'S'
+ || dir.modifier == FMT_LEN_l)
{
/* In the worst case the length of output of a wide string S
is bounded by MB_LEN_MAX * wcslen (S). */
@@ -2302,6 +2187,10 @@ format_string (const directive &dir, tree arg, vr_values *)
/* Even a non-empty wide character string need not convert into
any bytes. */
res.range.min = 0;
+
+ /* A non-empty wide character conversion may fail. */
+ if (slen.range.max > 0)
+ res.mayfail = true;
}
else
{
@@ -2340,7 +2229,8 @@ format_string (const directive &dir, tree arg, vr_values *)
at level 2. This result is adjust upward for width (if it's
specified). */
- if (dir.modifier == FMT_LEN_l)
+ if (dir.specifier == 'S'
+ || dir.modifier == FMT_LEN_l)
{
/* A wide character converts to as few as zero bytes. */
slen.range.min = 0;
@@ -2352,6 +2242,10 @@ format_string (const directive &dir, tree arg, vr_values *)
if (slen.range.likely < target_int_max ())
slen.range.unlikely *= target_mb_len_max ();
+
+ /* A non-empty wide character conversion may fail. */
+ if (slen.range.max > 0)
+ res.mayfail = true;
}
res.range = slen.range;
@@ -2904,11 +2798,14 @@ format_directive (const sprintf_dom_walker::call_info &info,
of 4095 bytes required to be supported? */
bool minunder4k = fmtres.range.min < 4096;
bool maxunder4k = fmtres.range.max < 4096;
- /* Clear UNDER4K in the overall result if the maximum has exceeded
- the 4k (this is necessary to avoid the return valuye optimization
+ /* Clear POSUNDER4K in the overall result if the maximum has exceeded
+ the 4k (this is necessary to avoid the return value optimization
that may not be safe in the maximum case). */
if (!maxunder4k)
- res->under4k = false;
+ res->posunder4k = false;
+ /* Also clear POSUNDER4K if the directive may fail. */
+ if (fmtres.mayfail)
+ res->posunder4k = false;
if (!warned
/* Only warn at level 2. */
@@ -3354,12 +3251,15 @@ parse_directive (sprintf_dom_walker::call_info &info,
dir.fmtfunc = format_none;
break;
+ case 'C':
case 'c':
+ /* POSIX wide character and C/POSIX narrow character. */
dir.fmtfunc = format_character;
break;
case 'S':
case 's':
+ /* POSIX wide string and C/POSIX narrow character string. */
dir.fmtfunc = format_string;
break;
@@ -3517,10 +3417,10 @@ sprintf_dom_walker::compute_format_length (call_info &info,
res->range.min = res->range.max = 0;
/* No directive has been seen yet so the length of output is bounded
- by the known range [0, 0] (with no conversion producing more than
- 4K bytes) until determined otherwise. */
+ by the known range [0, 0] (with no conversion resulting in a failure
+ or producing more than 4K bytes) until determined otherwise. */
res->knownrange = true;
- res->under4k = true;
+ res->posunder4k = true;
res->floating = false;
res->warned = false;
@@ -3588,7 +3488,7 @@ is_call_safe (const sprintf_dom_walker::call_info &info,
const format_result &res, bool under4k,
unsigned HOST_WIDE_INT retval[2])
{
- if (under4k && !res.under4k)
+ if (under4k && !res.posunder4k)
return false;
/* The minimum return value. */
diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
index 0ae4581..85dd5bc 100644
--- a/gcc/gimple-ssa-store-merging.c
+++ b/gcc/gimple-ssa-store-merging.c
@@ -2701,16 +2701,90 @@ imm_store_chain_info::coalesce_immediate_stores ()
merged_store->start + merged_store->width - 1))
{
/* Only allow overlapping stores of constants. */
- if (info->rhs_code == INTEGER_CST
- && merged_store->stores[0]->rhs_code == INTEGER_CST
- && check_no_overlap (m_store_info, i, INTEGER_CST,
- MAX (merged_store->last_order, info->order),
- MAX (merged_store->start
- + merged_store->width,
- info->bitpos + info->bitsize)))
+ if (info->rhs_code == INTEGER_CST)
{
- merged_store->merge_overlapping (info);
- goto done;
+ bool only_constants = true;
+ store_immediate_info *infoj;
+ unsigned int j;
+ FOR_EACH_VEC_ELT (merged_store->stores, j, infoj)
+ if (infoj->rhs_code != INTEGER_CST)
+ {
+ only_constants = false;
+ break;
+ }
+ unsigned int last_order
+ = MAX (merged_store->last_order, info->order);
+ unsigned HOST_WIDE_INT end
+ = MAX (merged_store->start + merged_store->width,
+ info->bitpos + info->bitsize);
+ if (only_constants
+ && check_no_overlap (m_store_info, i, INTEGER_CST,
+ last_order, end))
+ {
+ /* check_no_overlap call above made sure there are no
+ overlapping stores with non-INTEGER_CST rhs_code
+ in between the first and last of the stores we've
+ just merged. If there are any INTEGER_CST rhs_code
+ stores in between, we need to merge_overlapping them
+ even if in the sort_by_bitpos order there are other
+ overlapping stores in between. Keep those stores as is.
+ Example:
+ MEM[(int *)p_28] = 0;
+ MEM[(char *)p_28 + 3B] = 1;
+ MEM[(char *)p_28 + 1B] = 2;
+ MEM[(char *)p_28 + 2B] = MEM[(char *)p_28 + 6B];
+ We can't merge the zero store with the store of two and
+ not merge anything else, because the store of one is
+ in the original order in between those two, but in
+ store_by_bitpos order it comes after the last store that
+ we can't merge with them. We can merge the first 3 stores
+ and keep the last store as is though. */
+ unsigned int len = m_store_info.length (), k = i;
+ for (unsigned int j = i + 1; j < len; ++j)
+ {
+ store_immediate_info *info2 = m_store_info[j];
+ if (info2->bitpos >= end)
+ break;
+ if (info2->order < last_order)
+ {
+ if (info2->rhs_code != INTEGER_CST)
+ {
+ /* Normally check_no_overlap makes sure this
+ doesn't happen, but if end grows below, then
+ we need to process more stores than
+ check_no_overlap verified. Example:
+ MEM[(int *)p_5] = 0;
+ MEM[(short *)p_5 + 3B] = 1;
+ MEM[(char *)p_5 + 4B] = _9;
+ MEM[(char *)p_5 + 2B] = 2; */
+ k = 0;
+ break;
+ }
+ k = j;
+ end = MAX (end, info2->bitpos + info2->bitsize);
+ }
+ }
+
+ if (k != 0)
+ {
+ merged_store->merge_overlapping (info);
+
+ for (unsigned int j = i + 1; j <= k; j++)
+ {
+ store_immediate_info *info2 = m_store_info[j];
+ gcc_assert (info2->bitpos < end);
+ if (info2->order < last_order)
+ {
+ gcc_assert (info2->rhs_code == INTEGER_CST);
+ merged_store->merge_overlapping (info2);
+ }
+ /* Other stores are kept and not merged in any
+ way. */
+ }
+ ignore = k;
+ goto done;
+ }
+ }
}
}
/* |---store 1---||---store 2---|
diff --git a/gcc/gimple-ssa-warn-alloca.c b/gcc/gimple-ssa-warn-alloca.c
index 0331f66..d1b1de4 100644
--- a/gcc/gimple-ssa-warn-alloca.c
+++ b/gcc/gimple-ssa-warn-alloca.c
@@ -38,6 +38,8 @@ along with GCC; see the file COPYING3. If not see
#include "cfgloop.h"
#include "intl.h"
+static unsigned HOST_WIDE_INT adjusted_warn_limit (bool);
+
const pass_data pass_data_walloca = {
GIMPLE_PASS,
"walloca",
@@ -82,7 +84,9 @@ pass_walloca::gate (function *fun ATTRIBUTE_UNUSED)
// Warning is disabled when its size limit is greater than PTRDIFF_MAX
// for the target maximum, which makes the limit negative since when
// represented in signed HOST_WIDE_INT.
- return warn_alloca_limit >= 0 || warn_vla_limit >= 0;
+ unsigned HOST_WIDE_INT max = tree_to_uhwi (TYPE_MAX_VALUE (ptrdiff_type_node));
+ return (adjusted_warn_limit (false) <= max
+ || adjusted_warn_limit (true) <= max);
}
// Possible problematic uses of alloca.
@@ -124,9 +128,37 @@ struct alloca_type_and_limit {
alloca_type_and_limit ();
alloca_type_and_limit (enum alloca_type type,
wide_int i) : type(type), limit(i) { }
- alloca_type_and_limit (enum alloca_type type) : type(type) { }
+ alloca_type_and_limit (enum alloca_type type) : type(type)
+ { if (type == ALLOCA_BOUND_MAYBE_LARGE
+ || type == ALLOCA_BOUND_DEFINITELY_LARGE)
+ limit = wi::to_wide (integer_zero_node);
+ }
};
+/* Return the value of the argument N to -Walloca-larger-than= or
+ -Wvla-larger-than= adjusted for the target data model so that
+ when N == HOST_WIDE_INT_MAX, the adjusted value is set to
+ PTRDIFF_MAX on the target. This is done to prevent warnings
+ for unknown/unbounded allocations in the "permissive mode"
+ while still diagnosing excessive and necessarily invalid
+ allocations. */
+
+static unsigned HOST_WIDE_INT
+adjusted_warn_limit (bool idx)
+{
+ static HOST_WIDE_INT limits[2];
+ if (limits[idx])
+ return limits[idx];
+
+ limits[idx] = idx ? warn_vla_limit : warn_alloca_limit;
+ if (limits[idx] != HOST_WIDE_INT_MAX)
+ return limits[idx];
+
+ limits[idx] = tree_to_shwi (TYPE_MAX_VALUE (ptrdiff_type_node));
+ return limits[idx];
+}
+
+
// NOTE: When we get better range info, this entire function becomes
// irrelevant, as it should be possible to get range info for an SSA
// name at any point in the program.
@@ -309,11 +341,7 @@ alloca_call_type (gimple *stmt, bool is_vla, tree *invalid_casted_type)
// Adjust warn_alloca_max_size for VLAs, by taking the underlying
// type into account.
- unsigned HOST_WIDE_INT max_size;
- if (is_vla)
- max_size = warn_vla_limit;
- else
- max_size = warn_alloca_limit;
+ unsigned HOST_WIDE_INT max_size = adjusted_warn_limit (is_vla);
// Check for the obviously bounded case.
if (TREE_CODE (len) == INTEGER_CST)
@@ -510,6 +538,8 @@ pass_walloca::execute (function *fun)
struct alloca_type_and_limit t
= alloca_call_type (stmt, is_vla, &invalid_casted_type);
+ unsigned HOST_WIDE_INT adjusted_alloca_limit
+ = adjusted_warn_limit (false);
// Even if we think the alloca call is OK, make sure it's not in a
// loop, except for a VLA, since VLAs are guaranteed to be cleaned
// up when they go out of scope, including in a loop.
@@ -519,8 +549,7 @@ pass_walloca::execute (function *fun)
is less than the maximum valid object size. */
const offset_int maxobjsize
= wi::to_offset (max_object_size ());
- if ((unsigned HOST_WIDE_INT) warn_alloca_limit
- < maxobjsize.to_uhwi ())
+ if (adjusted_alloca_limit < maxobjsize.to_uhwi ())
t = alloca_type_and_limit (ALLOCA_IN_LOOP);
}
@@ -532,29 +561,38 @@ pass_walloca::execute (function *fun)
case ALLOCA_OK:
break;
case ALLOCA_BOUND_MAYBE_LARGE:
- if (warning_at (loc, wcode,
- is_vla ? G_("argument to variable-length array "
- "may be too large")
- : G_("argument to %<alloca%> may be too large"))
- && t.limit != 0)
- {
- print_decu (t.limit, buff);
- inform (loc, G_("limit is %wu bytes, but argument "
- "may be as large as %s"),
- is_vla ? warn_vla_limit : warn_alloca_limit, buff);
- }
+ {
+ auto_diagnostic_group d;
+ if (warning_at (loc, wcode,
+ is_vla ? G_("argument to variable-length "
+ "array may be too large")
+ : G_("argument to %<alloca%> may be too "
+ "large"))
+ && t.limit != 0)
+ {
+ print_decu (t.limit, buff);
+ inform (loc, G_("limit is %wu bytes, but argument "
+ "may be as large as %s"),
+ is_vla ? warn_vla_limit : adjusted_alloca_limit,
+ buff);
+ }
+ }
break;
case ALLOCA_BOUND_DEFINITELY_LARGE:
- if (warning_at (loc, wcode,
- is_vla ? G_("argument to variable-length array "
- "is too large")
- : G_("argument to %<alloca%> is too large"))
- && t.limit != 0)
- {
- print_decu (t.limit, buff);
- inform (loc, G_("limit is %wu bytes, but argument is %s"),
- is_vla ? warn_vla_limit : warn_alloca_limit, buff);
- }
+ {
+ auto_diagnostic_group d;
+ if (warning_at (loc, wcode,
+ is_vla ? G_("argument to variable-length"
+ " array is too large")
+ : G_("argument to %<alloca%> is too large"))
+ && t.limit != 0)
+ {
+ print_decu (t.limit, buff);
+ inform (loc, G_("limit is %wu bytes, but argument is %s"),
+ is_vla ? warn_vla_limit : adjusted_alloca_limit,
+ buff);
+ }
+ }
break;
case ALLOCA_BOUND_UNKNOWN:
warning_at (loc, wcode,
diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c
index 7dedb24..ea30b71 100644
--- a/gcc/gimple-ssa-warn-restrict.c
+++ b/gcc/gimple-ssa-warn-restrict.c
@@ -88,7 +88,7 @@ class wrestrict_dom_walker : public dom_walker
bool handle_gimple_call (gimple_stmt_iterator *);
private:
- void check_call (gcall *);
+ void check_call (gimple *);
};
edge
@@ -102,8 +102,7 @@ wrestrict_dom_walker::before_dom_children (basic_block bb)
if (!is_gimple_call (stmt))
continue;
- if (gcall *call = as_a <gcall *> (stmt))
- check_call (call);
+ check_call (stmt);
}
return NULL;
@@ -192,7 +191,7 @@ class builtin_access
return detect_overlap != &builtin_access::generic_overlap;
}
- builtin_access (gcall *, builtin_memref &, builtin_memref &);
+ builtin_access (gimple *, builtin_memref &, builtin_memref &);
/* Entry point to determine overlap. */
bool overlap ();
@@ -563,7 +562,7 @@ builtin_memref::offset_out_of_bounds (int strict, offset_int ooboff[2]) const
/* Create an association between the memory references DST and SRC
for access by a call EXPR to a memory or string built-in funtion. */
-builtin_access::builtin_access (gcall *call, builtin_memref &dst,
+builtin_access::builtin_access (gimple *call, builtin_memref &dst,
builtin_memref &src)
: dstref (&dst), srcref (&src), sizrange (), ovloff (), ovlsiz (),
dstoff (), srcoff (), dstsiz (), srcsiz ()
@@ -1324,7 +1323,7 @@ builtin_access::overlap ()
Return true when one has been detected, false otherwise. */
static bool
-maybe_diag_overlap (location_t loc, gcall *call, builtin_access &acs)
+maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
{
if (!acs.overlap ())
return false;
@@ -1577,7 +1576,7 @@ maybe_diag_overlap (location_t loc, gcall *call, builtin_access &acs)
has been issued. */
static bool
-maybe_diag_offset_bounds (location_t loc, gcall *call, tree func, int strict,
+maybe_diag_offset_bounds (location_t loc, gimple *call, tree func, int strict,
tree expr, const builtin_memref &ref)
{
if (!warn_array_bounds)
@@ -1619,6 +1618,7 @@ maybe_diag_offset_bounds (location_t loc, gcall *call, tree func, int strict,
if (DECL_P (ref.base)
&& TREE_CODE (type = TREE_TYPE (ref.base)) == ARRAY_TYPE)
{
+ auto_diagnostic_group d;
if (warning_at (loc, OPT_Warray_bounds,
"%G%qD pointer overflow between offset %s "
"and size %s accessing array %qD with type %qT",
@@ -1651,6 +1651,7 @@ maybe_diag_offset_bounds (location_t loc, gcall *call, tree func, int strict,
if (DECL_P (ref.base))
{
+ auto_diagnostic_group d;
if ((ref.basesize < maxobjsize
&& warning_at (loc, OPT_Warray_bounds,
form
@@ -1722,7 +1723,7 @@ maybe_diag_offset_bounds (location_t loc, gcall *call, tree func, int strict,
if/when appropriate. */
void
-wrestrict_dom_walker::check_call (gcall *call)
+wrestrict_dom_walker::check_call (gimple *call)
{
/* Avoid checking the call if it has already been diagnosed for
some reason. */
@@ -1730,7 +1731,7 @@ wrestrict_dom_walker::check_call (gcall *call)
return;
tree func = gimple_call_fndecl (call);
- if (!func || DECL_BUILT_IN_CLASS (func) != BUILT_IN_NORMAL)
+ if (!func || !fndecl_built_in_p (func, BUILT_IN_NORMAL))
return;
/* Argument number to extract from the call (depends on the built-in
@@ -1822,7 +1823,7 @@ wrestrict_dom_walker::check_call (gcall *call)
detected and diagnosed, true otherwise. */
bool
-check_bounds_or_overlap (gcall *call, tree dst, tree src, tree dstsize,
+check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize,
tree srcsize, bool bounds_only /* = false */)
{
location_t loc = gimple_nonartificial_location (call);
diff --git a/gcc/gimple-ssa-warn-restrict.h b/gcc/gimple-ssa-warn-restrict.h
index 9bf84a3..c624589 100644
--- a/gcc/gimple-ssa-warn-restrict.h
+++ b/gcc/gimple-ssa-warn-restrict.h
@@ -20,7 +20,7 @@
#ifndef GIMPLE_SSA_WARN_RESTRICT_H
-extern bool check_bounds_or_overlap (gcall *, tree, tree, tree, tree,
+extern bool check_bounds_or_overlap (gimple *, tree, tree, tree, tree,
bool = false);
#endif /* GIMPLE_SSA_WARN_RESTRICT_H */
diff --git a/gcc/gimple-streamer-in.c b/gcc/gimple-streamer-in.c
index 6ffef29..31ba4cc 100644
--- a/gcc/gimple-streamer-in.c
+++ b/gcc/gimple-streamer-in.c
@@ -270,6 +270,7 @@ input_bb (struct lto_input_block *ib, enum LTO_tags tag,
bb->count
= bb->count.apply_scale (count_materialization_scale, REG_BR_PROB_BASE);
bb->flags = streamer_read_hwi (ib);
+ bb->discriminator = streamer_read_hwi (ib);
/* LTO_bb1 has statements. LTO_bb0 does not. */
if (tag == LTO_bb0)
diff --git a/gcc/gimple-streamer-out.c b/gcc/gimple-streamer-out.c
index d120aa9..3a23680 100644
--- a/gcc/gimple-streamer-out.c
+++ b/gcc/gimple-streamer-out.c
@@ -212,6 +212,7 @@ output_bb (struct output_block *ob, basic_block bb, struct function *fn)
streamer_write_uhwi (ob, bb->index);
bb->count.stream_out (ob);
streamer_write_hwi (ob, bb->flags);
+ streamer_write_hwi (ob, bb->discriminator);
if (!gsi_end_p (bsi) || phi_nodes (bb))
{
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 8d56a96..e3e651b 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -376,7 +376,7 @@ gimple_build_call_from_tree (tree t, tree fnptrtype)
gimple_call_set_must_tail (call, CALL_EXPR_MUST_TAIL_CALL (t));
gimple_call_set_return_slot_opt (call, CALL_EXPR_RETURN_SLOT_OPT (t));
if (fndecl
- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
+ && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
&& ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (fndecl)))
gimple_call_set_alloca_for_var (call, CALL_ALLOCA_FOR_VAR_P (t));
else
@@ -2681,8 +2681,7 @@ gimple_call_builtin_p (const gimple *stmt, enum built_in_function code)
tree fndecl;
if (is_gimple_call (stmt)
&& (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (fndecl) == code)
+ && fndecl_built_in_p (fndecl, code))
return gimple_builtin_call_types_compatible_p (stmt, fndecl);
return false;
}
@@ -2701,7 +2700,7 @@ gimple_call_combined_fn (const gimple *stmt)
tree fndecl = gimple_call_fndecl (stmt);
if (fndecl
- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
+ && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
&& gimple_builtin_call_types_compatible_p (stmt, fndecl))
return as_combined_fn (DECL_FUNCTION_CODE (fndecl));
}
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 4a109ae..509fc2f 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -2173,6 +2173,7 @@ warn_implicit_fallthrough_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
{
struct label_entry *l;
bool warned_p = false;
+ auto_diagnostic_group d;
if (!should_warn_for_implicit_fallthrough (gsi_p, label))
/* Quiet. */;
else if (gimple_code (prev) == GIMPLE_LABEL
@@ -3208,8 +3209,7 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
transform all calls in the same manner as the expanders do, but
we do transform most of them. */
fndecl = get_callee_fndecl (*expr_p);
- if (fndecl
- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+ if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
switch (DECL_FUNCTION_CODE (fndecl))
{
CASE_BUILT_IN_ALLOCA:
@@ -3244,7 +3244,7 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
default:
;
}
- if (fndecl && DECL_BUILT_IN (fndecl))
+ if (fndecl && fndecl_built_in_p (fndecl))
{
tree new_tree = fold_call_expr (input_location, *expr_p, !want_value);
if (new_tree && new_tree != *expr_p)
@@ -3296,9 +3296,7 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
tree last_arg_fndecl = get_callee_fndecl (last_arg);
if (last_arg_fndecl
- && TREE_CODE (last_arg_fndecl) == FUNCTION_DECL
- && DECL_BUILT_IN_CLASS (last_arg_fndecl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (last_arg_fndecl) == BUILT_IN_VA_ARG_PACK)
+ && fndecl_built_in_p (last_arg_fndecl, BUILT_IN_VA_ARG_PACK))
{
tree call = *expr_p;
@@ -3772,8 +3770,7 @@ gimple_boolify (tree expr)
/* For __builtin_expect ((long) (x), y) recurse into x as well
if x is truth_value_p. */
if (fn
- && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (fn) == BUILT_IN_EXPECT
+ && fndecl_built_in_p (fn, BUILT_IN_EXPECT)
&& call_expr_nargs (call) == 2)
{
tree arg = CALL_EXPR_ARG (call, 0);
@@ -5718,8 +5715,7 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
STRIP_USELESS_TYPE_CONVERSION (CALL_EXPR_FN (*from_p));
tree fndecl = get_callee_fndecl (*from_p);
if (fndecl
- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT
+ && fndecl_built_in_p (fndecl, BUILT_IN_EXPECT)
&& call_expr_nargs (*from_p) == 3)
call_stmt = gimple_build_call_internal (IFN_BUILTIN_EXPECT, 3,
CALL_EXPR_ARG (*from_p, 0),
@@ -5977,7 +5973,7 @@ gimplify_addr_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
being taken (we can unify those cases here) then we can mark
the builtin for implicit generation by GCC. */
if (TREE_CODE (op0) == FUNCTION_DECL
- && DECL_BUILT_IN_CLASS (op0) == BUILT_IN_NORMAL
+ && fndecl_built_in_p (op0, BUILT_IN_NORMAL)
&& builtin_decl_declared_p (DECL_FUNCTION_CODE (op0)))
set_builtin_decl_implicit_p (DECL_FUNCTION_CODE (op0), true);
@@ -7517,6 +7513,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
case OMP_TARGET_EXIT_DATA:
case OACC_DECLARE:
case OACC_HOST_DATA:
+ case OACC_PARALLEL:
+ case OACC_KERNELS:
ctx->target_firstprivatize_array_bases = true;
default:
break;
@@ -8560,7 +8558,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
if (code == OACC_DATA
&& OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
- && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
+ && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
remove = true;
if (remove)
*list_p = OMP_CLAUSE_CHAIN (c);
@@ -12539,9 +12538,15 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
/* An lvalue will do. Take the address of the expression, store it
in a temporary, and replace the expression with an INDIRECT_REF of
that temporary. */
+ tree ref_alias_type = reference_alias_ptr_type (*expr_p);
+ unsigned int ref_align = get_object_alignment (*expr_p);
+ tree ref_type = TREE_TYPE (*expr_p);
tmp = build_fold_addr_expr_loc (input_location, *expr_p);
gimplify_expr (&tmp, pre_p, post_p, is_gimple_reg, fb_rvalue);
- *expr_p = build_simple_mem_ref (tmp);
+ if (TYPE_ALIGN (ref_type) != ref_align)
+ ref_type = build_aligned_type (ref_type, ref_align);
+ *expr_p = build2 (MEM_REF, ref_type,
+ tmp, build_zero_cst (ref_alias_type));
}
else if ((fallback & fb_rvalue) && is_gimple_reg_rhs_or_call (*expr_p))
{
@@ -13079,6 +13084,7 @@ gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p,
/* Unfortunately, this is merely undefined, rather than a constraint
violation, so we cannot make this an error. If this call is never
executed, the program is still strictly conforming. */
+ auto_diagnostic_group d;
warned = warning_at (xloc, 0,
"%qT is promoted to %qT when passed through %<...%>",
type, promoted_type);
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index a392ed8..3512922 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,13 @@
+2018-09-20 Allan Sandfeld Jensen <allan.jensen@qt.io>
+
+ * gospec.c (lang_specific_driver): Handle -r like -nostdlib.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ * go-gcc.cc (Gcc_backend::call_expression): Use new function
+ fndecl_built_in_p and remove check for FUNCTION_DECL if
+ possible.
+
2018-07-20 Martin Sebor <msebor@redhat.com>
PR middle-end/82063
@@ -468,7 +478,7 @@
2015-07-12 Aldy Hernandez <aldyh@redhat.com>
* gofrontend/backend.h: Fix double word typos.
- * gofrontend/expressions.cc: Same.
+ * gofrontend/expressions.cc: Same.
* gospec.c: Same.
2015-07-07 Andrew MacLeod <amacleod@redhat.com>
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index 76a2026..1a449b7 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -1948,8 +1948,8 @@ Gcc_backend::call_expression(Bfunction*, // containing fcn for call
tree excess_type = NULL_TREE;
if (optimize
&& TREE_CODE(fndecl) == FUNCTION_DECL
- && DECL_IS_BUILTIN(fndecl)
- && DECL_BUILT_IN_CLASS(fndecl) == BUILT_IN_NORMAL
+ && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
+ && DECL_IS_BUILTIN (fndecl)
&& nargs > 0
&& ((SCALAR_FLOAT_TYPE_P(rettype)
&& SCALAR_FLOAT_TYPE_P(TREE_TYPE(args[0])))
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 95b6bcc..175db5d 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-a2e0ad16555b2698df8e71f4c0fe02e185715bc1
+7b25b4dff4778fc4d6b5d6e10594814146b3e5dd
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/escape.cc b/gcc/go/gofrontend/escape.cc
index e32ae5b..9c31525 100644
--- a/gcc/go/gofrontend/escape.cc
+++ b/gcc/go/gofrontend/escape.cc
@@ -1361,7 +1361,13 @@ Escape_analysis_assign::statement(Block*, size_t*, Statement* s)
{
Expression* init = s->temporary_statement()->init();
if (init != NULL)
- this->assign(Node::make_node(s), Node::make_node(init));
+ {
+ Node* n = Node::make_node(init);
+ if (s->temporary_statement()->value_escapes())
+ this->assign(this->context_->sink(), n);
+ else
+ this->assign(Node::make_node(s), n);
+ }
}
break;
@@ -1616,15 +1622,6 @@ Escape_analysis_assign::expression(Expression** pexpr)
}
break;
- case Runtime::SELECTSEND:
- {
- // Send to a channel, lose track. The last argument is
- // the address of the value to send.
- Node* arg_node = Node::make_node(call->args()->back());
- this->assign_deref(this->context_->sink(), arg_node);
- }
- break;
-
case Runtime::IFACEE2T2:
case Runtime::IFACEI2T2:
{
@@ -2228,8 +2225,12 @@ Escape_analysis_assign::assign(Node* dst, Node* src)
case Expression::EXPRESSION_TEMPORARY_REFERENCE:
{
// Temporary is tracked through the underlying Temporary_statement.
- Statement* t = dst->expr()->temporary_reference_expression()->statement();
- dst = Node::make_node(t);
+ Temporary_statement* t =
+ dst->expr()->temporary_reference_expression()->statement();
+ if (t->value_escapes())
+ dst = this->context_->sink();
+ else
+ dst = Node::make_node(t);
}
break;
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 2c2ae1c..46a1e69 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -131,6 +131,40 @@ Expression::determine_type_no_context()
this->do_determine_type(&context);
}
+// Return true if two expressions refer to the same variable or struct
+// field. This can only be true when there are no side effects.
+
+bool
+Expression::is_same_variable(Expression* a, Expression* b)
+{
+ if (a->classification() != b->classification())
+ return false;
+
+ Var_expression* av = a->var_expression();
+ if (av != NULL)
+ return av->named_object() == b->var_expression()->named_object();
+
+ Field_reference_expression* af = a->field_reference_expression();
+ if (af != NULL)
+ {
+ Field_reference_expression* bf = b->field_reference_expression();
+ return (af->field_index() == bf->field_index()
+ && Expression::is_same_variable(af->expr(), bf->expr()));
+ }
+
+ Unary_expression* au = a->unary_expression();
+ if (au != NULL)
+ {
+ Unary_expression* bu = b->unary_expression();
+ return (au->op() == OPERATOR_MULT
+ && bu->op() == OPERATOR_MULT
+ && Expression::is_same_variable(au->operand(),
+ bu->operand()));
+ }
+
+ return false;
+}
+
// Return an expression handling any conversions which must be done during
// assignment.
@@ -4453,7 +4487,8 @@ Unary_expression::do_get_backend(Translate_context* context)
// initialize the value once, so we can use this directly
// rather than copying it. In that case we can't make it
// read-only, because the program is permitted to change it.
- copy_to_heap = context->function() != NULL;
+ copy_to_heap = (context->function() != NULL
+ || context->is_const());
}
std::string asm_name(go_selectively_encode_id(var_name));
Bvariable* implicit =
@@ -7374,7 +7409,32 @@ Builtin_call_expression::do_lower(Gogo*, Named_object* function,
loc);
Expression* e3 = Expression::make_temporary_reference(key_temp,
loc);
- e3 = Expression::make_unary(OPERATOR_AND, e3, loc);
+
+ // If the call to delete is deferred, and is in a loop,
+ // then the loop will only have a single instance of the
+ // temporary variable. Passing the address of the
+ // temporary variable here means that the deferred call
+ // will see the last value in the loop, not the current
+ // value. So for this unusual case copy the value into
+ // the heap.
+ if (!this->is_deferred())
+ e3 = Expression::make_unary(OPERATOR_AND, e3, loc);
+ else
+ {
+ Expression* a = Expression::make_allocation(mt->key_type(),
+ loc);
+ Temporary_statement* atemp =
+ Statement::make_temporary(NULL, a, loc);
+ inserter->insert(atemp);
+
+ a = Expression::make_temporary_reference(atemp, loc);
+ a = Expression::make_dereference(a, NIL_CHECK_NOT_NEEDED, loc);
+ Statement* s = Statement::make_assignment(a, e3, loc);
+ inserter->insert(s);
+
+ e3 = Expression::make_temporary_reference(atemp, loc);
+ }
+
return Runtime::make_call(Runtime::MAPDELETE, this->location(),
3, e1, e2, e3);
}
@@ -7420,7 +7480,7 @@ Builtin_call_expression::do_flatten(Gogo* gogo, Named_object* function,
break;
case BUILTIN_APPEND:
- return this->flatten_append(gogo, function, inserter);
+ return this->flatten_append(gogo, function, inserter, NULL, NULL);
case BUILTIN_COPY:
{
@@ -7657,11 +7717,18 @@ Builtin_call_expression::lower_make(Statement_inserter* inserter)
// Flatten a call to the predeclared append function. We do this in
// the flatten phase, not the lowering phase, so that we run after
-// type checking and after order_evaluations.
+// type checking and after order_evaluations. If ASSIGN_LHS is not
+// NULL, this append is the right-hand-side of an assignment and
+// ASSIGN_LHS is the left-hand-side; in that case, set LHS directly
+// rather than returning a slice. This lets us omit a write barrier
+// in common cases like a = append(a, ...) when the slice does not
+// need to grow. ENCLOSING is not NULL iff ASSIGN_LHS is not NULL.
Expression*
Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function,
- Statement_inserter* inserter)
+ Statement_inserter* inserter,
+ Expression* assign_lhs,
+ Block* enclosing)
{
if (this->is_error_expression())
return this;
@@ -7678,6 +7745,8 @@ Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function,
if (args->size() == 1)
{
// append(s) evaluates to s.
+ if (assign_lhs != NULL)
+ return NULL;
return args->front();
}
@@ -7794,14 +7863,46 @@ Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function,
// FIXME: Mark this index as not requiring bounds checks.
ref = Expression::make_index(ref, zero, ref2, NULL, loc);
- Expression* rhs = Expression::make_conditional(cond, call, ref, loc);
+ if (assign_lhs == NULL)
+ {
+ Expression* rhs = Expression::make_conditional(cond, call, ref, loc);
+
+ gogo->lower_expression(function, inserter, &rhs);
+ gogo->flatten_expression(function, inserter, &rhs);
+
+ ref = Expression::make_temporary_reference(s1tmp, loc);
+ Statement* assign = Statement::make_assignment(ref, rhs, loc);
+ inserter->insert(assign);
+ }
+ else
+ {
+ gogo->lower_expression(function, inserter, &cond);
+ gogo->flatten_expression(function, inserter, &cond);
+ gogo->lower_expression(function, inserter, &call);
+ gogo->flatten_expression(function, inserter, &call);
+ gogo->lower_expression(function, inserter, &ref);
+ gogo->flatten_expression(function, inserter, &ref);
+
+ Block* then_block = new Block(enclosing, loc);
+ Assignment_statement* assign =
+ Statement::make_assignment(assign_lhs, call, loc);
+ then_block->add_statement(assign);
- gogo->lower_expression(function, inserter, &rhs);
- gogo->flatten_expression(function, inserter, &rhs);
+ Block* else_block = new Block(enclosing, loc);
+ assign = Statement::make_assignment(assign_lhs->copy(), ref, loc);
+ // This assignment will not change the pointer value, so it does
+ // not need a write barrier.
+ assign->set_omit_write_barrier();
+ else_block->add_statement(assign);
- Expression* lhs = Expression::make_temporary_reference(s1tmp, loc);
- Statement* assign = Statement::make_assignment(lhs, rhs, loc);
- inserter->insert(assign);
+ Statement* s = Statement::make_if_statement(cond, then_block,
+ else_block, loc);
+ inserter->insert(s);
+
+ ref = Expression::make_temporary_reference(s1tmp, loc);
+ assign = Statement::make_assignment(ref, assign_lhs->copy(), loc);
+ inserter->insert(assign);
+ }
if (this->is_varargs())
{
@@ -7838,12 +7939,17 @@ Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function,
Expression* off = Expression::make_integer_ul(i, int_type, loc);
ref2 = Expression::make_binary(OPERATOR_PLUS, ref2, off, loc);
// FIXME: Mark this index as not requiring bounds checks.
- lhs = Expression::make_index(ref, ref2, NULL, NULL, loc);
+ Expression* lhs = Expression::make_index(ref, ref2, NULL, NULL,
+ loc);
gogo->lower_expression(function, inserter, &lhs);
gogo->flatten_expression(function, inserter, &lhs);
// The flatten pass runs after the write barrier pass, so we
// need to insert a write barrier here if necessary.
- if (!gogo->assign_needs_write_barrier(lhs))
+ // However, if ASSIGN_LHS is not NULL, we have been called
+ // directly before the write barrier pass.
+ Statement* assign;
+ if (assign_lhs != NULL
+ || !gogo->assign_needs_write_barrier(lhs))
assign = Statement::make_assignment(lhs, *pa, loc);
else
{
@@ -7855,6 +7961,9 @@ Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function,
}
}
+ if (assign_lhs != NULL)
+ return NULL;
+
return Expression::make_temporary_reference(s1tmp, loc);
}
@@ -8940,6 +9049,10 @@ Builtin_call_expression::do_copy()
if (this->varargs_are_lowered())
bce->set_varargs_are_lowered();
+ if (this->is_deferred())
+ bce->set_is_deferred();
+ if (this->is_concurrent())
+ bce->set_is_concurrent();
return bce;
}
@@ -9522,8 +9635,16 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function,
// Recognize a call to a builtin function.
if (fntype->is_builtin())
- return new Builtin_call_expression(gogo, this->fn_, this->args_,
- this->is_varargs_, loc);
+ {
+ Builtin_call_expression* bce =
+ new Builtin_call_expression(gogo, this->fn_, this->args_,
+ this->is_varargs_, loc);
+ if (this->is_deferred_)
+ bce->set_is_deferred();
+ if (this->is_concurrent_)
+ bce->set_is_concurrent();
+ return bce;
+ }
// If this call returns multiple results, create a temporary
// variable to hold them.
@@ -9635,13 +9756,9 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function,
"__builtin_return_address",
0);
}
- else if (this->args_ != NULL
- && this->args_->size() == 1
+ else if ((this->args_ == NULL || this->args_->size() == 0)
&& n == "getcallersp")
{
- // The actual argument to getcallersp is always the
- // address of a parameter; we don't need that for the
- // GCC builtin function, so we just ignore it.
static Named_object* builtin_frame_address;
return this->lower_to_builtin(&builtin_frame_address,
"__builtin_frame_address",
@@ -10195,6 +10312,10 @@ Call_expression::do_copy()
if (this->varargs_are_lowered_)
call->set_varargs_are_lowered();
+ if (this->is_deferred_)
+ call->set_is_deferred();
+ if (this->is_concurrent_)
+ call->set_is_concurrent();
return call;
}
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 5fa4171..f53cc6e 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -869,6 +869,11 @@ class Expression
bool
is_local_variable() const;
+ // Return true if two expressions refer to the same variable or
+ // struct field.
+ static bool
+ is_same_variable(Expression*, Expression*);
+
// Make the builtin function descriptor type, so that it can be
// converted.
static void
@@ -2402,6 +2407,10 @@ class Builtin_call_expression : public Call_expression
static bool
array_len_is_constant(Expression* expr);
+ Expression*
+ flatten_append(Gogo*, Named_object*, Statement_inserter*, Expression*,
+ Block*);
+
protected:
// This overrides Call_expression::do_lower.
Expression*
@@ -2459,8 +2468,6 @@ class Builtin_call_expression : public Call_expression
Expression*
lower_make(Statement_inserter*);
- Expression* flatten_append(Gogo*, Named_object*, Statement_inserter*);
-
bool
check_int_value(Expression*, bool is_length, bool* small);
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index c16b40e..dd6733f 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -1535,7 +1535,8 @@ Gogo::write_globals()
// Avoid putting runtime.gcRoots itself on the list.
if (this->compiling_runtime()
&& this->package_name() == "runtime"
- && Gogo::unpack_hidden_name(no->name()) == "gcRoots")
+ && (Gogo::unpack_hidden_name(no->name()) == "gcRoots"
+ || Gogo::unpack_hidden_name(no->name()) == "gcRootsIndex"))
;
else
var_gc.push_back(no);
diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h
index 6511599..0864ee1 100644
--- a/gcc/go/gofrontend/gogo.h
+++ b/gcc/go/gofrontend/gogo.h
@@ -941,6 +941,9 @@ class Gogo
std::vector<Bstatement*>&,
Bfunction* init_bfunction);
+ void
+ propagate_writebarrierrec();
+
Named_object*
write_barrier_variable();
diff --git a/gcc/go/gofrontend/lex.cc b/gcc/go/gofrontend/lex.cc
index 560f5f9..3965f30 100644
--- a/gcc/go/gofrontend/lex.cc
+++ b/gcc/go/gofrontend/lex.cc
@@ -1922,9 +1922,15 @@ Lex::skip_cpp_comment()
// function that it calls, needs to use any write barriers, it
// should emit an error instead.
// FIXME: Should only work when compiling the runtime package.
- // FIXME: currently treated the same as go:nowritebarrier
this->pragmas_ |= GOPRAGMA_NOWRITEBARRIERREC;
}
+ else if (verb == "go:yeswritebarrierrec")
+ {
+ // Applies to the next function. Disables go:nowritebarrierrec
+ // when looking at callees; write barriers are permitted here.
+ // FIXME: Should only work when compiling the runtime package.
+ this->pragmas_ |= GOPRAGMA_YESWRITEBARRIERREC;
+ }
else if (verb == "go:cgo_unsafe_args")
{
// Applies to the next function. Taking the address of any
diff --git a/gcc/go/gofrontend/lex.h b/gcc/go/gofrontend/lex.h
index a8b7091..70f752b 100644
--- a/gcc/go/gofrontend/lex.h
+++ b/gcc/go/gofrontend/lex.h
@@ -63,9 +63,11 @@ enum GoPragma
GOPRAGMA_SYSTEMSTACK = 1 << 5, // Must run on system stack.
GOPRAGMA_NOWRITEBARRIER = 1 << 6, // No write barriers.
GOPRAGMA_NOWRITEBARRIERREC = 1 << 7, // No write barriers here or callees.
- GOPRAGMA_CGOUNSAFEARGS = 1 << 8, // Pointer to arg is pointer to all.
- GOPRAGMA_UINTPTRESCAPES = 1 << 9, // uintptr(p) escapes.
- GOPRAGMA_NOTINHEAP = 1 << 10 // type is not in heap.
+ GOPRAGMA_YESWRITEBARRIERREC = 1 << 8, // Stops nowritebarrierrec.
+ GOPRAGMA_MARK = 1 << 9, // Marker for nowritebarrierrec.
+ GOPRAGMA_CGOUNSAFEARGS = 1 << 10, // Pointer to arg is pointer to all.
+ GOPRAGMA_UINTPTRESCAPES = 1 << 11, // uintptr(p) escapes.
+ GOPRAGMA_NOTINHEAP = 1 << 12 // type is not in heap.
};
// A token returned from the lexer.
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index 4891e75..6ed4377 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -2360,7 +2360,10 @@ Parse::function_decl(unsigned int pragmas)
{ GOPRAGMA_NOINLINE, "noinline", false, true, true },
{ GOPRAGMA_SYSTEMSTACK, "systemstack", false, true, true },
{ GOPRAGMA_NOWRITEBARRIER, "nowritebarrier", false, true, true },
- { GOPRAGMA_NOWRITEBARRIERREC, "nowritebarrierrec", false, true, true },
+ { GOPRAGMA_NOWRITEBARRIERREC, "nowritebarrierrec", false, true,
+ true },
+ { GOPRAGMA_YESWRITEBARRIERREC, "yeswritebarrierrec", false, true,
+ true },
{ GOPRAGMA_CGOUNSAFEARGS, "cgo_unsafe_args", false, true, true },
{ GOPRAGMA_UINTPTRESCAPES, "uintptrescapes", true, true, true },
};
@@ -4301,9 +4304,15 @@ Parse::go_or_defer_stat()
this->gogo_->start_block(stat_location);
Statement* stat;
if (is_go)
- stat = Statement::make_go_statement(call_expr, stat_location);
+ {
+ stat = Statement::make_go_statement(call_expr, stat_location);
+ call_expr->set_is_concurrent();
+ }
else
- stat = Statement::make_defer_statement(call_expr, stat_location);
+ {
+ stat = Statement::make_defer_statement(call_expr, stat_location);
+ call_expr->set_is_deferred();
+ }
this->gogo_->add_statement(stat);
this->gogo_->add_block(this->gogo_->finish_block(stat_location),
stat_location);
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index fdb159e..ed759e8 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -152,22 +152,10 @@ DEF_GO_RUNTIME(CHANRECV1, "runtime.chanrecv1", P2(CHAN, POINTER), R0())
DEF_GO_RUNTIME(CHANRECV2, "runtime.chanrecv2", P2(CHAN, POINTER), R1(BOOL))
-// Start building a select statement.
-DEF_GO_RUNTIME(NEWSELECT, "runtime.newselect", P3(POINTER, INT64, INT32), R0())
-
-// Add a default clause to a select statement.
-DEF_GO_RUNTIME(SELECTDEFAULT, "runtime.selectdefault", P1(POINTER), R0())
-
-// Add a send clause to a select statement.
-DEF_GO_RUNTIME(SELECTSEND, "runtime.selectsend", P3(POINTER, CHAN, POINTER),
- R0())
-
-// Add a receive clause to a select statement.
-DEF_GO_RUNTIME(SELECTRECV, "runtime.selectrecv",
- P4(POINTER, CHAN, POINTER, BOOLPTR), R0())
-
-// Run a select, returning the index of the selected clause.
-DEF_GO_RUNTIME(SELECTGO, "runtime.selectgo", P1(POINTER), R1(INT))
+// Run a select, returning the index of the selected clause and
+// whether that channel received a value.
+DEF_GO_RUNTIME(SELECTGO, "runtime.selectgo", P3(POINTER, POINTER, INT),
+ R2(INT, BOOL))
// Panic.
@@ -314,7 +302,7 @@ DEF_GO_RUNTIME(IFACEEFACEEQ, "runtime.ifaceefaceeq", P2(IFACE, EFACE),
// Set *dst = src where dst is a pointer to a pointer and src is a pointer.
-DEF_GO_RUNTIME(WRITEBARRIERPTR, "runtime.writebarrierptr",
+DEF_GO_RUNTIME(GCWRITEBARRIER, "runtime.gcWriteBarrier",
P2(POINTER, POINTER), R0())
// Set *dst = *src for an arbitrary type.
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index c94d8cf..1df676f 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -686,7 +686,7 @@ Assignment_statement::do_traverse_assignments(Traverse_assignments* tassign)
}
// Lower an assignment to a map index expression to a runtime function
-// call.
+// call. Mark some slice assignments as not requiring a write barrier.
Statement*
Assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
@@ -750,6 +750,21 @@ Assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
return Statement::make_block_statement(b, loc);
}
+ // An assignment of the form s = s[:n] does not require a write
+ // barrier, because the pointer value will not change.
+ Array_index_expression* aie = this->rhs_->array_index_expression();
+ if (aie != NULL
+ && aie->end() != NULL
+ && Expression::is_same_variable(this->lhs_, aie->array()))
+ {
+ Numeric_constant nc;
+ unsigned long ival;
+ if (aie->start()->numeric_constant_value(&nc)
+ && nc.to_unsigned_long(&ival) == Numeric_constant::NC_UL_VALID
+ && ival == 0)
+ this->omit_write_barrier_ = true;
+ }
+
return this;
}
@@ -876,7 +891,7 @@ Assignment_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
// Make an assignment statement.
-Statement*
+Assignment_statement*
Statement::make_assignment(Expression* lhs, Expression* rhs,
Location location)
{
@@ -4533,17 +4548,19 @@ Select_clauses::Select_clause::traverse(Traverse* traverse)
void
Select_clauses::Select_clause::lower(Gogo* gogo, Named_object* function,
- Block* b, Temporary_statement* sel)
+ Block* b, Temporary_statement* scases,
+ size_t index, Temporary_statement* recvok)
{
Location loc = this->location_;
- Expression* selref = Expression::make_temporary_reference(sel, loc);
- selref = Expression::make_unary(OPERATOR_AND, selref, loc);
+ Expression* scase = Expression::make_temporary_reference(scases, loc);
+ Expression* index_expr = Expression::make_integer_ul(index, NULL, loc);
+ scase = Expression::make_array_index(scase, index_expr, NULL, NULL, loc);
if (this->is_default_)
{
go_assert(this->channel_ == NULL && this->val_ == NULL);
- this->lower_default(b, selref);
+ this->lower_default(b, scase);
this->is_lowered_ = true;
return;
}
@@ -4557,9 +4574,9 @@ Select_clauses::Select_clause::lower(Gogo* gogo, Named_object* function,
loc);
if (this->is_send_)
- this->lower_send(b, selref, chanref);
+ this->lower_send(b, scase, chanref);
else
- this->lower_recv(gogo, function, b, selref, chanref);
+ this->lower_recv(gogo, function, b, scase, chanref, recvok);
// Now all references should be handled through the statements, not
// through here.
@@ -4570,18 +4587,16 @@ Select_clauses::Select_clause::lower(Gogo* gogo, Named_object* function,
// Lower a default clause in a select statement.
void
-Select_clauses::Select_clause::lower_default(Block* b, Expression* selref)
+Select_clauses::Select_clause::lower_default(Block* b, Expression* scase)
{
Location loc = this->location_;
- Expression* call = Runtime::make_call(Runtime::SELECTDEFAULT, loc, 1,
- selref);
- b->add_statement(Statement::make_statement(call, true));
+ this->set_case(b, scase, Expression::make_nil(loc), NULL, caseDefault);
}
// Lower a send clause in a select statement.
void
-Select_clauses::Select_clause::lower_send(Block* b, Expression* selref,
+Select_clauses::Select_clause::lower_send(Block* b, Expression* scase,
Expression* chanref)
{
Location loc = this->location_;
@@ -4596,22 +4611,29 @@ Select_clauses::Select_clause::lower_send(Block* b, Expression* selref,
// evaluate the send values in the required order.
Temporary_statement* val = Statement::make_temporary(valtype, this->val_,
loc);
+ // The value here escapes, because it might be sent on a channel.
+ // We record that via the Temporary_statement, so that the escape
+ // analysis pass can pick it up. The gc compiler lowers select
+ // statements after escape analysis, so it doesn't have to worry
+ // about this.
+ val->set_value_escapes();
b->add_statement(val);
Expression* valref = Expression::make_temporary_reference(val, loc);
Expression* valaddr = Expression::make_unary(OPERATOR_AND, valref, loc);
+ Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
+ valaddr = Expression::make_cast(unsafe_pointer_type, valaddr, loc);
- Expression* call = Runtime::make_call(Runtime::SELECTSEND, loc, 3, selref,
- chanref, valaddr);
- b->add_statement(Statement::make_statement(call, true));
+ this->set_case(b, scase, chanref, valaddr, caseSend);
}
// Lower a receive clause in a select statement.
void
Select_clauses::Select_clause::lower_recv(Gogo* gogo, Named_object* function,
- Block* b, Expression* selref,
- Expression* chanref)
+ Block* b, Expression* scase,
+ Expression* chanref,
+ Temporary_statement* recvok)
{
Location loc = this->location_;
@@ -4625,26 +4647,10 @@ Select_clauses::Select_clause::lower_recv(Gogo* gogo, Named_object* function,
Expression* valref = Expression::make_temporary_reference(val, loc);
Expression* valaddr = Expression::make_unary(OPERATOR_AND, valref, loc);
+ Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
+ valaddr = Expression::make_cast(unsafe_pointer_type, valaddr, loc);
- Temporary_statement* closed_temp = NULL;
-
- Expression* caddr;
- if (this->closed_ == NULL && this->closedvar_ == NULL)
- caddr = Expression::make_nil(loc);
- else
- {
- closed_temp = Statement::make_temporary(Type::lookup_bool_type(), NULL,
- loc);
- b->add_statement(closed_temp);
- Expression* cref = Expression::make_temporary_reference(closed_temp,
- loc);
- caddr = Expression::make_unary(OPERATOR_AND, cref, loc);
- }
-
- Expression* call = Runtime::make_call(Runtime::SELECTRECV, loc, 4, selref,
- chanref, valaddr, caddr);
-
- b->add_statement(Statement::make_statement(call, true));
+ this->set_case(b, scase, chanref, valaddr, caseRecv);
// If the block of statements is executed, arrange for the received
// value to move from VAL to the place where the statements expect
@@ -4669,16 +4675,14 @@ Select_clauses::Select_clause::lower_recv(Gogo* gogo, Named_object* function,
if (this->closedvar_ != NULL)
{
go_assert(this->closed_ == NULL);
- Expression* cref = Expression::make_temporary_reference(closed_temp,
- loc);
+ Expression* cref = Expression::make_temporary_reference(recvok, loc);
this->closedvar_->var_value()->set_init(cref);
}
else if (this->closed_ != NULL && !this->closed_->is_sink_expression())
{
if (init == NULL)
init = new Block(b, loc);
- Expression* cref = Expression::make_temporary_reference(closed_temp,
- loc);
+ Expression* cref = Expression::make_temporary_reference(recvok, loc);
init->add_statement(Statement::make_assignment(this->closed_, cref,
loc));
}
@@ -4694,6 +4698,45 @@ Select_clauses::Select_clause::lower_recv(Gogo* gogo, Named_object* function,
}
}
+// Set the fields of an scase struct, an element in the array that we
+// pass to the runtime function selectgo.
+
+void
+Select_clauses::Select_clause::set_case(Block* b,
+ Expression* scase,
+ Expression* chanref,
+ Expression* elem,
+ int kind)
+{
+ Location loc = this->location_;
+ Struct_type* scase_type = scase->type()->struct_type();
+
+ int field_index = 0;
+ go_assert(scase_type->field(field_index)->is_field_name("c"));
+ Expression* ref = Expression::make_field_reference(scase, field_index, loc);
+ Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
+ chanref = Expression::make_unsafe_cast(unsafe_pointer_type, chanref, loc);
+ Statement* s = Statement::make_assignment(ref, chanref, loc);
+ b->add_statement(s);
+
+ if (elem != NULL)
+ {
+ field_index = 1;
+ go_assert(scase_type->field(field_index)->is_field_name("elem"));
+ ref = Expression::make_field_reference(scase->copy(), field_index, loc);
+ s = Statement::make_assignment(ref, elem, loc);
+ b->add_statement(s);
+ }
+
+ field_index = 2;
+ go_assert(scase_type->field(field_index)->is_field_name("kind"));
+ Type* uint16_type = Type::lookup_integer_type("uint16");
+ Expression* k = Expression::make_integer_ul(kind, uint16_type, loc);
+ ref = Expression::make_field_reference(scase->copy(), field_index, loc);
+ s = Statement::make_assignment(ref, k, loc);
+ b->add_statement(s);
+}
+
// Determine types.
void
@@ -4813,12 +4856,13 @@ Select_clauses::traverse(Traverse* traverse)
void
Select_clauses::lower(Gogo* gogo, Named_object* function, Block* b,
- Temporary_statement* sel)
+ Temporary_statement* scases, Temporary_statement* recvok)
{
+ size_t i = 0;
for (Clauses::iterator p = this->clauses_.begin();
p != this->clauses_.end();
- ++p)
- p->lower(gogo, function, b, sel);
+ ++p, ++i)
+ p->lower(gogo, function, b, scases, i, recvok);
}
// Determine types.
@@ -4857,13 +4901,13 @@ Select_clauses::may_fall_through() const
return false;
}
-// Convert to the backend representation. We have already accumulated
-// all the select information. Now we call selectgo, which will
-// return the index of the clause to execute.
+// Convert to the backend representation. Assemble the clauses and
+// build a switch statement on the index value returned by the call to
+// selectgo.
Bstatement*
Select_clauses::get_backend(Translate_context* context,
- Temporary_statement* sel,
+ Temporary_statement* index,
Unnamed_label *break_label,
Location location)
{
@@ -4894,21 +4938,14 @@ Select_clauses::get_backend(Translate_context* context,
clauses[i] = context->backend()->compound_statement(s, g);
}
- Expression* selref = Expression::make_temporary_reference(sel, location);
- selref = Expression::make_unary(OPERATOR_AND, selref, location);
- Expression* call = Runtime::make_call(Runtime::SELECTGO, location, 1,
- selref);
- context->gogo()->lower_expression(context->function(), NULL, &call);
- Bexpression* bcall = call->get_backend(context);
-
- if (count == 0)
- {
- Bfunction* bfunction = context->function()->func_value()->get_decl();
- return context->backend()->expression_statement(bfunction, bcall);
- }
+ Expression* ref = Expression::make_temporary_reference(index, location);
+ Bexpression* bindex = ref->get_backend(context);
Bfunction* bfunction = context->function()->func_value()->get_decl();
+ if (count == 0)
+ return context->backend()->expression_statement(bfunction, bindex);
+
Expression* crash = Runtime::make_call(Runtime::UNREACHABLE, location, 0);
Bexpression* bcrash = crash->get_backend(context);
clauses[count] = context->backend()->expression_statement(bfunction, bcrash);
@@ -4917,7 +4954,7 @@ Select_clauses::get_backend(Translate_context* context,
statements.reserve(2);
Bstatement* switch_stmt = context->backend()->switch_statement(bfunction,
- bcall,
+ bindex,
cases,
clauses,
location);
@@ -4928,6 +4965,7 @@ Select_clauses::get_backend(Translate_context* context,
return context->backend()->statement_list(statements);
}
+
// Dump the AST representation for select clauses.
void
@@ -4952,10 +4990,10 @@ Select_statement::break_label()
return this->break_label_;
}
-// Lower a select statement. This will still return a select
-// statement, but it will be modified to implement the order of
-// evaluation rules, and to include the send and receive statements as
-// explicit statements in the clauses.
+// Lower a select statement. This will return a block containing this
+// select statement. The block will implement the order of evaluation
+// rules, include the send and receive statements as explicit
+// statements in the clauses, and call the runtime selectgo function.
Statement*
Select_statement::do_lower(Gogo* gogo, Named_object* function,
@@ -4968,30 +5006,69 @@ Select_statement::do_lower(Gogo* gogo, Named_object* function,
Block* b = new Block(enclosing, loc);
- go_assert(this->sel_ == NULL);
-
int ncases = this->clauses_->size();
- Type* selstruct_type = Channel_type::select_type(ncases);
- this->sel_ = Statement::make_temporary(selstruct_type, NULL, loc);
- b->add_statement(this->sel_);
+ Type* scase_type = Channel_type::select_case_type();
+ Expression* ncases_expr =
+ Expression::make_integer_ul(ncases, NULL,
+ Linemap::predeclared_location());
+ Array_type* scases_type = Type::make_array_type(scase_type, ncases_expr);
+ scases_type->set_is_array_incomparable();
+
+ Temporary_statement* scases = Statement::make_temporary(scases_type, NULL,
+ loc);
+ b->add_statement(scases);
- int64_t selstruct_size;
- if (!selstruct_type->backend_type_size(gogo, &selstruct_size))
- {
- go_assert(saw_errors());
- return Statement::make_error_statement(loc);
- }
+ Expression* ncases2_expr =
+ Expression::make_integer_ul(ncases * 2, NULL,
+ Linemap::predeclared_location());
+ Type* uint16_type = Type::lookup_integer_type("uint16");
+ Array_type* order_type = Type::make_array_type(uint16_type, ncases2_expr);
+ order_type->set_is_array_incomparable();
- Expression* ref = Expression::make_temporary_reference(this->sel_, loc);
- ref = Expression::make_unary(OPERATOR_AND, ref, loc);
- Expression* selstruct_size_expr =
- Expression::make_integer_int64(selstruct_size, NULL, loc);
- Expression* size_expr = Expression::make_integer_ul(ncases, NULL, loc);
- Expression* call = Runtime::make_call(Runtime::NEWSELECT, loc, 3,
- ref, selstruct_size_expr, size_expr);
- b->add_statement(Statement::make_statement(call, true));
+ Temporary_statement* order = Statement::make_temporary(order_type, NULL,
+ loc);
+ b->add_statement(order);
+
+ Type* int_type = Type::lookup_integer_type("int");
+ this->index_ = Statement::make_temporary(int_type, NULL, loc);
+ b->add_statement(this->index_);
+
+ Type* bool_type = Type::lookup_bool_type();
+ Temporary_statement* recvok = Statement::make_temporary(bool_type, NULL,
+ loc);
+ b->add_statement(recvok);
+
+ // Initialize the scases array.
+ this->clauses_->lower(gogo, function, b, scases, recvok);
+
+ // Build the call to selectgo. Later, in do_get_backend, we will
+ // build a switch on the result that branches to the various cases.
+
+ Expression* scases_ref = Expression::make_temporary_reference(scases, loc);
+ scases_ref = Expression::make_unary(OPERATOR_AND, scases_ref, loc);
+ Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
+ scases_ref = Expression::make_cast(unsafe_pointer_type, scases_ref, loc);
+
+ Expression* order_ref = Expression::make_temporary_reference(order, loc);
+ order_ref = Expression::make_unary(OPERATOR_AND, order_ref, loc);
+ order_ref = Expression::make_cast(unsafe_pointer_type, order_ref, loc);
+
+ Expression* count_expr = Expression::make_integer_ul(ncases, int_type, loc);
+
+ Call_expression* call = Runtime::make_call(Runtime::SELECTGO, loc, 3,
+ scases_ref, order_ref,
+ count_expr);
+
+ Expression* result = Expression::make_call_result(call, 0);
+ Expression* ref = Expression::make_temporary_reference(this->index_, loc);
+ Statement* s = Statement::make_assignment(ref, result, loc);
+ b->add_statement(s);
+
+ result = Expression::make_call_result(call, 1);
+ ref = Expression::make_temporary_reference(recvok, loc);
+ s = Statement::make_assignment(ref, result, loc);
+ b->add_statement(s);
- this->clauses_->lower(gogo, function, b, this->sel_);
this->is_lowered_ = true;
b->add_statement(this);
@@ -5016,8 +5093,8 @@ Select_statement::do_may_fall_through() const
Bstatement*
Select_statement::do_get_backend(Translate_context* context)
{
- return this->clauses_->get_backend(context, this->sel_, this->break_label(),
- this->location());
+ return this->clauses_->get_backend(context, this->index_,
+ this->break_label(), this->location());
}
// Dump the AST representation for a select statement.
diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h
index 852ab43..81b26b3 100644
--- a/gcc/go/gofrontend/statements.h
+++ b/gcc/go/gofrontend/statements.h
@@ -148,7 +148,7 @@ class Statement
make_temporary(Type*, Expression*, Location);
// Make an assignment statement.
- static Statement*
+ static Assignment_statement*
make_assignment(Expression*, Expression*, Location);
// Make an assignment operation (+=, etc.).
@@ -562,7 +562,7 @@ class Assignment_statement : public Statement
Assignment_statement(Expression* lhs, Expression* rhs,
Location location)
: Statement(STATEMENT_ASSIGNMENT, location),
- lhs_(lhs), rhs_(rhs)
+ lhs_(lhs), rhs_(rhs), omit_write_barrier_(false)
{ }
Expression*
@@ -573,6 +573,14 @@ class Assignment_statement : public Statement
rhs() const
{ return this->rhs_; }
+ bool
+ omit_write_barrier() const
+ { return this->omit_write_barrier_; }
+
+ void
+ set_omit_write_barrier()
+ { this->omit_write_barrier_ = true; }
+
protected:
int
do_traverse(Traverse* traverse);
@@ -603,6 +611,8 @@ class Assignment_statement : public Statement
Expression* lhs_;
// Right hand side--the rvalue.
Expression* rhs_;
+ // True if we can omit a write barrier from this assignment.
+ bool omit_write_barrier_;
};
// A statement which creates and initializes a temporary variable.
@@ -612,7 +622,8 @@ class Temporary_statement : public Statement
public:
Temporary_statement(Type* type, Expression* init, Location location)
: Statement(STATEMENT_TEMPORARY, location),
- type_(type), init_(init), bvariable_(NULL), is_address_taken_(false)
+ type_(type), init_(init), bvariable_(NULL), is_address_taken_(false),
+ value_escapes_(false)
{ }
// Return the type of the temporary variable.
@@ -630,6 +641,16 @@ class Temporary_statement : public Statement
set_is_address_taken()
{ this->is_address_taken_ = true; }
+ // Whether the value escapes.
+ bool
+ value_escapes() const
+ { return this->value_escapes_; }
+
+ // Record that the value escapes.
+ void
+ set_value_escapes()
+ { this->value_escapes_ = true; }
+
// Return the temporary variable. This should not be called until
// after the statement itself has been converted.
Bvariable*
@@ -666,6 +687,9 @@ class Temporary_statement : public Statement
Bvariable* bvariable_;
// True if something takes the address of this temporary variable.
bool is_address_taken_;
+ // True if the value assigned to this temporary variable escapes.
+ // This is used for select statements.
+ bool value_escapes_;
};
// A variable declaration. This marks the point in the code where a
@@ -841,7 +865,7 @@ class Send_statement : public Statement
Expression*
channel()
- { return this->channel_; }
+ { return this->channel_; }
Expression*
val()
@@ -914,7 +938,8 @@ class Select_clauses
// Lower statements.
void
- lower(Gogo*, Named_object*, Block*, Temporary_statement*);
+ lower(Gogo*, Named_object*, Block*, Temporary_statement*,
+ Temporary_statement*);
// Determine types.
void
@@ -931,7 +956,7 @@ class Select_clauses
// Convert to the backend representation.
Bstatement*
- get_backend(Translate_context*, Temporary_statement* sel,
+ get_backend(Translate_context*, Temporary_statement* index,
Unnamed_label* break_label, Location);
// Dump AST representation.
@@ -964,7 +989,8 @@ class Select_clauses
// Lower statements.
void
- lower(Gogo*, Named_object*, Block*, Temporary_statement*);
+ lower(Gogo*, Named_object*, Block*, Temporary_statement*, size_t,
+ Temporary_statement*);
// Determine types.
void
@@ -1017,6 +1043,14 @@ class Select_clauses
dump_clause(Ast_dump_context*) const;
private:
+ // These values must match the values in libgo/go/runtime/select.go.
+ enum
+ {
+ caseRecv = 1,
+ caseSend = 2,
+ caseDefault = 3,
+ };
+
void
lower_default(Block*, Expression*);
@@ -1024,7 +1058,11 @@ class Select_clauses
lower_send(Block*, Expression*, Expression*);
void
- lower_recv(Gogo*, Named_object*, Block*, Expression*, Expression*);
+ lower_recv(Gogo*, Named_object*, Block*, Expression*, Expression*,
+ Temporary_statement*);
+
+ void
+ set_case(Block*, Expression*, Expression*, Expression*, int);
// The channel.
Expression* channel_;
@@ -1062,7 +1100,7 @@ class Select_statement : public Statement
public:
Select_statement(Location location)
: Statement(STATEMENT_SELECT, location),
- clauses_(NULL), sel_(NULL), break_label_(NULL), is_lowered_(false)
+ clauses_(NULL), index_(NULL), break_label_(NULL), is_lowered_(false)
{ }
// Add the clauses.
@@ -1105,8 +1143,8 @@ class Select_statement : public Statement
private:
// The select clauses.
Select_clauses* clauses_;
- // A temporary which holds the select structure we build up at runtime.
- Temporary_statement* sel_;
+ // A temporary that holds the index value returned by selectgo.
+ Temporary_statement* index_;
// The break label.
Unnamed_label* break_label_;
// Whether this statement has been lowered.
@@ -1599,7 +1637,7 @@ class Case_clauses
// Dump the AST representation to a dump context.
void
dump_clauses(Ast_dump_context*) const;
-
+
private:
// For a constant switch we need to keep a record of constants we
// have already seen.
@@ -1673,7 +1711,7 @@ class Case_clauses
// Dump the AST representation to a dump context.
void
dump_clause(Ast_dump_context*) const;
-
+
private:
// The list of case expressions.
Expression_list* cases_;
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index 2fb6706..cc07bfc 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -7975,12 +7975,11 @@ Map_type::make_map_type_descriptor_type()
Type* bool_type = Type::lookup_bool_type();
Struct_type* sf =
- Type::make_builtin_struct_type(12,
+ Type::make_builtin_struct_type(11,
"", tdt,
"key", ptdt,
"elem", ptdt,
"bucket", ptdt,
- "hmap", ptdt,
"keysize", uint8_type,
"indirectkey", bool_type,
"valuesize", uint8_type,
@@ -8065,11 +8064,6 @@ Map_type::do_type_descriptor(Gogo* gogo, Named_type* name)
vals->push_back(Expression::make_type_descriptor(bucket_type, bloc));
++p;
- go_assert(p->is_field_name("hmap"));
- Type* hmap_type = this->hmap_type(bucket_type);
- vals->push_back(Expression::make_type_descriptor(hmap_type, bloc));
-
- ++p;
go_assert(p->is_field_name("keysize"));
if (keysize > Map_type::max_key_size)
vals->push_back(Expression::make_integer_int64(ptrsize, uint8_type, bloc));
@@ -8563,51 +8557,29 @@ Channel_type::do_import(Import* imp)
return Type::make_channel_type(may_send, may_receive, element_type);
}
-// Return the type to manage a select statement with ncases case
-// statements. A value of this type is allocated on the stack. This
-// must match the type hselect in libgo/go/runtime/select.go.
+// Return the type that the runtime package uses for one case of a
+// select statement. An array of values of this type is allocated on
+// the stack. This must match scase in libgo/go/runtime/select.go.
Type*
-Channel_type::select_type(int ncases)
+Channel_type::select_case_type()
{
- Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
- Type* uint16_type = Type::lookup_integer_type("uint16");
-
static Struct_type* scase_type;
if (scase_type == NULL)
{
- Type* uintptr_type = Type::lookup_integer_type("uintptr");
- Type* uint64_type = Type::lookup_integer_type("uint64");
+ Type* unsafe_pointer_type =
+ Type::make_pointer_type(Type::make_void_type());
+ Type* uint16_type = Type::lookup_integer_type("uint16");
+ Type* int64_type = Type::lookup_integer_type("int64");
scase_type =
- Type::make_builtin_struct_type(7,
+ Type::make_builtin_struct_type(4,
+ "c", unsafe_pointer_type,
"elem", unsafe_pointer_type,
- "chan", unsafe_pointer_type,
- "pc", uintptr_type,
"kind", uint16_type,
- "index", uint16_type,
- "receivedp", unsafe_pointer_type,
- "releasetime", uint64_type);
+ "releasetime", int64_type);
scase_type->set_is_struct_incomparable();
}
-
- Expression* ncases_expr =
- Expression::make_integer_ul(ncases, NULL, Linemap::predeclared_location());
- Array_type* scases = Type::make_array_type(scase_type, ncases_expr);
- scases->set_is_array_incomparable();
- Array_type* order = Type::make_array_type(uint16_type, ncases_expr);
- order->set_is_array_incomparable();
-
- Struct_type* ret =
- Type::make_builtin_struct_type(7,
- "tcase", uint16_type,
- "ncase", uint16_type,
- "pollorder", unsafe_pointer_type,
- "lockorder", unsafe_pointer_type,
- "scase", scases,
- "lockorderarr", order,
- "pollorderarr", order);
- ret->set_is_struct_incomparable();
- return ret;
+ return scase_type;
}
// Make a new channel type.
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index 0f85c3a..e011236 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -2981,7 +2981,7 @@ class Channel_type : public Type
make_chan_type_descriptor_type();
static Type*
- select_type(int ncases);
+ select_case_type();
protected:
int
diff --git a/gcc/go/gofrontend/wb.cc b/gcc/go/gofrontend/wb.cc
index 99f467e..4f84d99 100644
--- a/gcc/go/gofrontend/wb.cc
+++ b/gcc/go/gofrontend/wb.cc
@@ -16,26 +16,87 @@
#include "runtime.h"
#include "gogo.h"
-// Mark variables whose addresses are taken. This has to be done
-// before the write barrier pass and after the escape analysis pass.
-// It would be nice to do this elsewhere but there isn't an obvious
-// place.
+// Mark variables whose addresses are taken and do some other
+// cleanups. This has to be done before the write barrier pass and
+// after the escape analysis pass. It would be nice to do this
+// elsewhere but there isn't an obvious place.
class Mark_address_taken : public Traverse
{
public:
Mark_address_taken(Gogo* gogo)
- : Traverse(traverse_expressions),
- gogo_(gogo)
+ : Traverse(traverse_functions
+ | traverse_statements
+ | traverse_expressions),
+ gogo_(gogo), function_(NULL)
{ }
int
+ function(Named_object*);
+
+ int
+ statement(Block*, size_t*, Statement*);
+
+ int
expression(Expression**);
private:
+ // General IR.
Gogo* gogo_;
+ // The function we are traversing.
+ Named_object* function_;
};
+// Record a function.
+
+int
+Mark_address_taken::function(Named_object* no)
+{
+ go_assert(this->function_ == NULL);
+ this->function_ = no;
+ int t = no->func_value()->traverse(this);
+ this->function_ = NULL;
+
+ if (t == TRAVERSE_EXIT)
+ return t;
+ return TRAVERSE_SKIP_COMPONENTS;
+}
+
+// Traverse a statement.
+
+int
+Mark_address_taken::statement(Block* block, size_t* pindex, Statement* s)
+{
+ // If this is an assignment of the form s = append(s, ...), expand
+ // it now, so that we can assign it to the left hand side in the
+ // middle of the expansion and possibly skip a write barrier.
+ Assignment_statement* as = s->assignment_statement();
+ if (as != NULL && !as->lhs()->is_sink_expression())
+ {
+ Call_expression* rce = as->rhs()->call_expression();
+ if (rce != NULL
+ && rce->builtin_call_expression() != NULL
+ && (rce->builtin_call_expression()->code()
+ == Builtin_call_expression::BUILTIN_APPEND)
+ && Expression::is_same_variable(as->lhs(), rce->args()->front()))
+ {
+ Statement_inserter inserter = Statement_inserter(block, pindex);
+ Expression* a =
+ rce->builtin_call_expression()->flatten_append(this->gogo_,
+ this->function_,
+ &inserter,
+ as->lhs(),
+ block);
+ go_assert(a == NULL);
+ // That does the assignment, so remove this statement.
+ Expression* e = Expression::make_boolean(true, s->location());
+ Statement* dummy = Statement::make_statement(e, true);
+ block->replace_statement(*pindex, dummy);
+ }
+ }
+ return TRAVERSE_CONTINUE;
+}
+
// Mark variable addresses taken.
int
@@ -170,6 +231,133 @@ Check_escape::expression(Expression** pexpr)
return TRAVERSE_CONTINUE;
}
+// Collect all writebarrierrec functions. This is used when compiling
+// the runtime package, to propagate //go:nowritebarrierrec.
+
+class Collect_writebarrierrec_functions : public Traverse
+{
+ public:
+ Collect_writebarrierrec_functions(std::vector<Named_object*>* worklist)
+ : Traverse(traverse_functions),
+ worklist_(worklist)
+ { }
+
+ private:
+ int
+ function(Named_object*);
+
+ // The collected functions are put here.
+ std::vector<Named_object*>* worklist_;
+};
+
+int
+Collect_writebarrierrec_functions::function(Named_object* no)
+{
+ if (no->is_function()
+ && no->func_value()->enclosing() == NULL
+ && (no->func_value()->pragmas() & GOPRAGMA_NOWRITEBARRIERREC) != 0)
+ {
+ go_assert((no->func_value()->pragmas() & GOPRAGMA_MARK) == 0);
+ this->worklist_->push_back(no);
+ }
+ return TRAVERSE_CONTINUE;
+}
+
+// Collect all callees of this function. We only care about locally
+// defined, known, functions.
+
+class Collect_callees : public Traverse
+{
+ public:
+ Collect_callees(std::vector<Named_object*>* worklist)
+ : Traverse(traverse_expressions),
+ worklist_(worklist)
+ { }
+
+ private:
+ int
+ expression(Expression**);
+
+ // The collected callees are put here.
+ std::vector<Named_object*>* worklist_;
+};
+
+int
+Collect_callees::expression(Expression** pexpr)
+{
+ Call_expression* ce = (*pexpr)->call_expression();
+ if (ce != NULL)
+ {
+ Func_expression* fe = ce->fn()->func_expression();
+ if (fe != NULL)
+ {
+ Named_object* no = fe->named_object();
+ if (no->package() == NULL && no->is_function())
+ {
+ // The function runtime.systemstack is special, in that
+ // it is a common way to call a function in the runtime:
+ // mark its argument if we can.
+ if (Gogo::unpack_hidden_name(no->name()) != "systemstack")
+ this->worklist_->push_back(no);
+ else if (ce->args()->size() > 0)
+ {
+ fe = ce->args()->front()->func_expression();
+ if (fe != NULL)
+ {
+ no = fe->named_object();
+ if (no->package() == NULL && no->is_function())
+ this->worklist_->push_back(no);
+ }
+ }
+ }
+ }
+ }
+ return TRAVERSE_CONTINUE;
+}
+
+// When compiling the runtime package, propagate //go:nowritebarrierrec
+// annotations. A function marked as //go:nowritebarrierrec does not
+// permit write barriers, and also all the functions that it calls,
+// recursively, do not permit write barriers. Except that a
+// //go:yeswritebarrierrec annotation permits write barriers even if
+// called by a //go:nowritebarrierrec function. Here we turn
+// //go:nowritebarrierrec into //go:nowritebarrier, as appropriate.
+
+void
+Gogo::propagate_writebarrierrec()
+{
+ std::vector<Named_object*> worklist;
+ Collect_writebarrierrec_functions cwf(&worklist);
+ this->traverse(&cwf);
+
+ Collect_callees cc(&worklist);
+
+ while (!worklist.empty())
+ {
+ Named_object* no = worklist.back();
+ worklist.pop_back();
+
+ unsigned int pragmas = no->func_value()->pragmas();
+ if ((pragmas & GOPRAGMA_MARK) != 0)
+ {
+ // We've already seen this function.
+ continue;
+ }
+ if ((pragmas & GOPRAGMA_YESWRITEBARRIERREC) != 0)
+ {
+ // We don't want to propagate //go:nowritebarrierrec into
+ // this function or it's callees.
+ continue;
+ }
+
+ no->func_value()->set_pragmas(pragmas
+ | GOPRAGMA_NOWRITEBARRIER
+ | GOPRAGMA_MARK);
+
+ no->func_value()->traverse(&cc);
+ }
+}
+
// Add write barriers to the IR. This are required by the concurrent
// garbage collector. A write barrier is needed for any write of a
// pointer into memory controlled by the garbage collector. Write
@@ -192,7 +380,7 @@ Check_escape::expression(Expression** pexpr)
// This is compatible with the definition in the runtime package.
//
// For types that are pointer shared (pointers, maps, chans, funcs),
-// we replaced the call to typedmemmove with writebarrierptr(&A, B).
+// we replaced the call to typedmemmove with gcWriteBarrier(&A, B).
// As far as the GC is concerned, all pointers are the same, so it
// doesn't need the type descriptor.
//
@@ -203,7 +391,7 @@ Check_escape::expression(Expression** pexpr)
// runtime package, so we could optimize by only testing it once
// between function calls.
//
-// A slice could be handled with a call to writebarrierptr plus two
+// A slice could be handled with a call to gcWriteBarrier plus two
// integer moves.
// Traverse the IR adding write barriers.
@@ -387,6 +575,10 @@ Write_barriers::statement(Block* block, size_t* pindex, Statement* s)
case Statement::STATEMENT_ASSIGNMENT:
{
Assignment_statement* as = s->assignment_statement();
+
+ if (as->omit_write_barrier())
+ break;
+
Expression* lhs = as->lhs();
Expression* rhs = as->rhs();
@@ -427,6 +619,8 @@ Gogo::add_write_barriers()
if (this->compiling_runtime() && this->package_name() == "runtime")
{
+ this->propagate_writebarrierrec();
+
Check_escape chk(this);
this->traverse(&chk);
}
@@ -471,8 +665,8 @@ Gogo::assign_needs_write_barrier(Expression* lhs)
if (!lhs->type()->has_pointer())
return false;
- // An assignment to a field is handled like an assignment to the
- // struct.
+ // An assignment to a field or an array index is handled like an
+ // assignment to the struct.
while (true)
{
// Nothing to do for a type that can not be in the heap, or a
@@ -485,9 +679,22 @@ Gogo::assign_needs_write_barrier(Expression* lhs)
return false;
Field_reference_expression* fre = lhs->field_reference_expression();
- if (fre == NULL)
- break;
- lhs = fre->expr();
+ if (fre != NULL)
+ {
+ lhs = fre->expr();
+ continue;
+ }
+
+ Array_index_expression* aie = lhs->array_index_expression();
+ if (aie != NULL
+ && aie->end() == NULL
+ && !aie->array()->type()->is_slice_type())
+ {
+ lhs = aie->array();
+ continue;
+ }
+
+ break;
}
// Nothing to do for an assignment to a temporary.
@@ -555,9 +762,7 @@ Gogo::assign_with_write_barrier(Function* function, Block* enclosing,
Statement_inserter* inserter, Expression* lhs,
Expression* rhs, Location loc)
{
- if (function != NULL
- && ((function->pragmas() & GOPRAGMA_NOWRITEBARRIER) != 0
- || (function->pragmas() & GOPRAGMA_NOWRITEBARRIERREC) != 0))
+ if (function != NULL && (function->pragmas() & GOPRAGMA_NOWRITEBARRIER) != 0)
go_error_at(loc, "write barrier prohibited");
Type* type = lhs->type();
@@ -619,7 +824,7 @@ Gogo::assign_with_write_barrier(Function* function, Block* enclosing,
case Type::TYPE_MAP:
case Type::TYPE_CHANNEL:
// These types are all represented by a single pointer.
- call = Runtime::make_call(Runtime::WRITEBARRIERPTR, loc, 2, lhs, rhs);
+ call = Runtime::make_call(Runtime::GCWRITEBARRIER, loc, 2, lhs, rhs);
break;
case Type::TYPE_STRING:
diff --git a/gcc/go/gospec.c b/gcc/go/gospec.c
index 7a10997..d265fc9 100644
--- a/gcc/go/gospec.c
+++ b/gcc/go/gospec.c
@@ -139,6 +139,7 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
switch (decoded_options[i].opt_index)
{
+ case OPT_r:
case OPT_nostdlib:
case OPT_nodefaultlibs:
library = -1;
diff --git a/gcc/graphite.h b/gcc/graphite.h
index 4e0e58c..be0a22b 100644
--- a/gcc/graphite.h
+++ b/gcc/graphite.h
@@ -37,6 +37,8 @@ along with GCC; see the file COPYING3. If not see
#include <isl/schedule.h>
#include <isl/ast_build.h>
#include <isl/schedule_node.h>
+#include <isl/id.h>
+#include <isl/space.h>
typedef struct poly_dr *poly_dr_p;
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index 4a899b5..1fdc9df 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -529,6 +529,9 @@ haifa_classify_rtx (const_rtx x)
/* Test if it is a 'store'. */
tmp_class = may_trap_exp (XEXP (x, 0), 1);
break;
+ case CLOBBER_HIGH:
+ gcc_assert (REG_P (XEXP (x, 0)));
+ break;
case SET:
/* Test if it is a store. */
tmp_class = may_trap_exp (SET_DEST (x), 1);
@@ -2539,7 +2542,7 @@ enum rfs_decision {
RFS_SCHED_GROUP, RFS_PRESSURE_DELAY, RFS_PRESSURE_TICK,
RFS_FEEDS_BACKTRACK_INSN, RFS_PRIORITY, RFS_SPECULATION,
RFS_SCHED_RANK, RFS_LAST_INSN, RFS_PRESSURE_INDEX,
- RFS_DEP_COUNT, RFS_TIE, RFS_FUSION, RFS_N };
+ RFS_DEP_COUNT, RFS_TIE, RFS_FUSION, RFS_COST, RFS_N };
/* Corresponding strings for print outs. */
static const char *rfs_str[RFS_N] = {
@@ -2547,7 +2550,7 @@ static const char *rfs_str[RFS_N] = {
"RFS_SCHED_GROUP", "RFS_PRESSURE_DELAY", "RFS_PRESSURE_TICK",
"RFS_FEEDS_BACKTRACK_INSN", "RFS_PRIORITY", "RFS_SPECULATION",
"RFS_SCHED_RANK", "RFS_LAST_INSN", "RFS_PRESSURE_INDEX",
- "RFS_DEP_COUNT", "RFS_TIE", "RFS_FUSION" };
+ "RFS_DEP_COUNT", "RFS_TIE", "RFS_FUSION", "RFS_COST" };
/* Statistical breakdown of rank_for_schedule decisions. */
struct rank_for_schedule_stats_t { unsigned stats[RFS_N]; };
@@ -2800,6 +2803,14 @@ rank_for_schedule (const void *x, const void *y)
if (flag_sched_dep_count_heuristic && val != 0)
return rfs_result (RFS_DEP_COUNT, val, tmp, tmp2);
+ /* Sort by INSN_COST rather than INSN_LUID. This means that instructions
+ which take longer to execute are prioritised and it leads to more
+ dual-issue opportunities on in-order cores which have this feature. */
+
+ if (INSN_COST (tmp) != INSN_COST (tmp2))
+ return rfs_result (RFS_COST, INSN_COST (tmp2) - INSN_COST (tmp),
+ tmp, tmp2);
+
/* If insns are equally good, sort by INSN_LUID (original insn order),
so that we make the sort stable. This minimizes instruction movement,
thus minimizing sched's effect on debugging and cross-jumping. */
diff --git a/gcc/hash-table.c b/gcc/hash-table.c
index c86d84d..bff9644 100644
--- a/gcc/hash-table.c
+++ b/gcc/hash-table.c
@@ -98,7 +98,16 @@ hash_table_higher_prime_index (unsigned long n)
return low;
}
-mem_alloc_description<mem_usage> hash_table_usage;
+/* Return a reference to the lazily initialized hash-table usage description.
+ This needs to be a function rather than a simple global variable so that it
+ is reliably initialized before hash table variables in other files such as
+ sem_item::m_type_hash_cache. */
+mem_alloc_description<mem_usage>&
+hash_table_usage ()
+{
+ static mem_alloc_description<mem_usage> usage;
+ return usage;
+}
/* Support function for statistics. */
void dump_hash_table_loc_statistics (void)
@@ -109,7 +118,6 @@ void dump_hash_table_loc_statistics (void)
for (unsigned i = HASH_TABLE_ORIGIN; i <= HASH_SET_ORIGIN; i++)
{
mem_alloc_origin origin = (mem_alloc_origin) i;
- hash_table_usage.dump (origin);
+ hash_table_usage ().dump (origin);
}
}
-
diff --git a/gcc/hash-table.h b/gcc/hash-table.h
index 706b237..bd83345 100644
--- a/gcc/hash-table.h
+++ b/gcc/hash-table.h
@@ -561,7 +561,7 @@ private:
#include "mem-stats.h"
#include "hash-map.h"
-extern mem_alloc_description<mem_usage> hash_table_usage;
+extern mem_alloc_description<mem_usage>& hash_table_usage (void);
/* Support function for statistics. */
extern void dump_hash_table_loc_statistics (void);
@@ -580,7 +580,7 @@ hash_table<Descriptor, Allocator>::hash_table (size_t size, bool ggc, bool
size = prime_tab[size_prime_index].prime;
if (m_gather_mem_stats)
- hash_table_usage.register_descriptor (this, origin, ggc
+ hash_table_usage ().register_descriptor (this, origin, ggc
FINAL_PASS_MEM_STAT);
m_entries = alloc_entries (size PASS_MEM_STAT);
@@ -600,7 +600,7 @@ hash_table<Descriptor, Allocator>::hash_table (const hash_table &h, bool ggc,
size_t size = h.m_size;
if (m_gather_mem_stats)
- hash_table_usage.register_descriptor (this, origin, ggc
+ hash_table_usage ().register_descriptor (this, origin, ggc
FINAL_PASS_MEM_STAT);
value_type *nentries = alloc_entries (size PASS_MEM_STAT);
@@ -630,7 +630,7 @@ hash_table<Descriptor, Allocator>::~hash_table ()
ggc_free (m_entries);
if (m_gather_mem_stats)
- hash_table_usage.release_instance_overhead (this,
+ hash_table_usage ().release_instance_overhead (this,
sizeof (value_type) * m_size,
true);
}
@@ -644,7 +644,7 @@ hash_table<Descriptor, Allocator>::alloc_entries (size_t n MEM_STAT_DECL) const
value_type *nentries;
if (m_gather_mem_stats)
- hash_table_usage.register_instance_overhead (sizeof (value_type) * n, this);
+ hash_table_usage ().register_instance_overhead (sizeof (value_type) * n, this);
if (!m_ggc)
nentries = Allocator <value_type> ::data_alloc (n);
@@ -736,7 +736,7 @@ hash_table<Descriptor, Allocator>::expand ()
value_type *nentries = alloc_entries (nsize);
if (m_gather_mem_stats)
- hash_table_usage.release_instance_overhead (this, sizeof (value_type)
+ hash_table_usage ().release_instance_overhead (this, sizeof (value_type)
* osize);
m_entries = nentries;
diff --git a/gcc/hsa-brig.c b/gcc/hsa-brig.c
index d3efff4..ca06611 100644
--- a/gcc/hsa-brig.c
+++ b/gcc/hsa-brig.c
@@ -35,8 +35,8 @@ along with GCC; see the file COPYING3. If not see
#include "stor-layout.h"
#include "output.h"
#include "basic-block.h"
-#include "cfg.h"
#include "function.h"
+#include "cfg.h"
#include "fold-const.h"
#include "stringpool.h"
#include "gimple-pretty-print.h"
diff --git a/gcc/hsa-dump.c b/gcc/hsa-dump.c
index 1407475..96f8264 100644
--- a/gcc/hsa-dump.c
+++ b/gcc/hsa-dump.c
@@ -27,8 +27,8 @@ along with GCC; see the file COPYING3. If not see
#include "vec.h"
#include "tree.h"
#include "basic-block.h"
-#include "cfg.h"
#include "function.h"
+#include "cfg.h"
#include "dumpfile.h"
#include "gimple-pretty-print.h"
#include "cgraph.h"
diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index 173707d..69e092e 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -69,6 +69,7 @@ along with GCC; see the file COPYING3. If not see
do \
{ \
hsa_fail_cfun (); \
+ auto_diagnostic_group d; \
if (warning_at (EXPR_LOCATION (hsa_cfun->m_decl), OPT_Whsa, \
HSA_SORRY_MSG)) \
inform (location, message, __VA_ARGS__); \
@@ -81,6 +82,7 @@ along with GCC; see the file COPYING3. If not see
do \
{ \
hsa_fail_cfun (); \
+ auto_diagnostic_group d; \
if (warning_at (EXPR_LOCATION (hsa_cfun->m_decl), OPT_Whsa, \
HSA_SORRY_MSG)) \
inform (location, message); \
@@ -3473,7 +3475,6 @@ gen_hsa_insns_for_switch_stmt (gswitch *s, hsa_bb *hbb)
e->flags &= ~EDGE_FALLTHRU;
e->flags |= EDGE_TRUE_VALUE;
- function *func = DECL_STRUCT_FUNCTION (current_function_decl);
tree index_tree = gimple_switch_index (s);
tree lowest = get_switch_low (s);
tree highest = get_switch_high (s);
@@ -3497,9 +3498,7 @@ gen_hsa_insns_for_switch_stmt (gswitch *s, hsa_bb *hbb)
hbb->append_insn (new hsa_insn_cbr (cmp_reg));
- tree default_label = gimple_switch_default_label (s);
- basic_block default_label_bb = label_to_block_fn (func,
- CASE_LABEL (default_label));
+ basic_block default_label_bb = gimple_switch_default_bb (cfun, s);
if (!gimple_seq_empty_p (phi_nodes (default_label_bb)))
{
@@ -3534,7 +3533,7 @@ gen_hsa_insns_for_switch_stmt (gswitch *s, hsa_bb *hbb)
for (unsigned i = 1; i < labels; i++)
{
tree label = gimple_switch_label (s, i);
- basic_block bb = label_to_block_fn (func, CASE_LABEL (label));
+ basic_block bb = label_to_block (cfun, CASE_LABEL (label));
unsigned HOST_WIDE_INT sub_low
= tree_to_uhwi (int_const_binop (MINUS_EXPR, CASE_LOW (label), lowest));
@@ -5301,8 +5300,7 @@ gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb)
tree function_decl = gimple_call_fndecl (stmt);
/* Prefetch pass can create type-mismatching prefetch builtin calls which
fail the gimple_call_builtin_p test above. Handle them here. */
- if (DECL_BUILT_IN_CLASS (function_decl)
- && DECL_FUNCTION_CODE (function_decl) == BUILT_IN_PREFETCH)
+ if (fndecl_built_in_p (function_decl, BUILT_IN_PREFETCH))
return;
if (function_decl == NULL_TREE)
@@ -6288,12 +6286,11 @@ LD: hard_work_3 ();
static bool
convert_switch_statements (void)
{
- function *func = DECL_STRUCT_FUNCTION (current_function_decl);
basic_block bb;
bool modified_cfg = false;
- FOR_EACH_BB_FN (bb, func)
+ FOR_EACH_BB_FN (bb, cfun)
{
gimple_stmt_iterator gsi = gsi_last_bb (bb);
if (gsi_end_p (gsi))
@@ -6316,7 +6313,7 @@ convert_switch_statements (void)
tree index_type = TREE_TYPE (index);
tree default_label = gimple_switch_default_label (s);
basic_block default_label_bb
- = label_to_block_fn (func, CASE_LABEL (default_label));
+ = label_to_block (cfun, CASE_LABEL (default_label));
basic_block cur_bb = bb;
auto_vec <edge> new_edges;
@@ -6328,8 +6325,7 @@ convert_switch_statements (void)
should be fixed after we add new collection of edges. */
for (unsigned i = 0; i < labels; i++)
{
- tree label = gimple_switch_label (s, i);
- basic_block label_bb = label_to_block_fn (func, CASE_LABEL (label));
+ basic_block label_bb = gimple_switch_label_bb (cfun, s, i);
edge e = find_edge (bb, label_bb);
edge_counts.safe_push (e->count ());
edge_probabilities.safe_push (e->probability);
@@ -6411,8 +6407,7 @@ convert_switch_statements (void)
gsi_insert_before (&cond_gsi, c, GSI_SAME_STMT);
- basic_block label_bb
- = label_to_block_fn (func, CASE_LABEL (label));
+ basic_block label_bb = label_to_block (cfun, CASE_LABEL (label));
edge new_edge = make_edge (cur_bb, label_bb, EDGE_TRUE_VALUE);
profile_probability prob_sum = sum_slice <profile_probability>
(edge_probabilities, i, labels, profile_probability::never ())
@@ -6479,10 +6474,9 @@ convert_switch_statements (void)
static void
expand_builtins ()
{
- function *func = DECL_STRUCT_FUNCTION (current_function_decl);
basic_block bb;
- FOR_EACH_BB_FN (bb, func)
+ FOR_EACH_BB_FN (bb, cfun)
{
for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
gsi_next (&gsi))
diff --git a/gcc/hsa-regalloc.c b/gcc/hsa-regalloc.c
index f402587..819f680 100644
--- a/gcc/hsa-regalloc.c
+++ b/gcc/hsa-regalloc.c
@@ -27,9 +27,9 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "dominance.h"
#include "basic-block.h"
-#include "cfg.h"
-#include "cfganal.h"
#include "function.h"
+#include "cfganal.h"
+#include "cfg.h"
#include "bitmap.h"
#include "dumpfile.h"
#include "cgraph.h"
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 8ede9ca..34d4f9e 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -3183,6 +3183,42 @@ direct_internal_fn_supported_p (internal_fn fn, tree type,
return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
}
+/* If FN is commutative in two consecutive arguments, return the
+ index of the first, otherwise return -1. */
+
+int
+first_commutative_argument (internal_fn fn)
+{
+ switch (fn)
+ {
+ case IFN_FMA:
+ case IFN_FMS:
+ case IFN_FNMA:
+ case IFN_FNMS:
+ case IFN_AVG_FLOOR:
+ case IFN_AVG_CEIL:
+ case IFN_FMIN:
+ case IFN_FMAX:
+ return 0;
+
+ case IFN_COND_ADD:
+ case IFN_COND_MUL:
+ case IFN_COND_MIN:
+ case IFN_COND_MAX:
+ case IFN_COND_AND:
+ case IFN_COND_IOR:
+ case IFN_COND_XOR:
+ case IFN_COND_FMA:
+ case IFN_COND_FMS:
+ case IFN_COND_FNMA:
+ case IFN_COND_FNMS:
+ return 1;
+
+ default:
+ return -1;
+ }
+}
+
/* Return true if IFN_SET_EDOM is supported. */
bool
diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h
index 5c5bda1..99765cf 100644
--- a/gcc/internal-fn.h
+++ b/gcc/internal-fn.h
@@ -201,6 +201,8 @@ direct_internal_fn_supported_p (internal_fn fn, tree type0, tree type1,
opt_type);
}
+extern int first_commutative_argument (internal_fn);
+
extern bool set_edom_supported_p (void);
extern internal_fn get_conditional_internal_fn (tree_code);
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 42dd4cc..afc4596 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -638,8 +638,7 @@ determine_versionability (struct cgraph_node *node,
if (DECL_EXTERNAL (node->decl))
for (cgraph_edge *edge = node->callees; !reason && edge;
edge = edge->next_callee)
- if (DECL_BUILT_IN (edge->callee->decl)
- && DECL_BUILT_IN_CLASS (edge->callee->decl) == BUILT_IN_NORMAL)
+ if (fndecl_built_in_p (edge->callee->decl, BUILT_IN_NORMAL))
{
if (DECL_FUNCTION_CODE (edge->callee->decl) == BUILT_IN_VA_ARG_PACK)
reason = "external function which calls va_arg_pack";
@@ -2911,7 +2910,7 @@ estimate_local_effects (struct cgraph_node *node)
"known contexts, code not going to grow.\n");
}
else if (good_cloning_opportunity_p (node,
- MAX ((base_time - time).to_int (),
+ MIN ((base_time - time).to_int (),
65536),
stats.freq_sum, stats.count_sum,
size))
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index e99d8cc..9564d65 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -749,6 +749,7 @@ compare_virtual_tables (varpool_node *prevailing, varpool_node *vtable)
prevailing = vtable;
vtable = tmp;
}
+ auto_diagnostic_group d;
if (warning_at (DECL_SOURCE_LOCATION
(TYPE_NAME (DECL_CONTEXT (vtable->decl))),
OPT_Wodr,
@@ -790,22 +791,25 @@ compare_virtual_tables (varpool_node *prevailing, varpool_node *vtable)
&& TREE_CODE (ref1->referred->decl) == FUNCTION_DECL))
&& TREE_CODE (ref2->referred->decl) != FUNCTION_DECL)
{
- if (!class_type->rtti_broken
- && warning_at (DECL_SOURCE_LOCATION
- (TYPE_NAME (DECL_CONTEXT (vtable->decl))),
- OPT_Wodr,
- "virtual table of type %qD contains RTTI "
- "information",
- DECL_CONTEXT (vtable->decl)))
+ if (!class_type->rtti_broken)
{
- inform (DECL_SOURCE_LOCATION
- (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
- "but is prevailed by one without from other translation "
- "unit");
- inform (DECL_SOURCE_LOCATION
- (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
- "RTTI will not work on this type");
- class_type->rtti_broken = true;
+ auto_diagnostic_group d;
+ if (warning_at (DECL_SOURCE_LOCATION
+ (TYPE_NAME (DECL_CONTEXT (vtable->decl))),
+ OPT_Wodr,
+ "virtual table of type %qD contains RTTI "
+ "information",
+ DECL_CONTEXT (vtable->decl)))
+ {
+ inform (DECL_SOURCE_LOCATION
+ (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
+ "but is prevailed by one without from other"
+ " translation unit");
+ inform (DECL_SOURCE_LOCATION
+ (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
+ "RTTI will not work on this type");
+ class_type->rtti_broken = true;
+ }
}
n2++;
end2 = !vtable->iterate_reference (n2, ref2);
@@ -831,6 +835,7 @@ compare_virtual_tables (varpool_node *prevailing, varpool_node *vtable)
if (DECL_SIZE (prevailing->decl) != DECL_SIZE (vtable->decl))
{
class_type->odr_violated = true;
+ auto_diagnostic_group d;
if (warning_at (DECL_SOURCE_LOCATION
(TYPE_NAME (DECL_CONTEXT (vtable->decl))),
OPT_Wodr,
@@ -859,6 +864,7 @@ compare_virtual_tables (varpool_node *prevailing, varpool_node *vtable)
if (TREE_CODE (ref1->referred->decl) != FUNCTION_DECL
&& TREE_CODE (ref2->referred->decl) != FUNCTION_DECL)
{
+ auto_diagnostic_group d;
if (warning_at (DECL_SOURCE_LOCATION
(TYPE_NAME (DECL_CONTEXT (vtable->decl))),
OPT_Wodr,
@@ -900,6 +906,7 @@ compare_virtual_tables (varpool_node *prevailing, varpool_node *vtable)
vtable = tmp;
ref1 = ref2;
}
+ auto_diagnostic_group d;
if (warning_at (DECL_SOURCE_LOCATION
(TYPE_NAME (DECL_CONTEXT (vtable->decl))),
OPT_Wodr,
@@ -931,6 +938,7 @@ compare_virtual_tables (varpool_node *prevailing, varpool_node *vtable)
/* And in the last case we have either mistmatch in between two virtual
methods or two virtual table pointers. */
+ auto_diagnostic_group d;
if (warning_at (DECL_SOURCE_LOCATION
(TYPE_NAME (DECL_CONTEXT (vtable->decl))), OPT_Wodr,
"virtual table of type %qD violates "
@@ -986,6 +994,7 @@ warn_odr (tree t1, tree t2, tree st1, tree st2,
if (lto_location_cache::current_cache)
lto_location_cache::current_cache->apply_location_cache ();
+ auto_diagnostic_group d;
if (!warning_at (DECL_SOURCE_LOCATION (TYPE_NAME (t1)), OPT_Wodr,
"type %qT violates the C++ One Definition Rule",
t1))
diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c
index c99718a..62095c6 100644
--- a/gcc/ipa-fnsummary.c
+++ b/gcc/ipa-fnsummary.c
@@ -1291,7 +1291,7 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
tree min, max;
predicate p;
- e = find_edge (bb, label_to_block (CASE_LABEL (cl)));
+ e = gimple_switch_edge (cfun, last, case_idx);
min = CASE_LOW (cl);
max = CASE_HIGH (cl);
@@ -1851,6 +1851,7 @@ find_foldable_builtin_expect (basic_block bb)
{
gimple *stmt = gsi_stmt (bsi);
if (gimple_call_builtin_p (stmt, BUILT_IN_EXPECT)
+ || gimple_call_builtin_p (stmt, BUILT_IN_EXPECT_WITH_PROBABILITY)
|| gimple_call_internal_p (stmt, IFN_BUILTIN_EXPECT))
{
tree var = gimple_call_lhs (stmt);
@@ -2454,10 +2455,8 @@ compute_fn_summary (struct cgraph_node *node, bool early)
for (e = node->callees; e; e = e->next_callee)
{
tree cdecl = e->callee->decl;
- if (DECL_BUILT_IN (cdecl)
- && DECL_BUILT_IN_CLASS (cdecl) == BUILT_IN_NORMAL
- && (DECL_FUNCTION_CODE (cdecl) == BUILT_IN_APPLY_ARGS
- || DECL_FUNCTION_CODE (cdecl) == BUILT_IN_VA_START))
+ if (fndecl_built_in_p (cdecl, BUILT_IN_APPLY_ARGS)
+ || fndecl_built_in_p (cdecl, BUILT_IN_VA_START))
break;
}
node->local.can_change_signature = !e;
diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c
index 39b96ba..8a6a7a3f 100644
--- a/gcc/ipa-icf.c
+++ b/gcc/ipa-icf.c
@@ -227,6 +227,8 @@ void sem_item::set_hash (hashval_t hash)
m_hash_set = true;
}
+hash_map<const_tree, hashval_t> sem_item::m_type_hash_cache;
+
/* Semantic function constructor that uses STACK as bitmap memory stack. */
sem_function::sem_function (bitmap_obstack *stack)
@@ -1587,7 +1589,7 @@ sem_item::add_type (const_tree type, inchash::hash &hstate)
return;
}
- hashval_t *val = optimizer->m_type_hash_cache.get (type);
+ hashval_t *val = m_type_hash_cache.get (type);
if (!val)
{
@@ -1607,7 +1609,7 @@ sem_item::add_type (const_tree type, inchash::hash &hstate)
hstate2.add_int (nf);
hash = hstate2.end ();
hstate.add_hwi (hash);
- optimizer->m_type_hash_cache.put (type, hash);
+ m_type_hash_cache.put (type, hash);
}
else
hstate.add_hwi (*val);
diff --git a/gcc/ipa-icf.h b/gcc/ipa-icf.h
index 622aebc..a64b385 100644
--- a/gcc/ipa-icf.h
+++ b/gcc/ipa-icf.h
@@ -281,6 +281,9 @@ private:
/* Initialize internal data structures. Bitmap STACK is used for
bitmap memory allocation process. */
void setup (bitmap_obstack *stack);
+
+ /* Because types can be arbitrarily large, avoid quadratic bottleneck. */
+ static hash_map<const_tree, hashval_t> m_type_hash_cache;
}; // class sem_item
class sem_function: public sem_item
@@ -524,9 +527,6 @@ public:
/* Gets a congruence class group based on given HASH value and TYPE. */
congruence_class_group *get_group_by_hash (hashval_t hash,
sem_item_type type);
-
- /* Because types can be arbitrarily large, avoid quadratic bottleneck. */
- hash_map<const_tree, hashval_t> m_type_hash_cache;
private:
/* For each semantic item, append hash values of references. */
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index a84d1d9..0257885 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -430,9 +430,9 @@ can_inline_edge_by_limits_p (struct cgraph_edge *e, bool report,
ipa_fn_summary *caller_info = ipa_fn_summaries->get (caller);
ipa_fn_summary *callee_info = ipa_fn_summaries->get (callee);
- /* Until GCC 4.9 we did not check the semantics alterning flags
- bellow and inline across optimization boundry.
- Enabling checks bellow breaks several packages by refusing
+ /* Until GCC 4.9 we did not check the semantics-altering flags
+ below and inlined across optimization boundaries.
+ Enabling checks below breaks several packages by refusing
to inline library always_inline functions. See PR65873.
Disable the check for early inlining for now until better solution
is found. */
diff --git a/gcc/ipa-param-manipulation.c b/gcc/ipa-param-manipulation.c
index 1ab1fcc..1e3a92a 100644
--- a/gcc/ipa-param-manipulation.c
+++ b/gcc/ipa-param-manipulation.c
@@ -218,7 +218,7 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments)
}
/* When signature changes, we need to clear builtin info. */
- if (DECL_BUILT_IN (fndecl))
+ if (fndecl_built_in_p (fndecl))
{
DECL_BUILT_IN_CLASS (fndecl) = NOT_BUILT_IN;
DECL_FUNCTION_CODE (fndecl) = (enum built_in_function) 0;
diff --git a/gcc/ipa-profile.c b/gcc/ipa-profile.c
index f921d1b..c74f4a4 100644
--- a/gcc/ipa-profile.c
+++ b/gcc/ipa-profile.c
@@ -25,13 +25,6 @@ along with GCC; see the file COPYING3. If not see
from profile feedback. This histogram is complete only with LTO,
otherwise it contains information only about the current unit.
- Similar histogram is also estimated by coverage runtime. This histogram
- is not dependent on LTO, but it suffers from various defects; first
- gcov runtime is not weighting individual basic block by estimated execution
- time and second the merging of multiple runs makes assumption that the
- histogram distribution did not change. Consequentely histogram constructed
- here may be more precise.
-
The information is used to set hot/cold thresholds.
- Next speculative indirect call resolution is performed: the local
profile pass assigns profile-id to each function and provide us with a
@@ -512,25 +505,7 @@ ipa_profile (void)
gcov_type threshold;
gcc_assert (overall_size);
- if (dump_file)
- {
- gcov_type min, cumulated_time = 0, cumulated_size = 0;
- fprintf (dump_file, "Overall time: %" PRId64"\n",
- (int64_t)overall_time);
- min = get_hot_bb_threshold ();
- for (i = 0; i < (int)histogram.length () && histogram[i]->count >= min;
- i++)
- {
- cumulated_time += histogram[i]->count * histogram[i]->time;
- cumulated_size += histogram[i]->size;
- }
- fprintf (dump_file, "GCOV min count: %" PRId64
- " Time:%3.2f%% Size:%3.2f%%\n",
- (int64_t)min,
- cumulated_time * 100.0 / overall_time,
- cumulated_size * 100.0 / overall_size);
- }
cutoff = (overall_time * PARAM_VALUE (HOT_BB_COUNT_WS_PERMILLE) + 500) / 1000;
threshold = 0;
for (i = 0; cumulated < cutoff; i++)
@@ -557,6 +532,7 @@ ipa_profile (void)
cumulated_time * 100.0 / overall_time,
cumulated_size * 100.0 / overall_size);
}
+
if (threshold > get_hot_bb_threshold ()
|| in_lto_p)
{
diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c
index 0e6440f..38f5bcf 100644
--- a/gcc/ipa-split.c
+++ b/gcc/ipa-split.c
@@ -899,8 +899,7 @@ visit_bb (basic_block bb, basic_block return_bb,
/* Check builtins that prevent splitting. */
if (gimple_code (stmt) == GIMPLE_CALL
&& (decl = gimple_call_fndecl (stmt)) != NULL_TREE
- && DECL_BUILT_IN (decl)
- && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
+ && fndecl_built_in_p (decl, BUILT_IN_NORMAL))
switch (DECL_FUNCTION_CODE (decl))
{
/* FIXME: once we will allow passing non-parm values to split part,
@@ -1347,7 +1346,7 @@ split_function (basic_block return_bb, struct split_point *split_point,
/* For usual cloning it is enough to clear builtin only when signature
changes. For partial inlining we however can not expect the part
of builtin implementation to have same semantic as the whole. */
- if (DECL_BUILT_IN (node->decl))
+ if (fndecl_built_in_p (node->decl))
{
DECL_BUILT_IN_CLASS (node->decl) = NOT_BUILT_IN;
DECL_FUNCTION_CODE (node->decl) = (enum built_in_function) 0;
diff --git a/gcc/ipa-utils.h b/gcc/ipa-utils.h
index 1609ac1..98f2a75 100644
--- a/gcc/ipa-utils.h
+++ b/gcc/ipa-utils.h
@@ -179,22 +179,24 @@ polymorphic_type_binfo_p (const_tree binfo)
inline bool
type_with_linkage_p (const_tree t)
{
- if (!TYPE_NAME (t) || TREE_CODE (TYPE_NAME (t)) != TYPE_DECL
- || !TYPE_STUB_DECL (t))
+ if (!TYPE_NAME (t) || TREE_CODE (TYPE_NAME (t)) != TYPE_DECL)
+ return false;
+
+ /* To support -fno-lto-odr-type-merigng recognize types with vtables
+ to have linkage. */
+ if (RECORD_OR_UNION_TYPE_P (t)
+ && TYPE_BINFO (t) && BINFO_VTABLE (TYPE_BINFO (t)))
+ return true;
+
+ /* After free_lang_data was run and -flto-odr-type-merging we can recongize
+ types with linkage by presence of mangled name. */
+ if (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t)))
+ return true;
+
+ /* If free lang data was not run check if indeed the type looks like C++
+ type with linkage. */
+ if (in_lto_p || !TYPE_STUB_DECL (t))
return false;
- /* In LTO do not get confused by non-C++ produced types or types built
- with -fno-lto-odr-type-merigng. */
- if (in_lto_p)
- {
- /* To support -fno-lto-odr-type-merigng recognize types with vtables
- to have linkage. */
- if (RECORD_OR_UNION_TYPE_P (t)
- && TYPE_BINFO (t) && BINFO_VTABLE (TYPE_BINFO (t)))
- return true;
- /* With -flto-odr-type-merging C++ FE specify mangled names
- for all types with the linkage. */
- return DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t));
- }
if (!RECORD_OR_UNION_TYPE_P (t) && TREE_CODE (t) != ENUMERAL_TYPE)
return false;
@@ -214,18 +216,16 @@ type_in_anonymous_namespace_p (const_tree t)
{
gcc_checking_assert (type_with_linkage_p (t));
- if (!TREE_PUBLIC (TYPE_STUB_DECL (t)))
- {
- /* C++ FE uses magic <anon> as assembler names of anonymous types.
- verify that this match with type_in_anonymous_namespace_p. */
- gcc_checking_assert (!in_lto_p
- || !DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t))
- || !strcmp ("<anon>",
- IDENTIFIER_POINTER
- (DECL_ASSEMBLER_NAME (TYPE_NAME (t)))));
- return true;
- }
- return false;
+ /* free_lang_data clears TYPE_STUB_DECL but sets assembler name to
+ "<anon>" */
+ if (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t)))
+ return !strcmp ("<anon>",
+ IDENTIFIER_POINTER
+ (DECL_ASSEMBLER_NAME (TYPE_NAME (t))));
+ else if (!TYPE_STUB_DECL (t))
+ return false;
+ else
+ return !TREE_PUBLIC (TYPE_STUB_DECL (t));
}
/* Return true of T is type with One Definition Rule info attached.
diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c
index 907dc9d..000207fa 100644
--- a/gcc/ipa-visibility.c
+++ b/gcc/ipa-visibility.c
@@ -203,7 +203,7 @@ cgraph_externally_visible_p (struct cgraph_node *node,
using the implicit built-in declarations anymore. Similarly this enables
us to remove them as unreachable before actual calls may appear during
expansion or folding. */
- if (DECL_BUILT_IN (node->decl))
+ if (fndecl_built_in_p (node->decl))
return true;
/* If linker counts on us, we must preserve the function. */
diff --git a/gcc/ira-build.c b/gcc/ira-build.c
index c0fd938..da017be 100644
--- a/gcc/ira-build.c
+++ b/gcc/ira-build.c
@@ -1876,6 +1876,11 @@ create_insn_allocnos (rtx x, rtx outer, bool output_p)
create_insn_allocnos (XEXP (x, 0), NULL, true);
return;
}
+ else if (code == CLOBBER_HIGH)
+ {
+ gcc_assert (REG_P (XEXP (x, 0)) && HARD_REGISTER_P (XEXP (x, 0)));
+ return;
+ }
else if (code == MEM)
{
create_insn_allocnos (XEXP (x, 0), NULL, false);
diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c
index 2b4ae38..6fa917a 100644
--- a/gcc/ira-costs.c
+++ b/gcc/ira-costs.c
@@ -1444,6 +1444,13 @@ scan_one_insn (rtx_insn *insn)
return insn;
}
+ if (pat_code == CLOBBER_HIGH)
+ {
+ gcc_assert (REG_P (XEXP (PATTERN (insn), 0))
+ && HARD_REGISTER_P (XEXP (PATTERN (insn), 0)));
+ return insn;
+ }
+
counted_mem = false;
set = single_set (insn);
extract_insn (insn);
diff --git a/gcc/ira.c b/gcc/ira.c
index b7bcc15..def194a 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -3086,6 +3086,7 @@ equiv_init_movable_p (rtx x, int regno)
case CC0:
case CLOBBER:
+ case CLOBBER_HIGH:
return 0;
case PRE_INC:
@@ -4411,6 +4412,7 @@ rtx_moveable_p (rtx *loc, enum op_type type)
&& rtx_moveable_p (&XEXP (x, 2), OP_IN));
case CLOBBER:
+ case CLOBBER_HIGH:
return rtx_moveable_p (&SET_DEST (x), OP_OUT);
case UNSPEC_VOLATILE:
@@ -4863,7 +4865,9 @@ interesting_dest_for_shprep (rtx_insn *insn, basic_block call_dom)
for (int i = 0; i < XVECLEN (pat, 0); i++)
{
rtx sub = XVECEXP (pat, 0, i);
- if (GET_CODE (sub) == USE || GET_CODE (sub) == CLOBBER)
+ if (GET_CODE (sub) == USE
+ || GET_CODE (sub) == CLOBBER
+ || GET_CODE (sub) == CLOBBER_HIGH)
continue;
if (GET_CODE (sub) != SET
|| side_effects_p (sub))
diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog
index 2267967..40dbde6 100644
--- a/gcc/jit/ChangeLog
+++ b/gcc/jit/ChangeLog
@@ -2158,7 +2158,7 @@
2014-12-09 David Malcolm <dmalcolm@redhat.com>
- PR jit/64206
+ PR jit/64206
* Make-lang.in (jit_OBJS): Add jit/jit-tempdir.o.
* jit-common.h (gcc::jit::tempdir): New forward decl.
* jit-playback.c: Include jit-tempdir.h.
diff --git a/gcc/jump.c b/gcc/jump.c
index f379048..06f7255 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -1094,6 +1094,7 @@ mark_jump_label_1 (rtx x, rtx_insn *insn, bool in_mem, bool is_target)
case CC0:
case REG:
case CLOBBER:
+ case CLOBBER_HIGH:
case CALL:
return;
diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index c7b5cf9f..4e6179f 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -369,7 +369,7 @@ lhd_print_error_function (diagnostic_context *context, const char *file,
{
if (diagnostic_last_function_changed (context, diagnostic))
{
- const char *old_prefix = context->printer->prefix;
+ char *old_prefix = pp_take_prefix (context->printer);
tree abstract_origin = diagnostic_abstract_origin (diagnostic);
char *new_prefix = (file && abstract_origin == NULL)
? file_name_as_prefix (context, file) : NULL;
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index 6d4042e..8be4d46 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -5709,7 +5709,7 @@ spill_hard_reg_in_range (int regno, enum reg_class rclass, rtx_insn *from, rtx_i
struct lra_insn_reg *reg;
for (reg = id->regs; reg != NULL; reg = reg->next)
- if (reg->regno <= FIRST_PSEUDO_REGISTER)
+ if (reg->regno < FIRST_PSEUDO_REGISTER)
SET_HARD_REG_BIT (ignore, reg->regno);
for (reg = static_id->hard_regs; reg != NULL; reg = reg->next)
SET_HARD_REG_BIT (ignore, reg->regno);
diff --git a/gcc/lra-eliminations.c b/gcc/lra-eliminations.c
index f5f1040..d0cfaa8 100644
--- a/gcc/lra-eliminations.c
+++ b/gcc/lra-eliminations.c
@@ -654,6 +654,7 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
return x;
case CLOBBER:
+ case CLOBBER_HIGH:
case SET:
gcc_unreachable ();
@@ -806,6 +807,16 @@ mark_not_eliminable (rtx x, machine_mode mem_mode)
setup_can_eliminate (ep, false);
return;
+ case CLOBBER_HIGH:
+ gcc_assert (REG_P (XEXP (x, 0)));
+ gcc_assert (REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER);
+ for (ep = reg_eliminate;
+ ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
+ ep++)
+ if (reg_is_clobbered_by_clobber_high (ep->to_rtx, XEXP (x, 0)))
+ setup_can_eliminate (ep, false);
+ return;
+
case SET:
if (SET_DEST (x) == stack_pointer_rtx
&& GET_CODE (SET_SRC (x)) == PLUS
diff --git a/gcc/lra-int.h b/gcc/lra-int.h
index 86e103b..5267b53 100644
--- a/gcc/lra-int.h
+++ b/gcc/lra-int.h
@@ -168,6 +168,8 @@ struct lra_insn_reg
/* True if there is an early clobber alternative for this
operand. */
unsigned int early_clobber : 1;
+ /* True if the reg is clobber highed by the operand. */
+ unsigned int clobber_high : 1;
/* The corresponding regno of the register. */
int regno;
/* Next reg info of the same insn. */
diff --git a/gcc/lra-lives.c b/gcc/lra-lives.c
index 920fd02..565c68b 100644
--- a/gcc/lra-lives.c
+++ b/gcc/lra-lives.c
@@ -658,7 +658,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
bool call_p;
int n_alt, dst_regno, src_regno;
rtx set;
- struct lra_insn_reg *reg;
+ struct lra_insn_reg *reg, *hr;
if (!NONDEBUG_INSN_P (curr_insn))
continue;
@@ -690,11 +690,12 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
break;
}
for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
- if (reg->type != OP_IN)
+ if (reg->type != OP_IN && !reg->clobber_high)
{
remove_p = false;
break;
}
+
if (remove_p && ! volatile_refs_p (PATTERN (curr_insn)))
{
dst_regno = REGNO (SET_DEST (set));
@@ -812,14 +813,24 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
unused values because they still conflict with quantities
that are live at the time of the definition. */
for (reg = curr_id->regs; reg != NULL; reg = reg->next)
- if (reg->type != OP_IN)
- {
- need_curr_point_incr
- |= mark_regno_live (reg->regno, reg->biggest_mode,
- curr_point);
- check_pseudos_live_through_calls (reg->regno,
- last_call_used_reg_set);
- }
+ {
+ if (reg->type != OP_IN)
+ {
+ need_curr_point_incr
+ |= mark_regno_live (reg->regno, reg->biggest_mode,
+ curr_point);
+ check_pseudos_live_through_calls (reg->regno,
+ last_call_used_reg_set);
+ }
+
+ if (reg->regno >= FIRST_PSEUDO_REGISTER)
+ for (hr = curr_static_id->hard_regs; hr != NULL; hr = hr->next)
+ if (hr->clobber_high
+ && maybe_gt (GET_MODE_SIZE (PSEUDO_REGNO_MODE (reg->regno)),
+ GET_MODE_SIZE (hr->biggest_mode)))
+ SET_HARD_REG_BIT (lra_reg_info[reg->regno].conflict_hard_regs,
+ hr->regno);
+ }
for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
if (reg->type != OP_IN)
@@ -1142,7 +1153,8 @@ remove_some_program_points_and_update_live_ranges (void)
n++;
if (lra_dump_file != NULL)
fprintf (lra_dump_file, "Compressing live ranges: from %d to %d - %d%%\n",
- lra_live_max_point, n, 100 * n / lra_live_max_point);
+ lra_live_max_point, n,
+ lra_live_max_point ? 100 * n / lra_live_max_point : 100);
if (n < lra_live_max_point)
{
lra_live_max_point = n;
diff --git a/gcc/lra-remat.c b/gcc/lra-remat.c
index 527f2dd..faf74ca 100644
--- a/gcc/lra-remat.c
+++ b/gcc/lra-remat.c
@@ -708,7 +708,7 @@ call_used_input_regno_present_p (rtx_insn *insn)
for (reg = (iter == 0 ? id->regs : static_id->hard_regs);
reg != NULL;
reg = reg->next)
- if (reg->type == OP_IN && reg->regno <= FIRST_PSEUDO_REGISTER
+ if (reg->type == OP_IN && reg->regno < FIRST_PSEUDO_REGISTER
&& TEST_HARD_REG_BIT (call_used_reg_set, reg->regno))
return true;
return false;
diff --git a/gcc/lra.c b/gcc/lra.c
index b410b90..aa768fb 100644
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -535,13 +535,14 @@ object_allocator<lra_insn_reg> lra_insn_reg_pool ("insn regs");
clobbered in the insn (EARLY_CLOBBER), and reference to the next
insn reg info (NEXT). If REGNO can be early clobbered,
alternatives in which it can be early clobbered are given by
- EARLY_CLOBBER_ALTS. */
+ EARLY_CLOBBER_ALTS. CLOBBER_HIGH marks if reference is a clobber
+ high. */
static struct lra_insn_reg *
new_insn_reg (rtx_insn *insn, int regno, enum op_type type,
machine_mode mode,
bool subreg_p, bool early_clobber,
alternative_mask early_clobber_alts,
- struct lra_insn_reg *next)
+ struct lra_insn_reg *next, bool clobber_high)
{
lra_insn_reg *ir = lra_insn_reg_pool.allocate ();
ir->type = type;
@@ -552,6 +553,7 @@ new_insn_reg (rtx_insn *insn, int regno, enum op_type type,
ir->subreg_p = subreg_p;
ir->early_clobber = early_clobber;
ir->early_clobber_alts = early_clobber_alts;
+ ir->clobber_high = clobber_high;
ir->regno = regno;
ir->next = next;
return ir;
@@ -821,12 +823,13 @@ setup_operand_alternative (lra_insn_recog_data_t data,
not the insn operands, in X with TYPE (in/out/inout) and flag that
it is early clobbered in the insn (EARLY_CLOBBER) and add the info
to LIST. X is a part of insn given by DATA. Return the result
- list. */
+ list. CLOBBER_HIGH marks if X is a clobber high. */
static struct lra_insn_reg *
collect_non_operand_hard_regs (rtx_insn *insn, rtx *x,
lra_insn_recog_data_t data,
struct lra_insn_reg *list,
- enum op_type type, bool early_clobber)
+ enum op_type type, bool early_clobber,
+ bool clobber_high)
{
int i, j, regno, last;
bool subreg_p;
@@ -890,7 +893,8 @@ collect_non_operand_hard_regs (rtx_insn *insn, rtx *x,
#endif
list = new_insn_reg (data->insn, regno, type, mode, subreg_p,
early_clobber,
- early_clobber ? ALL_ALTERNATIVES : 0, list);
+ early_clobber ? ALL_ALTERNATIVES : 0, list,
+ clobber_high);
}
}
return list;
@@ -899,24 +903,31 @@ collect_non_operand_hard_regs (rtx_insn *insn, rtx *x,
{
case SET:
list = collect_non_operand_hard_regs (insn, &SET_DEST (op), data,
- list, OP_OUT, false);
+ list, OP_OUT, false, false);
list = collect_non_operand_hard_regs (insn, &SET_SRC (op), data,
- list, OP_IN, false);
+ list, OP_IN, false, false);
break;
case CLOBBER:
/* We treat clobber of non-operand hard registers as early clobber. */
list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data,
- list, OP_OUT, true);
+ list, OP_OUT, true, false);
+ break;
+ case CLOBBER_HIGH:
+ /* Clobber high should always span exactly one register. */
+ gcc_assert (REG_NREGS (XEXP (op, 0)) == 1);
+ /* We treat clobber of non-operand hard registers as early clobber. */
+ list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data,
+ list, OP_OUT, true, true);
break;
case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC:
list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data,
- list, OP_INOUT, false);
+ list, OP_INOUT, false, false);
break;
case PRE_MODIFY: case POST_MODIFY:
list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data,
- list, OP_INOUT, false);
+ list, OP_INOUT, false, false);
list = collect_non_operand_hard_regs (insn, &XEXP (op, 1), data,
- list, OP_IN, false);
+ list, OP_IN, false, false);
break;
default:
fmt = GET_RTX_FORMAT (code);
@@ -924,11 +935,12 @@ collect_non_operand_hard_regs (rtx_insn *insn, rtx *x,
{
if (fmt[i] == 'e')
list = collect_non_operand_hard_regs (insn, &XEXP (op, i), data,
- list, OP_IN, false);
+ list, OP_IN, false, false);
else if (fmt[i] == 'E')
for (j = XVECLEN (op, i) - 1; j >= 0; j--)
list = collect_non_operand_hard_regs (insn, &XVECEXP (op, i, j),
- data, list, OP_IN, false);
+ data, list, OP_IN, false,
+ false);
}
}
return list;
@@ -1081,7 +1093,7 @@ lra_set_insn_recog_data (rtx_insn *insn)
else
insn_static_data->hard_regs
= collect_non_operand_hard_regs (insn, &PATTERN (insn), data,
- NULL, OP_IN, false);
+ NULL, OP_IN, false, false);
data->arg_hard_regs = NULL;
if (CALL_P (insn))
{
@@ -1107,6 +1119,11 @@ lra_set_insn_recog_data (rtx_insn *insn)
arg_hard_regs[n_hard_regs++]
= regno + i + (use_p ? 0 : FIRST_PSEUDO_REGISTER);
}
+ else if (GET_CODE (XEXP (link, 0)) == CLOBBER_HIGH)
+ /* We could support CLOBBER_HIGH and treat it in the same way as
+ HARD_REGNO_CALL_PART_CLOBBERED, but no port needs that yet. */
+ gcc_unreachable ();
+
if (n_hard_regs != 0)
{
arg_hard_regs[n_hard_regs++] = -1;
@@ -1469,7 +1486,7 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x,
{
data->regs = new_insn_reg (data->insn, regno, type, mode, subreg_p,
early_clobber, early_clobber_alts,
- data->regs);
+ data->regs, false);
return;
}
else
@@ -1482,7 +1499,8 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x,
structure. */
data->regs = new_insn_reg (data->insn, regno, type, mode,
subreg_p, early_clobber,
- early_clobber_alts, data->regs);
+ early_clobber_alts, data->regs,
+ false);
else
{
if (curr->type != type)
@@ -1509,6 +1527,8 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x,
add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_OUT,
true, ALL_ALTERNATIVES);
break;
+ case CLOBBER_HIGH:
+ gcc_unreachable ();
case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC:
add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_INOUT, false, 0);
break;
@@ -1643,10 +1663,16 @@ lra_update_insn_regno_info (rtx_insn *insn)
for (link = CALL_INSN_FUNCTION_USAGE (insn);
link != NULL_RTX;
link = XEXP (link, 1))
- if (((code = GET_CODE (XEXP (link, 0))) == USE || code == CLOBBER)
- && MEM_P (XEXP (XEXP (link, 0), 0)))
- add_regs_to_insn_regno_info (data, XEXP (XEXP (link, 0), 0), insn,
- code == USE ? OP_IN : OP_OUT, false, 0);
+ {
+ code = GET_CODE (XEXP (link, 0));
+ /* We could support CLOBBER_HIGH and treat it in the same way as
+ HARD_REGNO_CALL_PART_CLOBBERED, but no port needs that yet. */
+ gcc_assert (code != CLOBBER_HIGH);
+ if ((code == USE || code == CLOBBER)
+ && MEM_P (XEXP (XEXP (link, 0), 0)))
+ add_regs_to_insn_regno_info (data, XEXP (XEXP (link, 0), 0), insn,
+ code == USE ? OP_IN : OP_OUT, false, 0);
+ }
if (NONDEBUG_INSN_P (insn))
setup_insn_reg_info (data, freq);
}
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index d5e390c..6d9eea1 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -693,39 +693,14 @@ lto_output_ref (struct lto_simple_output_block *ob, struct ipa_ref *ref,
static void
output_profile_summary (struct lto_simple_output_block *ob)
{
- unsigned h_ix;
- struct bitpack_d bp;
-
if (profile_info)
{
/* We do not output num and run_max, they are not used by
GCC profile feedback and they are difficult to merge from multiple
units. */
- gcc_assert (profile_info->runs);
- streamer_write_uhwi_stream (ob->main_stream, profile_info->runs);
- streamer_write_gcov_count_stream (ob->main_stream, profile_info->sum_max);
+ unsigned runs = (profile_info->runs);
+ streamer_write_uhwi_stream (ob->main_stream, runs);
- /* sum_all is needed for computing the working set with the
- histogram. */
- streamer_write_gcov_count_stream (ob->main_stream, profile_info->sum_all);
-
- /* Create and output a bitpack of non-zero histogram entries indices. */
- bp = bitpack_create (ob->main_stream);
- for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
- bp_pack_value (&bp, profile_info->histogram[h_ix].num_counters > 0, 1);
- streamer_write_bitpack (&bp);
- /* Now stream out only those non-zero entries. */
- for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
- {
- if (!profile_info->histogram[h_ix].num_counters)
- continue;
- streamer_write_gcov_count_stream (ob->main_stream,
- profile_info->histogram[h_ix].num_counters);
- streamer_write_gcov_count_stream (ob->main_stream,
- profile_info->histogram[h_ix].min_value);
- streamer_write_gcov_count_stream (ob->main_stream,
- profile_info->histogram[h_ix].cum_value);
- }
/* IPA-profile computes hot bb threshold based on cumulated
whole program profile. We need to stream it down to ltrans. */
if (flag_wpa)
@@ -1266,7 +1241,7 @@ input_node (struct lto_file_decl_data *file_data,
have already been read will have their tag stored in the 'aux'
field. Since built-in functions can be referenced in multiple
functions, they are expected to be read more than once. */
- if (node->aux && !DECL_BUILT_IN (node->decl))
+ if (node->aux && !fndecl_built_in_p (node->decl))
internal_error ("bytecode stream: found multiple instances of cgraph "
"node with uid %d", node->get_uid ());
@@ -1591,46 +1566,16 @@ input_refs (struct lto_input_block *ib,
}
}
-
-static gcov_summary lto_gcov_summary;
-
/* Input profile_info from IB. */
static void
input_profile_summary (struct lto_input_block *ib,
struct lto_file_decl_data *file_data)
{
- unsigned h_ix;
- struct bitpack_d bp;
unsigned int runs = streamer_read_uhwi (ib);
if (runs)
{
file_data->profile_info.runs = runs;
- file_data->profile_info.sum_max = streamer_read_gcov_count (ib);
- file_data->profile_info.sum_all = streamer_read_gcov_count (ib);
-
- memset (file_data->profile_info.histogram, 0,
- sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
- /* Input the bitpack of non-zero histogram indices. */
- bp = streamer_read_bitpack (ib);
- /* Read in and unpack the full bitpack, flagging non-zero
- histogram entries by setting the num_counters non-zero. */
- for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
- {
- file_data->profile_info.histogram[h_ix].num_counters
- = bp_unpack_value (&bp, 1);
- }
- for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
- {
- if (!file_data->profile_info.histogram[h_ix].num_counters)
- continue;
-
- file_data->profile_info.histogram[h_ix].num_counters
- = streamer_read_gcov_count (ib);
- file_data->profile_info.histogram[h_ix].min_value
- = streamer_read_gcov_count (ib);
- file_data->profile_info.histogram[h_ix].cum_value
- = streamer_read_gcov_count (ib);
- }
+
/* IPA-profile computes hot bb threshold based on cumulated
whole program profile. We need to stream it down to ltrans. */
if (flag_ltrans)
@@ -1645,13 +1590,10 @@ static void
merge_profile_summaries (struct lto_file_decl_data **file_data_vec)
{
struct lto_file_decl_data *file_data;
- unsigned int j, h_ix;
+ unsigned int j;
gcov_unsigned_t max_runs = 0;
struct cgraph_node *node;
struct cgraph_edge *edge;
- gcov_type saved_sum_all = 0;
- gcov_summary *saved_profile_info = 0;
- int saved_scale = 0;
/* Find unit with maximal number of runs. If we ever get serious about
roundoff errors, we might also consider computing smallest common
@@ -1672,70 +1614,8 @@ merge_profile_summaries (struct lto_file_decl_data **file_data_vec)
return;
}
- profile_info = &lto_gcov_summary;
- lto_gcov_summary.runs = max_runs;
- lto_gcov_summary.sum_max = 0;
- memset (lto_gcov_summary.histogram, 0,
- sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
-
- /* Rescale all units to the maximal number of runs.
- sum_max can not be easily merged, as we have no idea what files come from
- the same run. We do not use the info anyway, so leave it 0. */
- for (j = 0; (file_data = file_data_vec[j]) != NULL; j++)
- if (file_data->profile_info.runs)
- {
- int scale = GCOV_COMPUTE_SCALE (max_runs,
- file_data->profile_info.runs);
- lto_gcov_summary.sum_max
- = MAX (lto_gcov_summary.sum_max,
- apply_scale (file_data->profile_info.sum_max, scale));
- lto_gcov_summary.sum_all
- = MAX (lto_gcov_summary.sum_all,
- apply_scale (file_data->profile_info.sum_all, scale));
- /* Save a pointer to the profile_info with the largest
- scaled sum_all and the scale for use in merging the
- histogram. */
- if (!saved_profile_info
- || lto_gcov_summary.sum_all > saved_sum_all)
- {
- saved_profile_info = &file_data->profile_info;
- saved_sum_all = lto_gcov_summary.sum_all;
- saved_scale = scale;
- }
- }
-
- gcc_assert (saved_profile_info);
-
- /* Scale up the histogram from the profile that had the largest
- scaled sum_all above. */
- for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
- {
- /* Scale up the min value as we did the corresponding sum_all
- above. Use that to find the new histogram index. */
- gcov_type scaled_min
- = apply_scale (saved_profile_info->histogram[h_ix].min_value,
- saved_scale);
- /* The new index may be shared with another scaled histogram entry,
- so we need to account for a non-zero histogram entry at new_ix. */
- unsigned new_ix = gcov_histo_index (scaled_min);
- lto_gcov_summary.histogram[new_ix].min_value
- = (lto_gcov_summary.histogram[new_ix].num_counters
- ? MIN (lto_gcov_summary.histogram[new_ix].min_value, scaled_min)
- : scaled_min);
- /* Some of the scaled counter values would ostensibly need to be placed
- into different (larger) histogram buckets, but we keep things simple
- here and place the scaled cumulative counter value in the bucket
- corresponding to the scaled minimum counter value. */
- lto_gcov_summary.histogram[new_ix].cum_value
- += apply_scale (saved_profile_info->histogram[h_ix].cum_value,
- saved_scale);
- lto_gcov_summary.histogram[new_ix].num_counters
- += saved_profile_info->histogram[h_ix].num_counters;
- }
-
- /* Watch roundoff errors. */
- if (lto_gcov_summary.sum_max < max_runs)
- lto_gcov_summary.sum_max = max_runs;
+ profile_info = XCNEW (gcov_summary);
+ profile_info->runs = max_runs;
/* If merging already happent at WPA time, we are done. */
if (flag_ltrans)
@@ -1814,10 +1694,6 @@ input_symtab (void)
merge_profile_summaries (file_data_vec);
- if (!flag_auto_profile)
- get_working_sets ();
-
-
/* Clear out the aux field that was used to store enough state to
tell which nodes should be overwritten. */
FOR_EACH_FUNCTION (node)
diff --git a/gcc/lto-opts.c b/gcc/lto-opts.c
index cc5f530..dbb41f6 100644
--- a/gcc/lto-opts.c
+++ b/gcc/lto-opts.c
@@ -78,6 +78,21 @@ lto_write_options (void)
&& !global_options.x_flag_openacc)
append_to_collect_gcc_options (&temporary_obstack, &first_p,
"-fno-openacc");
+ /* Append PIC/PIE mode because its default depends on target and it is
+ subject of merging in lto-wrapper. */
+ if (!global_options_set.x_flag_pic && !global_options_set.x_flag_pie)
+ {
+ append_to_collect_gcc_options (&temporary_obstack, &first_p,
+ global_options.x_flag_pic == 2
+ ? "-fPIC"
+ : global_options.x_flag_pic == 1
+ ? "-fpic"
+ : global_options.x_flag_pie == 2
+ ? "-fPIE"
+ : global_options.x_flag_pie == 1
+ ? "-fpie"
+ : "-fno-pie");
+ }
/* Append options from target hook and store them to offload_lto section. */
if (lto_stream_offload_p)
@@ -107,6 +122,7 @@ lto_write_options (void)
case OPT_dumpbase:
case OPT_SPECIAL_unknown:
case OPT_SPECIAL_ignore:
+ case OPT_SPECIAL_deprecated:
case OPT_SPECIAL_program_name:
case OPT_SPECIAL_input_file:
case OPT_dumpdir:
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index 8529c82..4ddcc8f 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -1013,6 +1013,14 @@ input_struct_function_base (struct function *fn, struct data_in *data_in,
/* Input the function start and end loci. */
fn->function_start_locus = stream_input_location_now (&bp, data_in);
fn->function_end_locus = stream_input_location_now (&bp, data_in);
+
+ /* Restore the instance discriminators if present. */
+ int instance_number = bp_unpack_value (&bp, 1);
+ if (instance_number)
+ {
+ instance_number = bp_unpack_value (&bp, sizeof (int) * CHAR_BIT);
+ maybe_create_decl_to_instance_map ()->put (fn->decl, instance_number);
+ }
}
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index 78b90e7..21ac1a4 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -837,7 +837,7 @@ DFS::DFS_write_tree_body (struct output_block *ob,
if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
{
- DFS_follow_tree_edge (DECL_VINDEX (expr));
+ gcc_checking_assert (DECL_VINDEX (expr) == NULL);
DFS_follow_tree_edge (DECL_FUNCTION_PERSONALITY (expr));
DFS_follow_tree_edge (DECL_FUNCTION_SPECIFIC_TARGET (expr));
DFS_follow_tree_edge (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr));
@@ -857,7 +857,9 @@ DFS::DFS_write_tree_body (struct output_block *ob,
DFS_follow_tree_edge (TYPE_CONTEXT (expr));
/* TYPE_CANONICAL is re-computed during type merging, so no need
to follow it here. */
- DFS_follow_tree_edge (TYPE_STUB_DECL (expr));
+ /* Do not stream TYPE_STUB_DECL; it is not needed by LTO but currently
+ it can not be freed by free_lang_data without triggering ICEs in
+ langhooks. */
}
if (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON))
@@ -1253,7 +1255,6 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
{
- visit (DECL_VINDEX (t));
visit (DECL_FUNCTION_PERSONALITY (t));
visit (DECL_FUNCTION_SPECIFIC_TARGET (t));
visit (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (t));
@@ -1270,7 +1271,6 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
;
else
visit (TYPE_CONTEXT (t));
- visit (TYPE_STUB_DECL (t));
}
if (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON))
@@ -2038,6 +2038,14 @@ output_struct_function_base (struct output_block *ob, struct function *fn)
stream_output_location (ob, &bp, fn->function_start_locus);
stream_output_location (ob, &bp, fn->function_end_locus);
+ /* Save the instance discriminator if present. */
+ int *instance_number_p = NULL;
+ if (decl_to_instance_map)
+ instance_number_p = decl_to_instance_map->get (fn->decl);
+ bp_pack_value (&bp, !!instance_number_p, 1);
+ if (instance_number_p)
+ bp_pack_value (&bp, *instance_number_p, sizeof (int) * CHAR_BIT);
+
streamer_write_bitpack (&bp);
}
@@ -2610,7 +2618,8 @@ write_symbol (struct streamer_tree_cache_d *cache,
unsigned char c;
gcc_checking_assert (TREE_PUBLIC (t)
- && !is_builtin_fn (t)
+ && (TREE_CODE (t) != FUNCTION_DECL
+ || !fndecl_built_in_p (t))
&& !DECL_ABSTRACT_P (t)
&& (!VAR_P (t) || !DECL_HARD_REGISTER (t)));
diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
index cf4a8c6..2b9d47e 100644
--- a/gcc/lto-wrapper.c
+++ b/gcc/lto-wrapper.c
@@ -245,6 +245,7 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
{
case OPT_SPECIAL_unknown:
case OPT_SPECIAL_ignore:
+ case OPT_SPECIAL_deprecated:
case OPT_SPECIAL_program_name:
case OPT_SPECIAL_input_file:
break;
@@ -255,6 +256,8 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
/* Fallthru. */
case OPT_fdiagnostics_show_caret:
+ case OPT_fdiagnostics_show_labels:
+ case OPT_fdiagnostics_show_line_numbers:
case OPT_fdiagnostics_show_option:
case OPT_fdiagnostics_show_location_:
case OPT_fshow_column:
@@ -283,7 +286,6 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
case OPT_fopenmp:
case OPT_fopenacc:
- case OPT_fcheck_pointer_bounds:
/* For selected options we can merge conservatively. */
for (j = 0; j < *decoded_options_count; ++j)
if ((*decoded_options)[j].opt_index == foption->opt_index)
@@ -291,8 +293,7 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
if (j == *decoded_options_count)
append_option (decoded_options, decoded_options_count, foption);
/* -fopenmp > -fno-openmp,
- -fopenacc > -fno-openacc,
- -fcheck_pointer_bounds > -fcheck_pointer_bounds */
+ -fopenacc > -fno-openacc */
else if (foption->value > (*decoded_options)[j].value)
(*decoded_options)[j] = *foption;
break;
@@ -408,6 +409,11 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
It is a common mistake to mix few -fPIC compiled objects into otherwise
non-PIC code. We do not want to build everything with PIC then.
+ Similarly we merge PIE options, however in addition we keep
+ -fPIC + -fPIE = -fPIE
+ -fpic + -fPIE = -fpie
+ -fPIC/-fpic + -fpie = -fpie
+
It would be good to warn on mismatches, but it is bit hard to do as
we do not know what nothing translates to. */
@@ -415,11 +421,38 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
if ((*decoded_options)[j].opt_index == OPT_fPIC
|| (*decoded_options)[j].opt_index == OPT_fpic)
{
- if (!pic_option
- || (pic_option->value > 0) != ((*decoded_options)[j].value > 0))
- remove_option (decoded_options, j, decoded_options_count);
- else if (pic_option->opt_index == OPT_fPIC
- && (*decoded_options)[j].opt_index == OPT_fpic)
+ /* -fno-pic in one unit implies -fno-pic everywhere. */
+ if ((*decoded_options)[j].value == 0)
+ j++;
+ /* If we have no pic option or merge in -fno-pic, we still may turn
+ existing pic/PIC mode into pie/PIE if -fpie/-fPIE is present. */
+ else if ((pic_option && pic_option->value == 0)
+ || !pic_option)
+ {
+ if (pie_option)
+ {
+ bool big = (*decoded_options)[j].opt_index == OPT_fPIC
+ && pie_option->opt_index == OPT_fPIE;
+ (*decoded_options)[j].opt_index = big ? OPT_fPIE : OPT_fpie;
+ if (pie_option->value)
+ (*decoded_options)[j].canonical_option[0] = big ? "-fPIE" : "-fpie";
+ else
+ (*decoded_options)[j].canonical_option[0] = big ? "-fno-pie" : "-fno-pie";
+ (*decoded_options)[j].value = pie_option->value;
+ j++;
+ }
+ else if (pic_option)
+ {
+ (*decoded_options)[j] = *pic_option;
+ j++;
+ }
+ /* We do not know if target defaults to pic or not, so just remove
+ option if it is missing in one unit but enabled in other. */
+ else
+ remove_option (decoded_options, j, decoded_options_count);
+ }
+ else if (pic_option->opt_index == OPT_fpic
+ && (*decoded_options)[j].opt_index == OPT_fPIC)
{
(*decoded_options)[j] = *pic_option;
j++;
@@ -430,11 +463,42 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
else if ((*decoded_options)[j].opt_index == OPT_fPIE
|| (*decoded_options)[j].opt_index == OPT_fpie)
{
- if (!pie_option
- || pie_option->value != (*decoded_options)[j].value)
- remove_option (decoded_options, j, decoded_options_count);
- else if (pie_option->opt_index == OPT_fPIE
- && (*decoded_options)[j].opt_index == OPT_fpie)
+ /* -fno-pie in one unit implies -fno-pie everywhere. */
+ if ((*decoded_options)[j].value == 0)
+ j++;
+ /* If we have no pie option or merge in -fno-pie, we still preserve
+ PIE/pie if pic/PIC is present. */
+ else if ((pie_option && pie_option->value == 0)
+ || !pie_option)
+ {
+ /* If -fPIC/-fpic is given, merge it with -fPIE/-fpie. */
+ if (pic_option)
+ {
+ if (pic_option->opt_index == OPT_fpic
+ && (*decoded_options)[j].opt_index == OPT_fPIE)
+ {
+ (*decoded_options)[j].opt_index = OPT_fpie;
+ (*decoded_options)[j].canonical_option[0]
+ = pic_option->value ? "-fpie" : "-fno-pie";
+ }
+ else if (!pic_option->value)
+ (*decoded_options)[j].canonical_option[0] = "-fno-pie";
+ (*decoded_options)[j].value = pic_option->value;
+ j++;
+ }
+ else if (pie_option)
+ {
+ (*decoded_options)[j] = *pie_option;
+ j++;
+ }
+ /* Because we always append pic/PIE options this code path should
+ not happen unless the LTO object was built by old lto1 which
+ did not contain that logic yet. */
+ else
+ remove_option (decoded_options, j, decoded_options_count);
+ }
+ else if (pie_option->opt_index == OPT_fpie
+ && (*decoded_options)[j].opt_index == OPT_fPIE)
{
(*decoded_options)[j] = *pie_option;
j++;
@@ -536,6 +600,8 @@ append_compiler_options (obstack *argv_obstack, struct cl_decoded_option *opts,
switch (option->opt_index)
{
case OPT_fdiagnostics_show_caret:
+ case OPT_fdiagnostics_show_labels:
+ case OPT_fdiagnostics_show_line_numbers:
case OPT_fdiagnostics_show_option:
case OPT_fdiagnostics_show_location_:
case OPT_fshow_column:
@@ -553,7 +619,6 @@ append_compiler_options (obstack *argv_obstack, struct cl_decoded_option *opts,
case OPT_Ofast:
case OPT_Og:
case OPT_Os:
- case OPT_fcheck_pointer_bounds:
break;
default:
@@ -582,6 +647,8 @@ append_diag_options (obstack *argv_obstack, struct cl_decoded_option *opts,
{
case OPT_fdiagnostics_color_:
case OPT_fdiagnostics_show_caret:
+ case OPT_fdiagnostics_show_labels:
+ case OPT_fdiagnostics_show_line_numbers:
case OPT_fdiagnostics_show_option:
case OPT_fdiagnostics_show_location_:
case OPT_fshow_column:
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index eb23997..f997f03 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,25 @@
+2018-08-29 Martin Liska <mliska@suse.cz>
+
+ PR bootstrap/87130
+ * lto.c (read_cgraph_and_symbols): Fix thinko, revert
+ to behavior before r263887.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ * lto-lang.c (handle_const_attribute): Use new function
+ fndecl_built_in_p and remove check for FUNCTION_DECL if
+ possible.
+ * lto-symtab.c (lto_symtab_merge_p): Likewise.
+ (lto_symtab_merge_decls_1): Likewise.
+ (lto_symtab_merge_symbols): Likewise.
+ * lto.c (lto_maybe_register_decl): Likewise.
+ (read_cgraph_and_symbols): Likewise.
+
+2018-08-21 Tom de Vries <tdevries@suse.de>
+
+ * lto.c (lto_main): Call debuginfo_early_start and
+ debuginfo_early_stop.
+
2018-07-20 Martin Sebor <msebor@redhat.com>
PR middle-end/82063
@@ -27,12 +49,12 @@
2018-06-20 Martin Liska <mliska@suse.cz>
* lto-symtab.c (lto_symtab_merge_p): Remove not valid
- FIXME comment.
+ FIXME comment.
2018-06-19 Martin Liska <mliska@suse.cz>
* lto-partition.c (add_symbol_to_partition_1): Use symbol_summary::get instead
- of get_create.
+ of get_create.
(undo_partition): Likewise.
(lto_balanced_map): Likewise.
@@ -272,11 +294,11 @@
2017-08-21 Richard Biener <rguenther@suse.de>
- * lto.c (unify_scc): Truncate DIE reference queue for dropped SCCs.
- (lto_read_decls): Process TRANSLATION_UNIT_DECLs. Remove
- TYPE_DECL debug processing, register DIE references from
- prevailing SCCs with the debug machinery.
- (lto_section_with_id): Handle LTO debug sections.
+ * lto.c (unify_scc): Truncate DIE reference queue for dropped SCCs.
+ (lto_read_decls): Process TRANSLATION_UNIT_DECLs. Remove
+ TYPE_DECL debug processing, register DIE references from
+ prevailing SCCs with the debug machinery.
+ (lto_section_with_id): Handle LTO debug sections.
2017-08-16 Nathan Sidwell <nathan@acm.org>
@@ -349,7 +371,7 @@
2017-05-01 Xi Ruoyao <ryxi@stu.xidian.edu.cn>
- PR c++/80038
+ PR c++/80038
* lto-lang.c (lto_init): Set in_lto_p earlier.
2017-04-12 Richard Biener <rguenther@suse.de>
@@ -508,7 +530,7 @@
decls have no assemblernames.
2016-01-19 Martin Liska <mliska@suse.cz>
- Martin Jambor <mjambor@suse.cz>
+ Martin Jambor <mjambor@suse.cz>
* lto-partition.c: Include "hsa.h"
(add_symbol_to_partition_1): Put hsa implementations into the
@@ -2137,7 +2159,7 @@
2012-06-18 Lawrence Crowl <crowl@google.com>
- * lto.c (do_whole_program_analysis): Rename use of TV_PHASE_CGRAPH to
+ * lto.c (do_whole_program_analysis): Rename use of TV_PHASE_CGRAPH to
TV_PHASE_OPT_GEN. Use new timevar TV_PHASE_STREAM_OUT around the call
to lto_wpa_write_files.
(lto_main): Rename use of TV_PHASE_CGRAPH to TV_PHASE_OPT_GEN. Move
@@ -2193,7 +2215,7 @@
2012-04-16 Jan Hubicka <jh@suse.cz>
* lto.c (read_cgraph_and_symbols): Use FOR_EACH
- walkers to walk cgraph and varpool.
+ walkers to walk cgraph and varpool.
(materialize_cgraph): Likewise.
* lto-partition.c (lto_1_to_1_map): Likewise.
(lto_balanced_map): Likewise.
@@ -2753,7 +2775,7 @@
2010-10-03 Andi Kleen <ak@linux.intel.com>
* lto.c (lto_file_finalize): Replace gcc_assert for missing section
- with fatal_error.
+ with fatal_error.
2010-09-28 Jan Hubicka <jh@suse.cz>
@@ -2856,7 +2878,7 @@
2010-07-10 Andi Kleen <ak@linux.intel.com>
PR lto/44992
- * lto.c: Include splay-tree.h
+ * lto.c: Include splay-tree.h
(lto_resolution_read): Change to walk file_ids tree and parse
extra file_id in resolution file.
(lto_section_with_id): Add.
@@ -2909,7 +2931,7 @@
2010-07-04 Jan Hubicka <jh@suse.cz>
- * lto.c (read_cgraph_and_symbols): Dump cgraph before merging.
+ * lto.c (read_cgraph_and_symbols): Dump cgraph before merging.
2010-06-13 Richard Guenther <rguenther@suse.de>
@@ -3328,7 +3350,7 @@
* lto.c (lto_resolution_read): Add more checks. Discard rest of line.
2009-11-04 Richard Guenther <rguenther@suse.de>
- Rafael Avila de Espindola <espindola@google.com>
+ Rafael Avila de Espindola <espindola@google.com>
* lto-elf.c (lto_elf_build_section_table): Add the base offset.
(lto_elf_file_open): Handle offsets in arguments name@offest.
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index de6ec1c..8eb4a25 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -303,8 +303,7 @@ handle_const_attribute (tree *node, tree ARG_UNUSED (name),
tree ARG_UNUSED (args), int ARG_UNUSED (flags),
bool * ARG_UNUSED (no_add_attrs))
{
- if (TREE_CODE (*node) != FUNCTION_DECL
- || !DECL_BUILT_IN (*node))
+ if (!fndecl_built_in_p (*node))
inform (UNKNOWN_LOCATION, "%s:%s: %E: %E", __FILE__, __func__, *node, name);
tree type = TREE_TYPE (*node);
diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c
index 0d603c0..cf08d45 100644
--- a/gcc/lto/lto-symtab.c
+++ b/gcc/lto/lto-symtab.c
@@ -546,14 +546,14 @@ lto_symtab_merge_p (tree prevailing, tree decl)
if (TREE_CODE (prevailing) == FUNCTION_DECL)
{
- if (DECL_BUILT_IN (prevailing) != DECL_BUILT_IN (decl))
+ if (fndecl_built_in_p (prevailing) != fndecl_built_in_p (decl))
{
if (dump_file)
fprintf (dump_file, "Not merging decls; "
"DECL_BUILT_IN mismatch\n");
return false;
}
- if (DECL_BUILT_IN (prevailing)
+ if (fndecl_built_in_p (prevailing)
&& (DECL_BUILT_IN_CLASS (prevailing) != DECL_BUILT_IN_CLASS (decl)
|| DECL_FUNCTION_CODE (prevailing) != DECL_FUNCTION_CODE (decl)))
{
@@ -797,7 +797,7 @@ lto_symtab_merge_decls_1 (symtab_node *first)
{
for (e = first; e; e = e->next_sharing_asm_name)
if (TREE_CODE (e->decl) == FUNCTION_DECL
- && !DECL_BUILT_IN (e->decl)
+ && !fndecl_built_in_p (e->decl)
&& lto_symtab_symbol_p (e))
{
prevailing = e;
@@ -1030,7 +1030,7 @@ lto_symtab_merge_symbols (void)
/* Builtins are not merged via decl merging. It is however
possible that tree merging unified the declaration. We
do not want duplicate entries in symbol table. */
- if (cnode && DECL_BUILT_IN (node->decl)
+ if (cnode && fndecl_built_in_p (node->decl)
&& (cnode2 = cgraph_node::get (node->decl))
&& cnode2 != cnode)
lto_cgraph_replace_node (cnode2, cnode);
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 8db280e..598492d 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -894,7 +894,7 @@ lto_maybe_register_decl (struct data_in *data_in, tree t, unsigned ix)
if (TREE_CODE (t) == VAR_DECL)
lto_register_var_decl_in_symtab (data_in, t, ix);
else if (TREE_CODE (t) == FUNCTION_DECL
- && !DECL_BUILT_IN (t))
+ && !fndecl_built_in_p (t))
lto_register_function_decl_in_symtab (data_in, t, ix);
}
@@ -2923,7 +2923,8 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
FOR_EACH_SYMBOL (snode)
if (snode->externally_visible && snode->real_symbol_p ()
&& snode->lto_file_data && snode->lto_file_data->resolution_map
- && !is_builtin_fn (snode->decl)
+ && !(TREE_CODE (snode->decl) == FUNCTION_DECL
+ && fndecl_built_in_p (snode->decl))
&& !(VAR_P (snode->decl) && DECL_HARD_REGISTER (snode->decl)))
{
ld_plugin_symbol_resolution_t *res;
@@ -3419,7 +3420,9 @@ lto_main (void)
lto_promote_statics_nonwpa ();
/* Annotate the CU DIE and mark the early debug phase as finished. */
+ debuginfo_early_start ();
debug_hooks->early_finish ("<artificial>");
+ debuginfo_early_stop ();
/* Let the middle end know that we have read and merged all of
the input files. */
diff --git a/gcc/machmode.h b/gcc/machmode.h
index b938eea..239a909 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -237,9 +237,6 @@ extern const unsigned char mode_class[NUM_MACHINE_MODES];
|| CLASS == MODE_ACCUM \
|| CLASS == MODE_UACCUM)
-#define POINTER_BOUNDS_MODE_P(MODE) \
- (GET_MODE_CLASS (MODE) == MODE_POINTER_BOUNDS)
-
/* An optional T (i.e. a T or nothing), where T is some form of mode class. */
template<typename T>
class opt_mode
@@ -482,7 +479,6 @@ scalar_mode::includes_p (machine_mode m)
case MODE_UACCUM:
case MODE_FLOAT:
case MODE_DECIMAL_FLOAT:
- case MODE_POINTER_BOUNDS:
return true;
default:
return false;
diff --git a/gcc/match.pd b/gcc/match.pd
index 0ae1af0c..74244f3 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -470,7 +470,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& TYPE_OVERFLOW_UNDEFINED (type)
&& wi::multiple_of_p (wi::to_wide (@1), wi::to_wide (@2),
TYPE_SIGN (type)))
- { build_zero_cst (type); })))
+ { build_zero_cst (type); }))
+ /* For (X % C) == 0, if X is signed and C is power of 2, use unsigned
+ modulo and comparison, since it is simpler and equivalent. */
+ (for cmp (eq ne)
+ (simplify
+ (cmp (mod @0 integer_pow2p@2) integer_zerop@1)
+ (if (!TYPE_UNSIGNED (TREE_TYPE (@0)))
+ (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
+ (cmp (mod (convert:utype @0) (convert:utype @2)) (convert:utype @1)))))))
/* X % -C is the same as X % C. */
(simplify
@@ -776,6 +784,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(bit_not (bit_and:cs (bit_not @0) @1))
(bit_ior @0 (bit_not @1)))
+/* ~(~a | b) --> a & ~b */
+(simplify
+ (bit_not (bit_ior:cs (bit_not @0) @1))
+ (bit_and @0 (bit_not @1)))
+
/* Simplify (~X & Y) to X ^ Y if we know that (X & ~Y) is 0. */
#if GIMPLE
(simplify
@@ -981,6 +994,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(bit_and:c (bit_ior:c @0 @1) (bit_xor:c @1 (bit_not @0)))
(bit_and @0 @1))
+/* (~x | y) & (x | ~y) -> ~(x ^ y) */
+(simplify
+ (bit_and (bit_ior:cs (bit_not @0) @1) (bit_ior:cs @0 (bit_not @1)))
+ (bit_not (bit_xor @0 @1)))
+
+/* (~x | y) ^ (x | ~y) -> x ^ y */
+(simplify
+ (bit_xor (bit_ior:c (bit_not @0) @1) (bit_ior:c @0 (bit_not @1)))
+ (bit_xor @0 @1))
+
/* ~x & ~y -> ~(x | y)
~x | ~y -> ~(x & y) */
(for op (bit_and bit_ior)
@@ -1027,7 +1050,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(for opo (bit_and bit_xor)
opi (bit_xor bit_and)
(simplify
- (opo:c (opi:c @0 @1) @1)
+ (opo:c (opi:cs @0 @1) @1)
(bit_and (bit_not @0) @1)))
/* Given a bit-wise operation CODE applied to ARG0 and ARG1, see if both
@@ -3535,8 +3558,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* Disable this optimization if we're casting a function pointer
type on targets that require function pointer canonicalization. */
&& !(targetm.have_canonicalize_funcptr_for_compare ()
- && TREE_CODE (TREE_TYPE (@00)) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (TREE_TYPE (@00))) == FUNCTION_TYPE)
+ && POINTER_TYPE_P (TREE_TYPE (@00))
+ && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (@00))))
&& single_use (@0))
(if (TYPE_PRECISION (TREE_TYPE (@00)) == TYPE_PRECISION (TREE_TYPE (@0))
&& (TREE_CODE (@10) == INTEGER_CST
@@ -4937,3 +4960,63 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (inverse_conditions_p (@0, @2)
&& element_precision (type) == element_precision (op_type))
(view_convert (cond_op @2 @3 @4 @5 (view_convert:op_type @1)))))))
+
+/* For pointers @0 and @2 and nonnegative constant offset @1, look for
+ expressions like:
+
+ A: (@0 + @1 < @2) | (@2 + @1 < @0)
+ B: (@0 + @1 <= @2) | (@2 + @1 <= @0)
+
+ If pointers are known not to wrap, B checks whether @1 bytes starting
+ at @0 and @2 do not overlap, while A tests the same thing for @1 + 1
+ bytes. A is more efficiently tested as:
+
+ A: (sizetype) (@0 + @1 - @2) > @1 * 2
+
+ The equivalent expression for B is given by replacing @1 with @1 - 1:
+
+ B: (sizetype) (@0 + (@1 - 1) - @2) > (@1 - 1) * 2
+
+ @0 and @2 can be swapped in both expressions without changing the result.
+
+ The folds rely on sizetype's being unsigned (which is always true)
+ and on its being the same width as the pointer (which we have to check).
+
+ The fold replaces two pointer_plus expressions, two comparisons and
+ an IOR with a pointer_plus, a pointer_diff, and a comparison, so in
+ the best case it's a saving of two operations. The A fold retains one
+ of the original pointer_pluses, so is a win even if both pointer_pluses
+ are used elsewhere. The B fold is a wash if both pointer_pluses are
+ used elsewhere, since all we end up doing is replacing a comparison with
+ a pointer_plus. We do still apply the fold under those circumstances
+ though, in case applying it to other conditions eventually makes one of the
+ pointer_pluses dead. */
+(for ior (truth_orif truth_or bit_ior)
+ (for cmp (le lt)
+ (simplify
+ (ior (cmp:cs (pointer_plus@3 @0 INTEGER_CST@1) @2)
+ (cmp:cs (pointer_plus@4 @2 @1) @0))
+ (if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+ && TYPE_OVERFLOW_WRAPS (sizetype)
+ && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (sizetype))
+ /* Calculate the rhs constant. */
+ (with { offset_int off = wi::to_offset (@1) - (cmp == LE_EXPR ? 1 : 0);
+ offset_int rhs = off * 2; }
+ /* Always fails for negative values. */
+ (if (wi::min_precision (rhs, UNSIGNED) <= TYPE_PRECISION (sizetype))
+ /* Since the order of @0 and @2 doesn't matter, let tree_swap_operands_p
+ pick a canonical order. This increases the chances of using the
+ same pointer_plus in multiple checks. */
+ (with { bool swap_p = tree_swap_operands_p (@0, @2);
+ tree rhs_tree = wide_int_to_tree (sizetype, rhs); }
+ (if (cmp == LT_EXPR)
+ (gt (convert:sizetype
+ (pointer_diff:ssizetype { swap_p ? @4 : @3; }
+ { swap_p ? @0 : @2; }))
+ { rhs_tree; })
+ (gt (convert:sizetype
+ (pointer_diff:ssizetype
+ (pointer_plus { swap_p ? @2 : @0; }
+ { wide_int_to_tree (sizetype, off); })
+ { swap_p ? @0 : @2; }))
+ { rhs_tree; })))))))))
diff --git a/gcc/memory-block.h b/gcc/memory-block.h
index 5440428..c045d2e 100644
--- a/gcc/memory-block.h
+++ b/gcc/memory-block.h
@@ -68,6 +68,11 @@ memory_block_pool::release (void *uncast_block)
block_list *block = new (uncast_block) block_list;
block->m_next = instance.m_blocks;
instance.m_blocks = block;
+
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS ((char *)uncast_block
+ + sizeof (block_list),
+ block_size
+ - sizeof (block_list)));
}
extern void *mempool_obstack_chunk_alloc (size_t) ATTRIBUTE_MALLOC;
diff --git a/gcc/mode-classes.def b/gcc/mode-classes.def
index 522e446..62ec138 100644
--- a/gcc/mode-classes.def
+++ b/gcc/mode-classes.def
@@ -22,7 +22,6 @@ along with GCC; see the file COPYING3. If not see
DEF_MODE_CLASS (MODE_CC), /* condition code in a register */ \
DEF_MODE_CLASS (MODE_INT), /* integer */ \
DEF_MODE_CLASS (MODE_PARTIAL_INT), /* integer with padding bits */ \
- DEF_MODE_CLASS (MODE_POINTER_BOUNDS), /* bounds */ \
DEF_MODE_CLASS (MODE_FRACT), /* signed fractional number */ \
DEF_MODE_CLASS (MODE_UFRACT), /* unsigned fractional number */ \
DEF_MODE_CLASS (MODE_ACCUM), /* signed accumulator */ \
diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c
index 9a27365..121e619 100644
--- a/gcc/modulo-sched.c
+++ b/gcc/modulo-sched.c
@@ -1449,10 +1449,6 @@ sms_schedule (void)
fprintf (dump_file, "%" PRId64 "max %" PRId64,
(int64_t) trip_count, (int64_t) max_trip_count);
fprintf (dump_file, "\n");
- fprintf (dump_file, "SMS profile-sum-max ");
- fprintf (dump_file, "%" PRId64,
- (int64_t) profile_info->sum_max);
- fprintf (dump_file, "\n");
}
}
continue;
@@ -1567,10 +1563,6 @@ sms_schedule (void)
fprintf (dump_file, "%" PRId64,
(int64_t) bb->count.to_gcov_type ());
fprintf (dump_file, "\n");
- fprintf (dump_file, "SMS profile-sum-max ");
- fprintf (dump_file, "%" PRId64,
- (int64_t) profile_info->sum_max);
- fprintf (dump_file, "\n");
}
fprintf (dump_file, "SMS doloop\n");
fprintf (dump_file, "SMS built-ddg %d\n", g->num_nodes);
diff --git a/gcc/multiple_target.c b/gcc/multiple_target.c
index a1fe09a..a610d9a 100644
--- a/gcc/multiple_target.c
+++ b/gcc/multiple_target.c
@@ -347,6 +347,7 @@ expand_target_clones (struct cgraph_node *node, bool definition)
if (node->definition
&& !tree_versionable_function_p (node->decl))
{
+ auto_diagnostic_group d;
error_at (DECL_SOURCE_LOCATION (node->decl),
"clones for %<target_clones%> attribute cannot be created");
const char *reason = NULL;
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index 6369371..5eeec72 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -2049,7 +2049,7 @@
Merge from 'apple/trunk' branch on FSF servers.
2005-08-23 Stuart Hastings <stuart@apple.com>
- Ziemowit Laski <zlaski@apple.com>
+ Ziemowit Laski <zlaski@apple.com>
Radar 4209854
* objc-act.c (objc_decay_parm_type): New function.
diff --git a/gcc/objcp/ChangeLog b/gcc/objcp/ChangeLog
index ec829b9..b8a9793 100644
--- a/gcc/objcp/ChangeLog
+++ b/gcc/objcp/ChangeLog
@@ -241,7 +241,7 @@
* Make-lang.in (cc1objplus-dummy): Remove.
(cc1objplus-checksum): Change to run checksum over object files
- and options only.
+ and options only.
2010-10-04 Andi Kleen <ak@linux.intel.com>
@@ -388,13 +388,13 @@
Revert:
2008-02-07 Andreas Tobler <andreast-list@fgznet.ch>
- Douglas Gregor <doug.gregor@gmail.com>
+ Douglas Gregor <doug.gregor@gmail.com>
PR bootstrap/35115
* objcp-decl.c (objcp_comptypes): Call cp_comptypes, not comptypes.
2008-02-07 Andreas Tobler <andreast-list@fgznet.ch>
- Douglas Gregor <doug.gregor@gmail.com>
+ Douglas Gregor <doug.gregor@gmail.com>
PR bootstrap/35115
* objcp-decl.c (objcp_comptypes): Call cp_comptypes, not comptypes.
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 843c66f..fdabf67 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -2975,9 +2975,8 @@ scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
static bool
setjmp_or_longjmp_p (const_tree fndecl)
{
- if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
- && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
- || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
+ if (fndecl_built_in_p (fndecl, BUILT_IN_SETJMP)
+ || fndecl_built_in_p (fndecl, BUILT_IN_LONGJMP))
return true;
tree declname = DECL_NAME (fndecl);
@@ -8832,7 +8831,7 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
call_stmt = as_a <gcall *> (stmt);
fndecl = gimple_call_fndecl (call_stmt);
if (fndecl
- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+ && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
switch (DECL_FUNCTION_CODE (fndecl))
{
case BUILT_IN_GOMP_BARRIER:
diff --git a/gcc/opt-functions.awk b/gcc/opt-functions.awk
index 6611bf3..6f62526 100644
--- a/gcc/opt-functions.awk
+++ b/gcc/opt-functions.awk
@@ -156,7 +156,6 @@ function switch_bit_fields (flags)
hwi_flag \
flag_init("ToLower", flags) \
flag_init("Report", flags) \
- flag_init("Deprecated", flags) \
byte_size_flag
sub(", $", "", result)
diff --git a/gcc/opt-suggestions.c b/gcc/opt-suggestions.c
index 894eea5..c68c9ee 100644
--- a/gcc/opt-suggestions.c
+++ b/gcc/opt-suggestions.c
@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see
#include "params.h"
#include "spellcheck.h"
#include "opt-suggestions.h"
+#include "common/common-target.h"
#include "selftest.h"
option_proposer::~option_proposer ()
@@ -38,7 +39,7 @@ option_proposer::suggest_option (const char *bad_opt)
{
/* Lazily populate m_option_suggestions. */
if (!m_option_suggestions)
- build_option_suggestions ();
+ build_option_suggestions (NULL);
gcc_assert (m_option_suggestions);
/* "m_option_suggestions" is now populated. Use it. */
@@ -80,7 +81,7 @@ option_proposer::get_completions (const char *option_prefix,
{
/* Lazily populate m_option_suggestions. */
if (!m_option_suggestions)
- build_option_suggestions ();
+ build_option_suggestions (option_prefix);
gcc_assert (m_option_suggestions);
for (unsigned i = 0; i < m_option_suggestions->length (); i++)
@@ -108,7 +109,7 @@ option_proposer::suggest_completion (const char *option_prefix)
}
void
-option_proposer::build_option_suggestions (void)
+option_proposer::build_option_suggestions (const char *prefix)
{
gcc_assert (m_option_suggestions == NULL);
m_option_suggestions = new auto_string_vec ();
@@ -135,8 +136,27 @@ option_proposer::build_option_suggestions (void)
}
}
else
- add_misspelling_candidates (m_option_suggestions, option,
- opt_text);
+ {
+ if (option->flags & CL_TARGET)
+ {
+ vec<const char *> option_values
+ = targetm_common.get_valid_option_values (i, prefix);
+ if (!option_values.is_empty ())
+ {
+ for (unsigned j = 0; j < option_values.length (); j++)
+ {
+ char *with_arg = concat (opt_text, option_values[j],
+ NULL);
+ add_misspelling_candidates (m_option_suggestions, option,
+ with_arg);
+ free (with_arg);
+ }
+ }
+ }
+ else
+ add_misspelling_candidates (m_option_suggestions, option,
+ opt_text);
+ }
break;
case OPT_fsanitize_:
diff --git a/gcc/opt-suggestions.h b/gcc/opt-suggestions.h
index 222bafa..eb93277 100644
--- a/gcc/opt-suggestions.h
+++ b/gcc/opt-suggestions.h
@@ -58,8 +58,10 @@ public:
private:
/* Helper function for option_proposer::suggest_option. Populate
m_option_suggestions with candidate strings for misspelled options.
- The strings will be freed by the option_proposer's dtor. */
- void build_option_suggestions ();
+ The strings will be freed by the option_proposer's dtor.
+ PREFIX is used for bash completion suggestions, otherwise
+ it's set to NULL. */
+ void build_option_suggestions (const char *prefix);
/* Find parameter completions for --param format with SEPARATOR.
Again, save the completions into results. */
diff --git a/gcc/optabs.c b/gcc/optabs.c
index cadf467..6052222 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -3812,6 +3812,9 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
gcc_assert (methods == OPTAB_DIRECT || methods == OPTAB_WIDEN
|| methods == OPTAB_LIB_WIDEN);
+ if (CONST_SCALAR_INT_P (y))
+ canonicalize_comparison (mode, &comparison, &y);
+
/* If we are optimizing, force expensive constants into a register. */
if (CONSTANT_P (x) && optimize
&& (rtx_cost (x, mode, COMPARE, 0, optimize_insn_for_speed_p ())
diff --git a/gcc/optc-gen.awk b/gcc/optc-gen.awk
index 7eaca62..3668b3e 100644
--- a/gcc/optc-gen.awk
+++ b/gcc/optc-gen.awk
@@ -323,8 +323,22 @@ for (i = 0; i < n_opts; i++) {
alias_arg = opt_args("Alias", flags[i])
if (alias_arg == "") {
- if (flag_set_p("Ignore", flags[i]))
- alias_data = "NULL, NULL, OPT_SPECIAL_ignore"
+ if (flag_set_p("Ignore", flags[i])) {
+ alias_data = "NULL, NULL, OPT_SPECIAL_ignore"
+ if (warn_message != "NULL")
+ print "#error Ignored option with Warn"
+ if (var_name(flags[i]) != "")
+ print "#error Ignored option with Var"
+ if (flag_set_p("Report", flags[i]))
+ print "#error Ignored option with Report"
+ }
+ else if (flag_set_p("Deprecated", flags[i])) {
+ alias_data = "NULL, NULL, OPT_SPECIAL_deprecated"
+ if (warn_message != "NULL")
+ print "#error Deprecated option with Warn"
+ if (flag_set_p("Report", flags[i]))
+ print "#error Deprecated option with Report"
+ }
else
alias_data = "NULL, NULL, N_OPTS"
if (flag_set_p("Enum.*", flags[i])) {
diff --git a/gcc/opth-gen.awk b/gcc/opth-gen.awk
index 36f22b8..c2390de 100644
--- a/gcc/opth-gen.awk
+++ b/gcc/opth-gen.awk
@@ -493,6 +493,7 @@ for (i = 0; i < n_opts; i++) {
print " N_OPTS,"
print " OPT_SPECIAL_unknown,"
print " OPT_SPECIAL_ignore,"
+print " OPT_SPECIAL_deprecated,"
print " OPT_SPECIAL_program_name,"
print " OPT_SPECIAL_input_file"
print "};"
diff --git a/gcc/optinfo-emit-json.cc b/gcc/optinfo-emit-json.cc
index 2199d52..992960e 100644
--- a/gcc/optinfo-emit-json.cc
+++ b/gcc/optinfo-emit-json.cc
@@ -537,7 +537,7 @@ namespace selftest {
static void
test_building_json_from_dump_calls ()
{
- temp_dump_context tmp (true);
+ temp_dump_context tmp (true, MSG_NOTE);
dump_location_t loc;
dump_printf_loc (MSG_NOTE, loc, "test of tree: ");
dump_generic_expr (MSG_NOTE, TDF_SLIM, integer_zero_node);
diff --git a/gcc/optinfo.cc b/gcc/optinfo.cc
index 93de9d9..b858c3c 100644
--- a/gcc/optinfo.cc
+++ b/gcc/optinfo.cc
@@ -34,11 +34,11 @@ along with GCC; see the file COPYING3. If not see
#include "cgraph.h"
#include "selftest.h"
-/* optinfo_item's ctor. */
+/* optinfo_item's ctor. Takes ownership of TEXT. */
optinfo_item::optinfo_item (enum optinfo_item_kind kind, location_t location,
- char *text, bool owned)
-: m_kind (kind), m_location (location), m_text (text), m_owned (owned)
+ char *text)
+: m_kind (kind), m_location (location), m_text (text)
{
}
@@ -46,8 +46,7 @@ optinfo_item::optinfo_item (enum optinfo_item_kind kind, location_t location,
optinfo_item::~optinfo_item ()
{
- if (m_owned)
- free (m_text);
+ free (m_text);
}
/* Get a string from KIND. */
@@ -81,7 +80,17 @@ optinfo::~optinfo ()
delete item;
}
-/* Emit the optinfo to all of the active destinations. */
+/* Add ITEM to this optinfo. */
+
+void
+optinfo::add_item (optinfo_item *item)
+{
+ gcc_assert (item);
+ m_items.safe_push (item);
+}
+
+/* Emit the optinfo to all of the "non-immediate" destinations
+ (emission to "immediate" destinations is done by emit_item). */
void
optinfo::emit ()
@@ -103,120 +112,6 @@ optinfo::handle_dump_file_kind (dump_flags_t dump_kind)
m_kind = OPTINFO_KIND_NOTE;
}
-/* Append a string literal to this optinfo. */
-
-void
-optinfo::add_string (const char *str)
-{
- optinfo_item *item
- = new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
- const_cast <char *> (str), false);
- m_items.safe_push (item);
-}
-
-/* Append printf-formatted text to this optinfo. */
-
-void
-optinfo::add_printf (const char *format, ...)
-{
- va_list ap;
- va_start (ap, format);
- add_printf_va (format, ap);
- va_end (ap);
-}
-
-/* Append printf-formatted text to this optinfo. */
-
-void
-optinfo::add_printf_va (const char *format, va_list ap)
-{
- char *formatted_text = xvasprintf (format, ap);
- optinfo_item *item
- = new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
- formatted_text, true);
- m_items.safe_push (item);
-}
-
-/* Append a gimple statement to this optinfo, equivalent to
- print_gimple_stmt. */
-
-void
-optinfo::add_gimple_stmt (gimple *stmt, int spc, dump_flags_t dump_flags)
-{
- pretty_printer pp;
- pp_needs_newline (&pp) = true;
- pp_gimple_stmt_1 (&pp, stmt, spc, dump_flags);
- pp_newline (&pp);
-
- optinfo_item *item
- = new optinfo_item (OPTINFO_ITEM_KIND_GIMPLE, gimple_location (stmt),
- xstrdup (pp_formatted_text (&pp)), true);
- m_items.safe_push (item);
-}
-
-/* Append a gimple statement to this optinfo, equivalent to
- print_gimple_expr. */
-
-void
-optinfo::add_gimple_expr (gimple *stmt, int spc, dump_flags_t dump_flags)
-{
- dump_flags |= TDF_RHS_ONLY;
- pretty_printer pp;
- pp_needs_newline (&pp) = true;
- pp_gimple_stmt_1 (&pp, stmt, spc, dump_flags);
-
- optinfo_item *item
- = new optinfo_item (OPTINFO_ITEM_KIND_GIMPLE, gimple_location (stmt),
- xstrdup (pp_formatted_text (&pp)), true);
- m_items.safe_push (item);
-}
-
-/* Append a tree node to this optinfo, equivalent to print_generic_expr. */
-
-void
-optinfo::add_tree (tree node, dump_flags_t dump_flags)
-{
- pretty_printer pp;
- pp_needs_newline (&pp) = true;
- pp_translate_identifiers (&pp) = false;
- dump_generic_node (&pp, node, 0, dump_flags, false);
-
- location_t loc = UNKNOWN_LOCATION;
- if (EXPR_HAS_LOCATION (node))
- loc = EXPR_LOCATION (node);
-
- optinfo_item *item
- = new optinfo_item (OPTINFO_ITEM_KIND_TREE, loc,
- xstrdup (pp_formatted_text (&pp)), true);
- m_items.safe_push (item);
-}
-
-/* Append a symbol table node to this optinfo. */
-
-void
-optinfo::add_symtab_node (symtab_node *node)
-{
- location_t loc = DECL_SOURCE_LOCATION (node->decl);
- optinfo_item *item
- = new optinfo_item (OPTINFO_ITEM_KIND_SYMTAB_NODE, loc,
- xstrdup (node->dump_name ()), true);
- m_items.safe_push (item);
-}
-
-/* Append the decimal represenation of a wide_int_ref to this
- optinfo. */
-
-void
-optinfo::add_dec (const wide_int_ref &wi, signop sgn)
-{
- char buf[WIDE_INT_PRINT_BUFFER_SIZE];
- print_dec (wi, buf, sgn);
- optinfo_item *item
- = new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
- xstrdup (buf), true);
- m_items.safe_push (item);
-}
-
/* Should optinfo instances be created?
All creation of optinfos should be guarded by this predicate.
Return true if any optinfo destinations are active. */
diff --git a/gcc/optinfo.h b/gcc/optinfo.h
index c4cf8ade..8ac961c 100644
--- a/gcc/optinfo.h
+++ b/gcc/optinfo.h
@@ -92,6 +92,8 @@ enum optinfo_kind
extern const char *optinfo_kind_to_string (enum optinfo_kind kind);
+class dump_context;
+
/* A bundle of information describing part of an optimization. */
class optinfo
@@ -120,41 +122,14 @@ class optinfo
location_t get_location_t () const { return m_loc.get_location_t (); }
profile_count get_count () const { return m_loc.get_count (); }
+ void add_item (optinfo_item *item);
+
private:
void emit ();
/* Pre-canned ways of manipulating the optinfo, for use by friend class
dump_context. */
void handle_dump_file_kind (dump_flags_t);
- void add_string (const char *str);
- void add_printf (const char *format, ...) ATTRIBUTE_PRINTF_2;
- void add_printf_va (const char *format, va_list ap) ATTRIBUTE_PRINTF (2, 0);
- void add_gimple_stmt (gimple *stmt, int spc, dump_flags_t dump_flags);
- void add_gimple_expr (gimple *stmt, int spc, dump_flags_t dump_flags);
- void add_tree (tree node, dump_flags_t dump_flags);
- void add_symtab_node (symtab_node *node);
- void add_dec (const wide_int_ref &wi, signop sgn);
-
- template<unsigned int N, typename C>
- void add_poly_int (const poly_int<N, C> &value)
- {
- /* Compare with dump_dec (MSG_NOTE, ). */
-
- STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
- signop sgn = poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED;
-
- if (value.is_constant ())
- add_dec (value.coeffs[0], sgn);
- else
- {
- add_string ("[");
- for (unsigned int i = 0; i < N; ++i)
- {
- add_dec (value.coeffs[i], sgn);
- add_string (i == N - 1 ? "]" : ",");
- }
- }
- }
private:
dump_location_t m_loc;
@@ -179,7 +154,7 @@ class optinfo_item
{
public:
optinfo_item (enum optinfo_item_kind kind, location_t location,
- char *text, bool owned);
+ char *text);
~optinfo_item ();
enum optinfo_item_kind get_kind () const { return m_kind; }
@@ -191,9 +166,8 @@ class optinfo_item
enum optinfo_item_kind m_kind;
location_t m_location;
- /* The textual form of the item. */
+ /* The textual form of the item, owned by the item. */
char *m_text;
- bool m_owned;
};
#endif /* #ifndef GCC_OPTINFO_H */
diff --git a/gcc/opts-common.c b/gcc/opts-common.c
index 1135644..9158602 100644
--- a/gcc/opts-common.c
+++ b/gcc/opts-common.c
@@ -663,13 +663,13 @@ decode_cmdline_option (const char **argv, unsigned int lang_mask,
{
size_t new_opt_index = option->alias_target;
- if (new_opt_index == OPT_SPECIAL_ignore)
+ if (new_opt_index == OPT_SPECIAL_ignore
+ || new_opt_index == OPT_SPECIAL_deprecated)
{
gcc_assert (option->alias_arg == NULL);
gcc_assert (option->neg_alias_arg == NULL);
opt_index = new_opt_index;
arg = NULL;
- value = 1;
}
else
{
@@ -744,10 +744,6 @@ decode_cmdline_option (const char **argv, unsigned int lang_mask,
if (!option_ok_for_language (option, lang_mask))
errors |= CL_ERR_WRONG_LANG;
- /* Mark all deprecated options. */
- if (option->cl_deprecated)
- errors |= CL_ERR_DEPRECATED;
-
/* Convert the argument to lowercase if appropriate. */
if (arg && option->cl_tolower)
{
@@ -823,7 +819,8 @@ decode_cmdline_option (const char **argv, unsigned int lang_mask,
else
decoded->canonical_option[i] = NULL;
}
- if (opt_index != OPT_SPECIAL_unknown && opt_index != OPT_SPECIAL_ignore)
+ if (opt_index != OPT_SPECIAL_unknown && opt_index != OPT_SPECIAL_ignore
+ && opt_index != OPT_SPECIAL_deprecated)
{
generate_canonical_option (opt_index, arg, value, decoded);
if (separate_args > 1)
@@ -1001,6 +998,7 @@ prune_options (struct cl_decoded_option **decoded_options,
{
case OPT_SPECIAL_unknown:
case OPT_SPECIAL_ignore:
+ case OPT_SPECIAL_deprecated:
case OPT_SPECIAL_program_name:
case OPT_SPECIAL_input_file:
goto keep;
@@ -1268,6 +1266,7 @@ cmdline_handle_error (location_t loc, const struct cl_option *option,
unsigned int i;
char *s;
+ auto_diagnostic_group d;
if (e->unknown_error)
error_at (loc, e->unknown_error, arg);
else
@@ -1324,6 +1323,14 @@ read_cmdline_option (struct gcc_options *opts,
if (decoded->opt_index == OPT_SPECIAL_ignore)
return;
+ if (decoded->opt_index == OPT_SPECIAL_deprecated)
+ {
+ /* Warn only about positive ignored options. */
+ if (decoded->value)
+ warning_at (loc, 0, "switch %qs is no longer supported", opt);
+ return;
+ }
+
option = &cl_options[decoded->opt_index];
if (decoded->errors
@@ -1337,12 +1344,6 @@ read_cmdline_option (struct gcc_options *opts,
return;
}
- if (decoded->errors & CL_ERR_DEPRECATED)
- {
- warning_at (loc, 0, "deprecated command line option %qs", opt);
- return;
- }
-
gcc_assert (!decoded->errors);
if (!handle_option (opts, opts_set, decoded, lang_mask, DK_UNSPECIFIED,
@@ -1619,7 +1620,7 @@ control_warning_option (unsigned int opt_index, int kind, const char *arg,
arg = cl_options[opt_index].alias_arg;
opt_index = cl_options[opt_index].alias_target;
}
- if (opt_index == OPT_SPECIAL_ignore)
+ if (opt_index == OPT_SPECIAL_ignore || opt_index == OPT_SPECIAL_deprecated)
return;
if (dc)
diagnostic_classify_diagnostic (dc, opt_index, (diagnostic_t) kind, loc);
diff --git a/gcc/opts.c b/gcc/opts.c
index 17d9198..dc12c2e 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -1090,6 +1090,21 @@ wrap_help (const char *help,
while (remaining);
}
+/* Data structure used to print list of valid option values. */
+
+struct option_help_tuple
+{
+ option_help_tuple (int code, vec<const char *> values):
+ m_code (code), m_values (values)
+ {}
+
+ /* Code of an option. */
+ int m_code;
+
+ /* List of possible values. */
+ vec<const char *> m_values;
+};
+
/* Print help for a specific front-end, etc. */
static void
print_filtered_help (unsigned int include_flags,
@@ -1143,6 +1158,8 @@ print_filtered_help (unsigned int include_flags,
if (!opts->x_help_enum_printed)
opts->x_help_enum_printed = XCNEWVAR (char, cl_enums_count);
+ auto_vec<option_help_tuple> help_tuples;
+
for (i = 0; i < cl_options_count; i++)
{
const struct cl_option *option = cl_options + i;
@@ -1303,6 +1320,13 @@ print_filtered_help (unsigned int include_flags,
if (option->var_type == CLVC_ENUM
&& opts->x_help_enum_printed[option->var_enum] != 2)
opts->x_help_enum_printed[option->var_enum] = 1;
+ else
+ {
+ vec<const char *> option_values
+ = targetm_common.get_valid_option_values (i, NULL);
+ if (!option_values.is_empty ())
+ help_tuples.safe_push (option_help_tuple (i, option_values));
+ }
}
if (! found)
@@ -1366,6 +1390,15 @@ print_filtered_help (unsigned int include_flags,
printf ("\n\n");
opts->x_help_enum_printed[i] = 2;
}
+
+ for (unsigned i = 0; i < help_tuples.length (); i++)
+ {
+ const struct cl_option *option = cl_options + help_tuples[i].m_code;
+ printf (" Known valid arguments for %s option:\n ", option->opt_text);
+ for (unsigned j = 0; j < help_tuples[i].m_values.length (); j++)
+ printf (" %s", help_tuples[i].m_values[j]);
+ printf ("\n\n");
+ }
}
/* Display help for a specified type of option.
@@ -2175,6 +2208,14 @@ common_handle_option (struct gcc_options *opts,
dc->show_caret = value;
break;
+ case OPT_fdiagnostics_show_labels:
+ dc->show_labels_p = value;
+ break;
+
+ case OPT_fdiagnostics_show_line_numbers:
+ dc->show_line_numbers_p = value;
+ break;
+
case OPT_fdiagnostics_color_:
diagnostic_color_init (dc, value);
break;
diff --git a/gcc/opts.h b/gcc/opts.h
index 0091fe0..04efda5 100644
--- a/gcc/opts.h
+++ b/gcc/opts.h
@@ -106,8 +106,6 @@ struct cl_option
BOOL_BITFIELD cl_tolower : 1;
/* Report argument with -fverbose-asm */
BOOL_BITFIELD cl_report : 1;
- /* Deprecated option */
- BOOL_BITFIELD cl_deprecated: 1;
/* Argument is an unsigned integer with an optional byte suffix. */
BOOL_BITFIELD cl_byte_size: 1;
/* Offset of field for this option in struct gcc_options, or
@@ -219,7 +217,6 @@ extern const unsigned int cl_enums_count;
#define CL_ERR_NEGATIVE (1 << 6) /* Negative form of option
not permitted (together
with OPT_SPECIAL_unknown). */
-#define CL_ERR_DEPRECATED (1 << 7) /* Deprecated option. */
/* Structure describing the result of decoding an option. */
diff --git a/gcc/params.def b/gcc/params.def
index 6bedeb5..9f06973 100644
--- a/gcc/params.def
+++ b/gcc/params.def
@@ -393,10 +393,15 @@ DEFPARAM(PARAM_SMS_LOOP_AVERAGE_COUNT_THRESHOLD,
"A threshold on the average loop count considered by the swing modulo scheduler.",
0, 0, 0)
+DEFPARAM(HOT_BB_COUNT_FRACTION,
+ "hot-bb-count-fraction",
+ "Select fraction of the maximal count of repetitions of basic block in program given basic "
+ "block needs to have to be considered hot (used in non-LTO mode)",
+ 10000, 0, 0)
DEFPARAM(HOT_BB_COUNT_WS_PERMILLE,
"hot-bb-count-ws-permille",
"A basic block profile count is considered hot if it contributes to "
- "the given permillage of the entire profiled execution.",
+ "the given permillage of the entire profiled execution (used in LTO mode).",
999, 0, 1000)
DEFPARAM(HOT_BB_FREQUENCY_FRACTION,
"hot-bb-frequency-fraction",
@@ -415,8 +420,8 @@ DEFPARAM (PARAM_ALIGN_THRESHOLD,
DEFPARAM (PARAM_ALIGN_LOOP_ITERATIONS,
"align-loop-iterations",
- "Loops iterating at least selected number of iterations will get loop alignment..",
- 4, 0, 0)
+ "Loops iterating at least selected number of iterations will get "
+ "loop alignment.", 4, 0, 0)
/* For guessed profiles, the loops having unknown number of iterations
are predicted to iterate relatively few (10) times at average.
@@ -828,7 +833,7 @@ DEFPARAM (PARAM_LOOP_INTERCHANGE_MAX_NUM_STMTS,
DEFPARAM (PARAM_LOOP_INTERCHANGE_STRIDE_RATIO,
"loop-interchange-stride-ratio",
- "The minimum stride ratio for loop interchange to be profitable",
+ "The minimum stride ratio for loop interchange to be profitable.",
2, 0, 0)
/* Whether we should use canonical types rather than deep "structural"
@@ -847,15 +852,15 @@ DEFPARAM (PARAM_MAX_PARTIAL_ANTIC_LENGTH,
"Maximum length of partial antic set when performing tree pre optimization.",
100, 0, 0)
-/* The following is used as a stop-gap limit for cases where really huge
- SCCs blow up memory and compile-time use too much. If we hit this limit,
- SCCVN and such FRE and PRE will be not done at all for the current
- function. */
+/* The following is used as a stop-gap limit for cases where really deep
+ loop nests cause compile-time to blow up. If we hit this limit,
+ FRE and PRE will value-number outer loops (but the outermost) in a
+ loop nest non-optimistically. */
-DEFPARAM (PARAM_SCCVN_MAX_SCC_SIZE,
- "sccvn-max-scc-size",
- "Maximum size of a SCC before SCCVN stops processing a function.",
- 10000, 10, 0)
+DEFPARAM (PARAM_RPO_VN_MAX_LOOP_DEPTH,
+ "rpo-vn-max-loop-depth",
+ "Maximum depth of a loop nest to fully value-number optimistically.",
+ 7, 2, 0)
/* The following is used as a stop-gap limit for cases where really huge
functions blow up compile-time use too much. It limits the number of
@@ -906,32 +911,32 @@ DEFPARAM (PARAM_SWITCH_CONVERSION_BRANCH_RATIO,
DEFPARAM (PARAM_LOOP_BLOCK_TILE_SIZE,
"loop-block-tile-size",
- "size of tiles for loop blocking.",
+ "Size of tiles for loop blocking.",
51, 0, 0)
/* Maximal number of parameters that we allow in a SCoP. */
DEFPARAM (PARAM_GRAPHITE_MAX_NB_SCOP_PARAMS,
"graphite-max-nb-scop-params",
- "maximum number of parameters in a SCoP.",
+ "Maximum number of parameters in a SCoP.",
10, 0, 0)
/* Maximal number of array references in a scop. */
DEFPARAM (PARAM_GRAPHITE_MAX_ARRAYS_PER_SCOP,
"graphite-max-arrays-per-scop",
- "maximum number of arrays per scop.",
+ "Maximum number of arrays per scop.",
100, 0, 0)
DEFPARAM (PARAM_MAX_ISL_OPERATIONS,
"max-isl-operations",
- "maximum number of isl operations, 0 means unlimited",
+ "Maximum number of isl operations, 0 means unlimited.",
350000, 0, 0)
/* For testsuite purposes allow to check for codegen error handling. */
DEFPARAM (PARAM_GRAPHITE_ALLOW_CODEGEN_ERRORS,
"graphite-allow-codegen-errors",
- "whether codegen errors should be ICEs when -fchecking.",
+ "Whether codegen errors should be ICEs when -fchecking.",
0, 0, 1)
/* Avoid data dependence analysis on very large loops. */
@@ -951,23 +956,23 @@ DEFPARAM (PARAM_LOOP_INVARIANT_MAX_BBS_IN_LOOP,
to look up for profile data. Otherwise, use a more stable
external id based on assembler name and source location. */
DEFPARAM (PARAM_PROFILE_FUNC_INTERNAL_ID,
- "profile-func-internal-id",
- "use internal function id in profile lookup.",
- 0, 0, 1)
+ "profile-func-internal-id",
+ "Use internal function id in profile lookup.",
+ 0, 0, 1)
/* When the parameter is 1, track the most frequent N target
addresses in indirect-call profile. This disables
indirect_call_profiler_v2 which tracks single target. */
DEFPARAM (PARAM_INDIR_CALL_TOPN_PROFILE,
- "indir-call-topn-profile",
- "track topn target addresses in indirect-call profile.",
- 0, 0, 1)
+ "indir-call-topn-profile",
+ "Track top N target addresses in indirect-call profile.",
+ 0, 0, 1)
/* Avoid SLP vectorization of large basic blocks. */
DEFPARAM (PARAM_SLP_MAX_INSNS_IN_BB,
- "slp-max-insns-in-bb",
- "Maximum number of instructions in basic block to be considered for SLP vectorization.",
- 1000, 0, 0)
+ "slp-max-insns-in-bb",
+ "Maximum number of instructions in basic block to be considered for "
+ "SLP vectorization.", 1000, 0, 0)
DEFPARAM (PARAM_MIN_INSN_TO_PREFETCH_RATIO,
"min-insn-to-prefetch-ratio",
@@ -1053,19 +1058,19 @@ DEFPARAM (PARAM_IPA_CP_VALUE_LIST_SIZE,
DEFPARAM (PARAM_IPA_CP_EVAL_THRESHOLD,
"ipa-cp-eval-threshold",
"Threshold ipa-cp opportunity evaluation that is still considered "
- "beneficial to clone..",
+ "beneficial to clone.",
500, 0, 0)
DEFPARAM (PARAM_IPA_CP_RECURSION_PENALTY,
"ipa-cp-recursion-penalty",
"Percentage penalty the recursive functions will receive when they "
- "are evaluated for cloning..",
+ "are evaluated for cloning.",
40, 0, 100)
DEFPARAM (PARAM_IPA_CP_SINGLE_CALL_PENALTY,
"ipa-cp-single-call-penalty",
"Percentage penalty functions containing a single call to another "
- "function will receive when they are evaluated for cloning..",
+ "function will receive when they are evaluated for cloning.",
15, 0, 100)
DEFPARAM (PARAM_IPA_MAX_AGG_ITEMS,
@@ -1077,13 +1082,13 @@ DEFPARAM (PARAM_IPA_MAX_AGG_ITEMS,
DEFPARAM (PARAM_IPA_CP_LOOP_HINT_BONUS,
"ipa-cp-loop-hint-bonus",
"Compile-time bonus IPA-CP assigns to candidates which make loop "
- "bounds or strides known..",
+ "bounds or strides known.",
64, 0, 0)
DEFPARAM (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS,
"ipa-cp-array-index-hint-bonus",
"Compile-time bonus IPA-CP assigns to candidates which make an array "
- "index known..",
+ "index known.",
48, 0, 0)
DEFPARAM (PARAM_IPA_MAX_AA_STEPS,
@@ -1143,7 +1148,7 @@ DEFPARAM (PARAM_ALLOW_STORE_DATA_RACES,
DEFPARAM (PARAM_TREE_REASSOC_WIDTH,
"tree-reassoc-width",
"Set the maximum number of instructions executed in parallel in "
- "reassociated tree. If 0, use the target dependent heuristic..",
+ "reassociated tree. If 0, use the target dependent heuristic.",
0, 0, 0)
DEFPARAM (PARAM_MAX_TAIL_MERGE_COMPARISONS,
@@ -1320,18 +1325,18 @@ DEFPARAM (PARAM_MAX_RTL_IF_CONVERSION_UNPREDICTABLE_COST,
DEFPARAM (PARAM_HSA_GEN_DEBUG_STORES,
"hsa-gen-debug-stores",
- "Level of hsa debug stores verbosity",
+ "Level of hsa debug stores verbosity.",
0, 0, 1)
DEFPARAM (PARAM_MAX_SPECULATIVE_DEVIRT_MAYDEFS,
"max-speculative-devirt-maydefs",
"Maximum number of may-defs visited when devirtualizing "
- "speculatively", 50, 0, 0)
+ "speculatively.", 50, 0, 0)
DEFPARAM (PARAM_MAX_VRP_SWITCH_ASSERTIONS,
"max-vrp-switch-assertions",
"Maximum number of assertions to add along the default "
- "edge of a switch statement during VRP",
+ "edge of a switch statement during VRP.",
10, 0, 0)
DEFPARAM (PARAM_VECT_EPILOGUES_NOMASK,
diff --git a/gcc/passes.def b/gcc/passes.def
index 2a8fbc2..7f4b347 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -98,7 +98,7 @@ along with GCC; see the file COPYING3. If not see
early optimizations again. It is thus good idea to do this
late. */
NEXT_PASS (pass_split_functions);
- NEXT_PASS (pass_strip_predict_hints);
+ NEXT_PASS (pass_strip_predict_hints, true /* early_p */);
POP_INSERT_PASSES ()
NEXT_PASS (pass_release_ssa_names);
NEXT_PASS (pass_rebuild_cgraph_edges);
@@ -183,7 +183,7 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_remove_cgraph_callee_edges);
/* Initial scalar cleanups before alias computation.
They ensure memory accesses are not indirect wherever possible. */
- NEXT_PASS (pass_strip_predict_hints);
+ NEXT_PASS (pass_strip_predict_hints, false /* early_p */);
NEXT_PASS (pass_ccp, true /* nonzero_p */);
NEXT_PASS (pass_post_ipa_warn);
/* After CCP we rewrite no longer addressed locals into SSA
@@ -348,7 +348,7 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_all_optimizations_g);
PUSH_INSERT_PASSES_WITHIN (pass_all_optimizations_g)
NEXT_PASS (pass_remove_cgraph_callee_edges);
- NEXT_PASS (pass_strip_predict_hints);
+ NEXT_PASS (pass_strip_predict_hints, false /* early_p */);
/* Lower remaining pieces of GIMPLE. */
NEXT_PASS (pass_lower_complex);
NEXT_PASS (pass_lower_vector_ssa);
diff --git a/gcc/postreload-gcse.c b/gcc/postreload-gcse.c
index 152dd6a..b569931 100644
--- a/gcc/postreload-gcse.c
+++ b/gcc/postreload-gcse.c
@@ -791,15 +791,18 @@ record_opr_changes (rtx_insn *insn)
record_last_reg_set_info_regno (insn, regno);
for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
- if (GET_CODE (XEXP (link, 0)) == CLOBBER)
- {
- x = XEXP (XEXP (link, 0), 0);
- if (REG_P (x))
- {
- gcc_assert (HARD_REGISTER_P (x));
- record_last_reg_set_info (insn, x);
- }
- }
+ {
+ gcc_assert (GET_CODE (XEXP (link, 0)) != CLOBBER_HIGH);
+ if (GET_CODE (XEXP (link, 0)) == CLOBBER)
+ {
+ x = XEXP (XEXP (link, 0), 0);
+ if (REG_P (x))
+ {
+ gcc_assert (HARD_REGISTER_P (x));
+ record_last_reg_set_info (insn, x);
+ }
+ }
+ }
if (! RTL_CONST_OR_PURE_CALL_P (insn))
record_last_mem_set_info (insn);
@@ -1158,7 +1161,7 @@ eliminate_partially_redundant_load (basic_block bb, rtx_insn *insn,
|| (optimize_bb_for_size_p (bb) && npred_ok > 1)
/* If we don't have profile information we cannot tell if splitting
a critical edge is profitable or not so don't do it. */
- || ((! profile_info || profile_status_for_fn (cfun) != PROFILE_READ
+ || ((!profile_info || profile_status_for_fn (cfun) != PROFILE_READ
|| targetm.cannot_modify_jumps_p ())
&& critical_edge_split))
goto cleanup;
diff --git a/gcc/postreload.c b/gcc/postreload.c
index 0638709..56cb14d 100644
--- a/gcc/postreload.c
+++ b/gcc/postreload.c
@@ -133,6 +133,8 @@ reload_cse_simplify (rtx_insn *insn, rtx testreg)
for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
{
rtx part = XVECEXP (body, 0, i);
+ /* asms can only have full clobbers, not clobber_highs. */
+ gcc_assert (GET_CODE (part) != CLOBBER_HIGH);
if (GET_CODE (part) == CLOBBER && REG_P (XEXP (part, 0)))
cselib_invalidate_rtx (XEXP (part, 0));
}
@@ -156,6 +158,7 @@ reload_cse_simplify (rtx_insn *insn, rtx testreg)
}
}
else if (GET_CODE (part) != CLOBBER
+ && GET_CODE (part) != CLOBBER_HIGH
&& GET_CODE (part) != USE)
break;
}
@@ -667,7 +670,8 @@ struct reg_use
STORE_RUID is always meaningful if we only want to use a value in a
register in a different place: it denotes the next insn in the insn
stream (i.e. the last encountered) that sets or clobbers the register.
- REAL_STORE_RUID is similar, but clobbers are ignored when updating it. */
+ REAL_STORE_RUID is similar, but clobbers are ignored when updating it.
+ EXPR is the expression used when storing the register. */
static struct
{
struct reg_use reg_use[RELOAD_COMBINE_MAX_USES];
@@ -677,6 +681,7 @@ static struct
int real_store_ruid;
int use_ruid;
bool all_offsets_match;
+ rtx expr;
} reg_state[FIRST_PSEUDO_REGISTER];
/* Reverse linear uid. This is increased in reload_combine while scanning
@@ -1341,6 +1346,10 @@ reload_combine (void)
{
rtx setuse = XEXP (link, 0);
rtx usage_rtx = XEXP (setuse, 0);
+ /* We could support CLOBBER_HIGH and treat it in the same way as
+ HARD_REGNO_CALL_PART_CLOBBERED, but no port needs that yet. */
+ gcc_assert (GET_CODE (setuse) != CLOBBER_HIGH);
+
if ((GET_CODE (setuse) == USE || GET_CODE (setuse) == CLOBBER)
&& REG_P (usage_rtx))
{
@@ -1516,6 +1525,10 @@ reload_combine_note_use (rtx *xp, rtx_insn *insn, int ruid, rtx containing_mem)
}
break;
+ case CLOBBER_HIGH:
+ gcc_assert (REG_P (SET_DEST (x)));
+ return;
+
case PLUS:
/* We are interested in (plus (reg) (const_int)) . */
if (!REG_P (XEXP (x, 0))
@@ -2135,6 +2148,9 @@ reload_cse_move2add (rtx_insn *first)
{
rtx setuse = XEXP (link, 0);
rtx usage_rtx = XEXP (setuse, 0);
+ /* CALL_INSN_FUNCTION_USAGEs can only have full clobbers, not
+ clobber_highs. */
+ gcc_assert (GET_CODE (setuse) != CLOBBER_HIGH);
if (GET_CODE (setuse) == CLOBBER
&& REG_P (usage_rtx))
{
@@ -2297,6 +2313,13 @@ move2add_note_store (rtx dst, const_rtx set, void *data)
move2add_record_mode (dst);
}
+ else if (GET_CODE (set) == CLOBBER_HIGH)
+ {
+ /* Only invalidate if actually clobbered. */
+ if (reg_mode[regno] == BLKmode
+ || reg_is_clobbered_by_clobber_high (regno, reg_mode[regno], dst))
+ goto invalidate;
+ }
else
{
invalidate:
diff --git a/gcc/predict.c b/gcc/predict.c
index 65e088f..ab2dc8e 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -92,6 +92,7 @@ static void predict_paths_leading_to_edge (edge, enum br_predictor,
enum prediction,
struct loop *in_loop = NULL);
static bool can_predict_insn_p (const rtx_insn *);
+static HOST_WIDE_INT get_predictor_value (br_predictor, HOST_WIDE_INT);
/* Information we hold about each branch predictor.
Filled using information from predict.def. */
@@ -128,12 +129,13 @@ static gcov_type min_count = -1;
gcov_type
get_hot_bb_threshold ()
{
- gcov_working_set_t *ws;
if (min_count == -1)
{
- ws = find_working_set (PARAM_VALUE (HOT_BB_COUNT_WS_PERMILLE));
- gcc_assert (ws);
- min_count = ws->min_counter;
+ min_count
+ = profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION);
+ if (dump_file)
+ fprintf (dump_file, "Setting hotness threshold to %" PRId64 ".\n",
+ min_count);
}
return min_count;
}
@@ -734,7 +736,7 @@ dump_prediction (FILE *file, enum br_predictor predictor, int probability,
else
edge_info_str[0] = '\0';
- fprintf (file, " %s heuristics%s%s: %.1f%%",
+ fprintf (file, " %s heuristics%s%s: %.2f%%",
predictor_info[predictor].name,
edge_info_str, reason_messages[reason],
probability * 100.0 / REG_BR_PROB_BASE);
@@ -826,11 +828,14 @@ unlikely_executed_bb_p (basic_block bb)
/* We can not predict the probabilities of outgoing edges of bb. Set them
evenly and hope for the best. If UNLIKELY_EDGES is not null, distribute
even probability for all edges not mentioned in the set. These edges
- are given PROB_VERY_UNLIKELY probability. */
+ are given PROB_VERY_UNLIKELY probability. Similarly for LIKELY_EDGES,
+ if we have exactly one likely edge, make the other edges predicted
+ as not probable. */
static void
set_even_probabilities (basic_block bb,
- hash_set<edge> *unlikely_edges = NULL)
+ hash_set<edge> *unlikely_edges = NULL,
+ hash_set<edge_prediction *> *likely_edges = NULL)
{
unsigned nedges = 0, unlikely_count = 0;
edge e = NULL;
@@ -842,7 +847,7 @@ set_even_probabilities (basic_block bb,
all -= e->probability;
else if (!unlikely_executed_edge_p (e))
{
- nedges ++;
+ nedges++;
if (unlikely_edges != NULL && unlikely_edges->contains (e))
{
all -= profile_probability::very_unlikely ();
@@ -851,26 +856,54 @@ set_even_probabilities (basic_block bb,
}
/* Make the distribution even if all edges are unlikely. */
+ unsigned likely_count = likely_edges ? likely_edges->elements () : 0;
if (unlikely_count == nedges)
{
unlikely_edges = NULL;
unlikely_count = 0;
}
- unsigned c = nedges - unlikely_count;
-
- FOR_EACH_EDGE (e, ei, bb->succs)
- if (e->probability.initialized_p ())
- ;
- else if (!unlikely_executed_edge_p (e))
- {
- if (unlikely_edges != NULL && unlikely_edges->contains (e))
- e->probability = profile_probability::very_unlikely ();
+ /* If we have one likely edge, then use its probability and distribute
+ remaining probabilities as even. */
+ if (likely_count == 1)
+ {
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (e->probability.initialized_p ())
+ ;
+ else if (!unlikely_executed_edge_p (e))
+ {
+ edge_prediction *prediction = *likely_edges->begin ();
+ int p = prediction->ep_probability;
+ profile_probability prob
+ = profile_probability::from_reg_br_prob_base (p);
+ profile_probability remainder = prob.invert ();
+
+ if (prediction->ep_edge == e)
+ e->probability = prob;
+ else
+ e->probability = remainder.apply_scale (1, nedges - 1);
+ }
else
- e->probability = all.apply_scale (1, c).guessed ();
- }
- else
- e->probability = profile_probability::never ();
+ e->probability = profile_probability::never ();
+ }
+ else
+ {
+ /* Make all unlikely edges unlikely and the rest will have even
+ probability. */
+ unsigned scale = nedges - unlikely_count;
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (e->probability.initialized_p ())
+ ;
+ else if (!unlikely_executed_edge_p (e))
+ {
+ if (unlikely_edges != NULL && unlikely_edges->contains (e))
+ e->probability = profile_probability::very_unlikely ();
+ else
+ e->probability = all.apply_scale (1, scale);
+ }
+ else
+ e->probability = profile_probability::never ();
+ }
}
/* Add REG_BR_PROB note to JUMP with PROB. */
@@ -1174,6 +1207,7 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
if (nedges != 2)
{
hash_set<edge> unlikely_edges (4);
+ hash_set<edge_prediction *> likely_edges (4);
/* Identify all edges that have a probability close to very unlikely.
Doing the approach for very unlikely doesn't worth for doing as
@@ -1181,11 +1215,16 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
edge_prediction **preds = bb_predictions->get (bb);
if (preds)
for (pred = *preds; pred; pred = pred->ep_next)
- if (pred->ep_probability <= PROB_VERY_UNLIKELY)
- unlikely_edges.add (pred->ep_edge);
+ {
+ if (pred->ep_probability <= PROB_VERY_UNLIKELY)
+ unlikely_edges.add (pred->ep_edge);
+ if (pred->ep_probability >= PROB_VERY_LIKELY
+ || pred->ep_predictor == PRED_BUILTIN_EXPECT)
+ likely_edges.add (pred);
+ }
if (!dry_run)
- set_even_probabilities (bb, &unlikely_edges);
+ set_even_probabilities (bb, &unlikely_edges, &likely_edges);
clear_bb_predictions (bb);
if (dump_file)
{
@@ -2262,18 +2301,21 @@ guess_outgoing_edge_probabilities (basic_block bb)
combine_predictions_for_insn (BB_END (bb), bb);
}
-static tree expr_expected_value (tree, bitmap, enum br_predictor *predictor);
+static tree expr_expected_value (tree, bitmap, enum br_predictor *predictor,
+ HOST_WIDE_INT *probability);
/* Helper function for expr_expected_value. */
static tree
expr_expected_value_1 (tree type, tree op0, enum tree_code code,
- tree op1, bitmap visited, enum br_predictor *predictor)
+ tree op1, bitmap visited, enum br_predictor *predictor,
+ HOST_WIDE_INT *probability)
{
gimple *def;
- if (predictor)
- *predictor = PRED_UNCONDITIONAL;
+ /* Reset returned probability value. */
+ *probability = -1;
+ *predictor = PRED_UNCONDITIONAL;
if (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS)
{
@@ -2292,8 +2334,7 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code,
{
/* Assume that any given atomic operation has low contention,
and thus the compare-and-swap operation succeeds. */
- if (predictor)
- *predictor = PRED_COMPARE_AND_SWAP;
+ *predictor = PRED_COMPARE_AND_SWAP;
return build_one_cst (TREE_TYPE (op0));
}
}
@@ -2329,12 +2370,17 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code,
if (arg == PHI_RESULT (def))
continue;
- new_val = expr_expected_value (arg, visited, &predictor2);
+ HOST_WIDE_INT probability2;
+ new_val = expr_expected_value (arg, visited, &predictor2,
+ &probability2);
/* It is difficult to combine value predictors. Simply assume
that later predictor is weaker and take its prediction. */
- if (predictor && *predictor < predictor2)
- *predictor = predictor2;
+ if (*predictor < predictor2)
+ {
+ *predictor = predictor2;
+ *probability = probability2;
+ }
if (!new_val)
return NULL;
if (!val)
@@ -2353,7 +2399,7 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code,
gimple_assign_rhs1 (def),
gimple_assign_rhs_code (def),
gimple_assign_rhs2 (def),
- visited, predictor);
+ visited, predictor, probability);
}
if (is_gimple_call (def))
@@ -2368,18 +2414,26 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code,
tree val = gimple_call_arg (def, 0);
if (TREE_CONSTANT (val))
return val;
- if (predictor)
- {
- tree val2 = gimple_call_arg (def, 2);
- gcc_assert (TREE_CODE (val2) == INTEGER_CST
- && tree_fits_uhwi_p (val2)
- && tree_to_uhwi (val2) < END_PREDICTORS);
- *predictor = (enum br_predictor) tree_to_uhwi (val2);
- }
+ tree val2 = gimple_call_arg (def, 2);
+ gcc_assert (TREE_CODE (val2) == INTEGER_CST
+ && tree_fits_uhwi_p (val2)
+ && tree_to_uhwi (val2) < END_PREDICTORS);
+ *predictor = (enum br_predictor) tree_to_uhwi (val2);
+ if (*predictor == PRED_BUILTIN_EXPECT)
+ *probability
+ = HITRATE (PARAM_VALUE (BUILTIN_EXPECT_PROBABILITY));
return gimple_call_arg (def, 1);
}
return NULL;
}
+
+ if (DECL_IS_MALLOC (decl) || DECL_IS_OPERATOR_NEW (decl))
+ {
+ if (predictor)
+ *predictor = PRED_MALLOC_NONNULL;
+ return boolean_true_node;
+ }
+
if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
switch (DECL_FUNCTION_CODE (decl))
{
@@ -2391,8 +2445,35 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code,
val = gimple_call_arg (def, 0);
if (TREE_CONSTANT (val))
return val;
- if (predictor)
- *predictor = PRED_BUILTIN_EXPECT;
+ *predictor = PRED_BUILTIN_EXPECT;
+ *probability
+ = HITRATE (PARAM_VALUE (BUILTIN_EXPECT_PROBABILITY));
+ return gimple_call_arg (def, 1);
+ }
+ case BUILT_IN_EXPECT_WITH_PROBABILITY:
+ {
+ tree val;
+ if (gimple_call_num_args (def) != 3)
+ return NULL;
+ val = gimple_call_arg (def, 0);
+ if (TREE_CONSTANT (val))
+ return val;
+ /* Compute final probability as:
+ probability * REG_BR_PROB_BASE. */
+ tree prob = gimple_call_arg (def, 2);
+ tree t = TREE_TYPE (prob);
+ tree base = build_int_cst (integer_type_node,
+ REG_BR_PROB_BASE);
+ base = build_real_from_int_cst (t, base);
+ tree r = fold_build2_initializer_loc (UNKNOWN_LOCATION,
+ MULT_EXPR, t, prob, base);
+ HOST_WIDE_INT probi
+ = real_to_integer (TREE_REAL_CST_PTR (r));
+ if (probi >= 0 && probi <= REG_BR_PROB_BASE)
+ {
+ *predictor = PRED_BUILTIN_EXPECT_WITH_PROBABILITY;
+ *probability = probi;
+ }
return gimple_call_arg (def, 1);
}
@@ -2411,8 +2492,11 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code,
case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16:
/* Assume that any given atomic operation has low contention,
and thus the compare-and-swap operation succeeds. */
+ *predictor = PRED_COMPARE_AND_SWAP;
+ return boolean_true_node;
+ case BUILT_IN_REALLOC:
if (predictor)
- *predictor = PRED_COMPARE_AND_SWAP;
+ *predictor = PRED_MALLOC_NONNULL;
return boolean_true_node;
default:
break;
@@ -2426,23 +2510,37 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code,
{
tree res;
enum br_predictor predictor2;
- op0 = expr_expected_value (op0, visited, predictor);
+ HOST_WIDE_INT probability2;
+ op0 = expr_expected_value (op0, visited, predictor, probability);
if (!op0)
return NULL;
- op1 = expr_expected_value (op1, visited, &predictor2);
- if (predictor && *predictor < predictor2)
- *predictor = predictor2;
+ op1 = expr_expected_value (op1, visited, &predictor2, &probability2);
if (!op1)
return NULL;
res = fold_build2 (code, type, op0, op1);
- if (TREE_CONSTANT (res))
- return res;
+ if (TREE_CODE (res) == INTEGER_CST
+ && TREE_CODE (op0) == INTEGER_CST
+ && TREE_CODE (op1) == INTEGER_CST)
+ {
+ /* Combine binary predictions. */
+ if (*probability != -1 || probability2 != -1)
+ {
+ HOST_WIDE_INT p1 = get_predictor_value (*predictor, *probability);
+ HOST_WIDE_INT p2 = get_predictor_value (predictor2, probability2);
+ *probability = RDIV (p1 * p2, REG_BR_PROB_BASE);
+ }
+
+ if (*predictor < predictor2)
+ *predictor = predictor2;
+
+ return res;
+ }
return NULL;
}
if (get_gimple_rhs_class (code) == GIMPLE_UNARY_RHS)
{
tree res;
- op0 = expr_expected_value (op0, visited, predictor);
+ op0 = expr_expected_value (op0, visited, predictor, probability);
if (!op0)
return NULL;
res = fold_build1 (code, type, op0);
@@ -2463,23 +2561,44 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code,
static tree
expr_expected_value (tree expr, bitmap visited,
- enum br_predictor *predictor)
+ enum br_predictor *predictor,
+ HOST_WIDE_INT *probability)
{
enum tree_code code;
tree op0, op1;
if (TREE_CONSTANT (expr))
{
- if (predictor)
- *predictor = PRED_UNCONDITIONAL;
+ *predictor = PRED_UNCONDITIONAL;
+ *probability = -1;
return expr;
}
extract_ops_from_tree (expr, &code, &op0, &op1);
return expr_expected_value_1 (TREE_TYPE (expr),
- op0, code, op1, visited, predictor);
+ op0, code, op1, visited, predictor,
+ probability);
}
+
+/* Return probability of a PREDICTOR. If the predictor has variable
+ probability return passed PROBABILITY. */
+
+static HOST_WIDE_INT
+get_predictor_value (br_predictor predictor, HOST_WIDE_INT probability)
+{
+ switch (predictor)
+ {
+ case PRED_BUILTIN_EXPECT:
+ case PRED_BUILTIN_EXPECT_WITH_PROBABILITY:
+ gcc_assert (probability != -1);
+ return probability;
+ default:
+ gcc_assert (probability == -1);
+ return predictor_info[(int) predictor].hitrate;
+ }
+}
+
/* Predict using opcode of the last statement in basic block. */
static void
tree_predict_by_opcode (basic_block bb)
@@ -2492,8 +2611,32 @@ tree_predict_by_opcode (basic_block bb)
enum tree_code cmp;
edge_iterator ei;
enum br_predictor predictor;
+ HOST_WIDE_INT probability;
- if (!stmt || gimple_code (stmt) != GIMPLE_COND)
+ if (!stmt)
+ return;
+
+ if (gswitch *sw = dyn_cast <gswitch *> (stmt))
+ {
+ tree index = gimple_switch_index (sw);
+ tree val = expr_expected_value (index, auto_bitmap (),
+ &predictor, &probability);
+ if (val && TREE_CODE (val) == INTEGER_CST)
+ {
+ edge e = find_taken_edge_switch_expr (sw, val);
+ if (predictor == PRED_BUILTIN_EXPECT)
+ {
+ int percent = PARAM_VALUE (BUILTIN_EXPECT_PROBABILITY);
+ gcc_assert (percent >= 0 && percent <= 100);
+ predict_edge (e, PRED_BUILTIN_EXPECT,
+ HITRATE (percent));
+ }
+ else
+ predict_edge_def (e, predictor, TAKEN);
+ }
+ }
+
+ if (gimple_code (stmt) != GIMPLE_COND)
return;
FOR_EACH_EDGE (then_edge, ei, bb->succs)
if (then_edge->flags & EDGE_TRUE_VALUE)
@@ -2503,21 +2646,13 @@ tree_predict_by_opcode (basic_block bb)
cmp = gimple_cond_code (stmt);
type = TREE_TYPE (op0);
val = expr_expected_value_1 (boolean_type_node, op0, cmp, op1, auto_bitmap (),
- &predictor);
+ &predictor, &probability);
if (val && TREE_CODE (val) == INTEGER_CST)
{
- if (predictor == PRED_BUILTIN_EXPECT)
- {
- int percent = PARAM_VALUE (BUILTIN_EXPECT_PROBABILITY);
-
- gcc_assert (percent >= 0 && percent <= 100);
- if (integer_zerop (val))
- percent = 100 - percent;
- predict_edge (then_edge, PRED_BUILTIN_EXPECT, HITRATE (percent));
- }
- else
- predict_edge_def (then_edge, predictor,
- integer_zerop (val) ? NOT_TAKEN : TAKEN);
+ HOST_WIDE_INT prob = get_predictor_value (predictor, probability);
+ if (integer_zerop (val))
+ prob = REG_BR_PROB_BASE - prob;
+ predict_edge (then_edge, predictor, prob);
}
/* Try "pointer heuristic."
A comparison ptr == 0 is predicted as false.
@@ -3872,38 +4007,28 @@ make_pass_profile (gcc::context *ctxt)
return new pass_profile (ctxt);
}
-namespace {
+/* Return true when PRED predictor should be removed after early
+ tree passes. Most of the predictors are beneficial to survive
+ as early inlining can also distribute then into caller's bodies. */
-const pass_data pass_data_strip_predict_hints =
-{
- GIMPLE_PASS, /* type */
- "*strip_predict_hints", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- TV_BRANCH_PROB, /* tv_id */
- PROP_cfg, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0, /* todo_flags_finish */
-};
-
-class pass_strip_predict_hints : public gimple_opt_pass
+static bool
+strip_predictor_early (enum br_predictor pred)
{
-public:
- pass_strip_predict_hints (gcc::context *ctxt)
- : gimple_opt_pass (pass_data_strip_predict_hints, ctxt)
- {}
-
- /* opt_pass methods: */
- opt_pass * clone () { return new pass_strip_predict_hints (m_ctxt); }
- virtual unsigned int execute (function *);
-
-}; // class pass_strip_predict_hints
+ switch (pred)
+ {
+ case PRED_TREE_EARLY_RETURN:
+ return true;
+ default:
+ return false;
+ }
+}
/* Get rid of all builtin_expect calls and GIMPLE_PREDICT statements
- we no longer need. */
+ we no longer need. EARLY is set to true when called from early
+ optimizations. */
+
unsigned int
-pass_strip_predict_hints::execute (function *fun)
+strip_predict_hints (function *fun, bool early)
{
basic_block bb;
gimple *ass_stmt;
@@ -3919,20 +4044,28 @@ pass_strip_predict_hints::execute (function *fun)
if (gimple_code (stmt) == GIMPLE_PREDICT)
{
- gsi_remove (&bi, true);
- changed = true;
- continue;
+ if (!early
+ || strip_predictor_early (gimple_predict_predictor (stmt)))
+ {
+ gsi_remove (&bi, true);
+ changed = true;
+ continue;
+ }
}
else if (is_gimple_call (stmt))
{
tree fndecl = gimple_call_fndecl (stmt);
- if ((fndecl
- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT
- && gimple_call_num_args (stmt) == 2)
- || (gimple_call_internal_p (stmt)
- && gimple_call_internal_fn (stmt) == IFN_BUILTIN_EXPECT))
+ if (!early
+ && ((fndecl != NULL_TREE
+ && fndecl_built_in_p (fndecl, BUILT_IN_EXPECT)
+ && gimple_call_num_args (stmt) == 2)
+ || (fndecl != NULL_TREE
+ && fndecl_built_in_p (fndecl,
+ BUILT_IN_EXPECT_WITH_PROBABILITY)
+ && gimple_call_num_args (stmt) == 3)
+ || (gimple_call_internal_p (stmt)
+ && gimple_call_internal_fn (stmt) == IFN_BUILTIN_EXPECT)))
{
var = gimple_call_lhs (stmt);
changed = true;
@@ -3955,6 +4088,49 @@ pass_strip_predict_hints::execute (function *fun)
return changed ? TODO_cleanup_cfg : 0;
}
+namespace {
+
+const pass_data pass_data_strip_predict_hints =
+{
+ GIMPLE_PASS, /* type */
+ "*strip_predict_hints", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_BRANCH_PROB, /* tv_id */
+ PROP_cfg, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_strip_predict_hints : public gimple_opt_pass
+{
+public:
+ pass_strip_predict_hints (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_strip_predict_hints, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ opt_pass * clone () { return new pass_strip_predict_hints (m_ctxt); }
+ void set_pass_param (unsigned int n, bool param)
+ {
+ gcc_assert (n == 0);
+ early_p = param;
+ }
+
+ virtual unsigned int execute (function *);
+
+private:
+ bool early_p;
+
+}; // class pass_strip_predict_hints
+
+unsigned int
+pass_strip_predict_hints::execute (function *fun)
+{
+ return strip_predict_hints (fun, early_p);
+}
+
} // anon namespace
gimple_opt_pass *
diff --git a/gcc/predict.def b/gcc/predict.def
index 4ed97ed..e2a56f9 100644
--- a/gcc/predict.def
+++ b/gcc/predict.def
@@ -22,7 +22,7 @@ along with GCC; see the file COPYING3. If not see
DEF_PREDICTOR (ENUM, NAME, HITRATE)
This macro will be called once for each predictor. The ENUM will
- be of type `enum predictor', and will enumerate all supported
+ be of type `enum br_predictor', and will enumerate all supported
predictors. The order of DEF_PREDICTOR calls is important, as
in the first match combining heuristics, the predictor appearing
first in this file will win.
@@ -51,6 +51,10 @@ DEF_PREDICTOR (PRED_NO_PREDICTION, "no prediction", PROB_ALWAYS, 0)
DEF_PREDICTOR (PRED_UNCONDITIONAL, "unconditional jump", PROB_ALWAYS,
PRED_FLAG_FIRST_MATCH)
+/* Return value of malloc function is almost always non-null. */
+DEF_PREDICTOR (PRED_MALLOC_NONNULL, "malloc returned non-NULL", \
+ PROB_VERY_LIKELY, PRED_FLAG_FIRST_MATCH)
+
/* Use number of loop iterations determined by # of iterations
analysis to set probability. We don't want to use Dempster-Shaffer
theory here, as the predictions is exact. */
@@ -69,6 +73,11 @@ DEF_PREDICTOR (PRED_COMPARE_AND_SWAP, "compare and swap", PROB_VERY_LIKELY,
DEF_PREDICTOR (PRED_BUILTIN_EXPECT, "__builtin_expect", PROB_VERY_LIKELY,
PRED_FLAG_FIRST_MATCH)
+/* Hints provided by user via __builtin_expect_with_probability. */
+DEF_PREDICTOR (PRED_BUILTIN_EXPECT_WITH_PROBABILITY,
+ "__builtin_expect_with_probability", PROB_UNINITIALIZED,
+ PRED_FLAG_FIRST_MATCH)
+
/* Use number of loop iterations guessed by the contents of the loop. */
DEF_PREDICTOR (PRED_LOOP_ITERATIONS_GUESSED, "guessed loop iterations",
PROB_UNINITIALIZED, PRED_FLAG_FIRST_MATCH)
@@ -169,7 +178,6 @@ DEF_PREDICTOR (PRED_HOT_LABEL, "hot label", HITRATE (85), 0)
DEF_PREDICTOR (PRED_COLD_LABEL, "cold label", PROB_VERY_LIKELY,
PRED_FLAG_FIRST_MATCH)
-
/* The following predictors are used in Fortran. */
/* Branch leading to an integer overflow are extremely unlikely. */
diff --git a/gcc/pretty-print.c b/gcc/pretty-print.c
index dc7791a..7dd900b 100644
--- a/gcc/pretty-print.c
+++ b/gcc/pretty-print.c
@@ -640,6 +640,16 @@ sgr_set_it:
{
attrib_add |= sb.wAttributes & ~attrib_rm;
}
+ if (attrib_add & COMMON_LVB_REVERSE_VIDEO)
+ {
+ /* COMMON_LVB_REVERSE_VIDEO is only effective for DBCS.
+ * Swap foreground and background colors by hand.
+ */
+ attrib_add = (attrib_add & 0xFF00)
+ | ((attrib_add & 0x00F0) >> 4)
+ | ((attrib_add & 0x000F) << 4);
+ attrib_add &= ~COMMON_LVB_REVERSE_VIDEO;
+ }
SetConsoleTextAttribute (h, attrib_add);
break;
}
@@ -684,7 +694,6 @@ mingw_ansi_fputs (const char *str, FILE *fp)
/* If it is not a console, write everything as-is. */
write_all (h, read, strlen (read));
- _close ((intptr_t) h);
return 1;
}
@@ -696,10 +705,11 @@ static void pp_quoted_string (pretty_printer *, const char *, size_t = -1);
For use e.g. when implementing "+" in client format decoders. */
void
-text_info::set_location (unsigned int idx, location_t loc, bool show_caret_p)
+text_info::set_location (unsigned int idx, location_t loc,
+ enum range_display_kind range_display_kind)
{
gcc_checking_assert (m_richloc);
- m_richloc->set_range (idx, loc, show_caret_p);
+ m_richloc->set_range (idx, loc, range_display_kind);
}
location_t
@@ -1482,23 +1492,38 @@ pp_clear_output_area (pretty_printer *pp)
pp_buffer (pp)->line_length = 0;
}
-/* Set PREFIX for PRETTY-PRINTER. */
+/* Set PREFIX for PRETTY-PRINTER, taking ownership of PREFIX, which
+ will eventually be free-ed. */
+
void
-pp_set_prefix (pretty_printer *pp, const char *prefix)
+pp_set_prefix (pretty_printer *pp, char *prefix)
{
+ free (pp->prefix);
pp->prefix = prefix;
pp_set_real_maximum_length (pp);
pp->emitted_prefix = false;
pp_indentation (pp) = 0;
}
+/* Take ownership of PP's prefix, setting it to NULL.
+ This allows clients to save, overide, and then restore an existing
+ prefix, without it being free-ed. */
+
+char *
+pp_take_prefix (pretty_printer *pp)
+{
+ char *result = pp->prefix;
+ pp->prefix = NULL;
+ return result;
+}
+
/* Free PRETTY-PRINTER's prefix, a previously malloc()'d string. */
void
pp_destroy_prefix (pretty_printer *pp)
{
if (pp->prefix != NULL)
{
- free (CONST_CAST (char *, pp->prefix));
+ free (pp->prefix);
pp->prefix = NULL;
}
}
@@ -1535,10 +1560,9 @@ pp_emit_prefix (pretty_printer *pp)
}
}
-/* Construct a PRETTY-PRINTER with PREFIX and of MAXIMUM_LENGTH
- characters per line. */
+/* Construct a PRETTY-PRINTER of MAXIMUM_LENGTH characters per line. */
-pretty_printer::pretty_printer (const char *p, int l)
+pretty_printer::pretty_printer (int maximum_length)
: buffer (new (XCNEW (output_buffer)) output_buffer ()),
prefix (),
padding (pp_none),
@@ -1552,10 +1576,10 @@ pretty_printer::pretty_printer (const char *p, int l)
translate_identifiers (true),
show_color ()
{
- pp_line_cutoff (this) = l;
+ pp_line_cutoff (this) = maximum_length;
/* By default, we emit prefixes once per message. */
pp_prefixing_rule (this) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
- pp_set_prefix (this, p);
+ pp_set_prefix (this, NULL);
}
pretty_printer::~pretty_printer ()
@@ -1564,6 +1588,7 @@ pretty_printer::~pretty_printer ()
delete m_format_postprocessor;
buffer->~output_buffer ();
XDELETE (buffer);
+ free (prefix);
}
/* Append a string delimited by START and END to the output area of
diff --git a/gcc/pretty-print.h b/gcc/pretty-print.h
index 56abe03..2decc51 100644
--- a/gcc/pretty-print.h
+++ b/gcc/pretty-print.h
@@ -36,7 +36,8 @@ struct text_info
void **x_data;
rich_location *m_richloc;
- void set_location (unsigned int idx, location_t loc, bool caret_p);
+ void set_location (unsigned int idx, location_t loc,
+ enum range_display_kind range_display_kind);
location_t get_location (unsigned int index_of_location) const;
};
@@ -215,17 +216,18 @@ class format_postprocessor
and add additional fields they need. */
struct pretty_printer
{
- // Default construct a pretty printer with specified prefix
- // and a maximum line length cut off limit.
- explicit pretty_printer (const char* = NULL, int = 0);
+ /* Default construct a pretty printer with specified
+ maximum line length cut off limit. */
+ explicit pretty_printer (int = 0);
virtual ~pretty_printer ();
/* Where we print external representation of ENTITY. */
output_buffer *buffer;
- /* The prefix for each new line. */
- const char *prefix;
+ /* The prefix for each new line. If non-NULL, this is "owned" by the
+ pretty_printer, and will eventually be free-ed. */
+ char *prefix;
/* Where to put whitespace around the entity being formatted. */
pp_padding padding;
@@ -338,7 +340,8 @@ pp_get_prefix (const pretty_printer *pp) { return pp->prefix; }
#define pp_buffer(PP) (PP)->buffer
extern void pp_set_line_maximum_length (pretty_printer *, int);
-extern void pp_set_prefix (pretty_printer *, const char *);
+extern void pp_set_prefix (pretty_printer *, char *);
+extern char *pp_take_prefix (pretty_printer *);
extern void pp_destroy_prefix (pretty_printer *);
extern int pp_remaining_character_count_for_line (pretty_printer *);
extern void pp_clear_output_area (pretty_printer *);
diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c
index 37c0d53..5dd2e31 100644
--- a/gcc/print-rtl.c
+++ b/gcc/print-rtl.c
@@ -36,11 +36,11 @@ along with GCC; see the file COPYING3. If not see
#include "alias.h"
#include "tree.h"
#include "basic-block.h"
-#include "cfg.h"
#include "print-tree.h"
#include "flags.h"
#include "predict.h"
#include "function.h"
+#include "cfg.h"
#include "basic-block.h"
#include "diagnostic.h"
#include "tree-pretty-print.h"
@@ -1742,6 +1742,7 @@ print_pattern (pretty_printer *pp, const_rtx x, int verbose)
print_exp (pp, x, verbose);
break;
case CLOBBER:
+ case CLOBBER_HIGH:
case USE:
pp_printf (pp, "%s ", GET_RTX_NAME (GET_CODE (x)));
print_value (pp, XEXP (x, 0), verbose);
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index 5347e06..8caf9dd 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -427,7 +427,7 @@ print_node (FILE *file, const char *prefix, tree node, int indent,
fputs (" autoinline", file);
if (code == FUNCTION_DECL && DECL_UNINLINABLE (node))
fputs (" uninlinable", file);
- if (code == FUNCTION_DECL && DECL_BUILT_IN (node))
+ if (code == FUNCTION_DECL && fndecl_built_in_p (node))
fputs (" built-in", file);
if (code == FUNCTION_DECL && DECL_STATIC_CHAIN (node))
fputs (" static-chain", file);
@@ -502,7 +502,7 @@ print_node (FILE *file, const char *prefix, tree node, int indent,
print_node (file, "size", DECL_SIZE (node), indent + 4);
print_node (file, "unit-size", DECL_SIZE_UNIT (node), indent + 4);
- if (code != FUNCTION_DECL || DECL_BUILT_IN (node))
+ if (code != FUNCTION_DECL || fndecl_built_in_p (node))
indent_to (file, indent + 3);
if (DECL_USER_ALIGN (node))
@@ -514,7 +514,7 @@ print_node (FILE *file, const char *prefix, tree node, int indent,
fprintf (file, " offset_align " HOST_WIDE_INT_PRINT_UNSIGNED,
DECL_OFFSET_ALIGN (node));
- if (code == FUNCTION_DECL && DECL_BUILT_IN (node))
+ if (code == FUNCTION_DECL && fndecl_built_in_p (node))
{
if (DECL_BUILT_IN_CLASS (node) == BUILT_IN_MD)
fprintf (file, " built-in: BUILT_IN_MD:%d", DECL_FUNCTION_CODE (node));
diff --git a/gcc/profile-count.c b/gcc/profile-count.c
index 716ffcc..f4ab244 100644
--- a/gcc/profile-count.c
+++ b/gcc/profile-count.c
@@ -25,8 +25,8 @@ along with GCC; see the file COPYING3. If not see
#include "options.h"
#include "tree.h"
#include "basic-block.h"
-#include "cfg.h"
#include "function.h"
+#include "cfg.h"
#include "gimple.h"
#include "data-streamer.h"
#include "cgraph.h"
diff --git a/gcc/profile.c b/gcc/profile.c
index cb51e0d..2130319 100644
--- a/gcc/profile.c
+++ b/gcc/profile.c
@@ -84,11 +84,7 @@ struct bb_profile_info {
/* Counter summary from the last set of coverage counts read. */
-const gcov_summary *profile_info;
-
-/* Counter working set information computed from the current counter
- summary. Not initialized unless profile_info summary is non-NULL. */
-static gcov_working_set_t gcov_working_sets[NUM_GCOV_WORKING_SETS];
+gcov_summary *profile_info;
/* Collect statistics on the performance of this pass for the entire source
file. */
@@ -103,14 +99,6 @@ static int total_num_times_called;
static int total_hist_br_prob[20];
static int total_num_branches;
-/* Helper function to update gcov_working_sets. */
-
-void add_working_set (gcov_working_set_t *set) {
- int i = 0;
- for (; i < NUM_GCOV_WORKING_SETS; i++)
- gcov_working_sets[i] = set[i];
-}
-
/* Forward declarations. */
static void find_spanning_tree (struct edge_list *);
@@ -207,60 +195,6 @@ instrument_values (histogram_values values)
}
-/* Fill the working set information into the profile_info structure. */
-
-void
-get_working_sets (void)
-{
- unsigned ws_ix, pctinc, pct;
- gcov_working_set_t *ws_info;
-
- if (!profile_info)
- return;
-
- compute_working_sets (profile_info, gcov_working_sets);
-
- if (dump_file)
- {
- fprintf (dump_file, "Counter working sets:\n");
- /* Multiply the percentage by 100 to avoid float. */
- pctinc = 100 * 100 / NUM_GCOV_WORKING_SETS;
- for (ws_ix = 0, pct = pctinc; ws_ix < NUM_GCOV_WORKING_SETS;
- ws_ix++, pct += pctinc)
- {
- if (ws_ix == NUM_GCOV_WORKING_SETS - 1)
- pct = 9990;
- ws_info = &gcov_working_sets[ws_ix];
- /* Print out the percentage using int arithmatic to avoid float. */
- fprintf (dump_file, "\t\t%u.%02u%%: num counts=%u, min counter="
- "%" PRId64 "\n",
- pct / 100, pct - (pct / 100 * 100),
- ws_info->num_counters,
- (int64_t)ws_info->min_counter);
- }
- }
-}
-
-/* Given a the desired percentage of the full profile (sum_all from the
- summary), multiplied by 10 to avoid float in PCT_TIMES_10, returns
- the corresponding working set information. If an exact match for
- the percentage isn't found, the closest value is used. */
-
-gcov_working_set_t *
-find_working_set (unsigned pct_times_10)
-{
- unsigned i;
- if (!profile_info)
- return NULL;
- gcc_assert (pct_times_10 <= 1000);
- if (pct_times_10 >= 999)
- return &gcov_working_sets[NUM_GCOV_WORKING_SETS - 1];
- i = pct_times_10 * NUM_GCOV_WORKING_SETS / 1000;
- if (!i)
- return &gcov_working_sets[0];
- return &gcov_working_sets[i - 1];
-}
-
/* Computes hybrid profile for all matching entries in da_file.
CFG_CHECKSUM is the precomputed checksum for the CFG. */
@@ -283,21 +217,14 @@ get_exec_counts (unsigned cfg_checksum, unsigned lineno_checksum)
num_edges++;
}
- counts = get_coverage_counts (GCOV_COUNTER_ARCS, num_edges, cfg_checksum,
- lineno_checksum, &profile_info);
+ counts = get_coverage_counts (GCOV_COUNTER_ARCS, cfg_checksum,
+ lineno_checksum);
if (!counts)
return NULL;
- get_working_sets ();
-
- if (dump_file && profile_info)
- fprintf (dump_file, "Merged %u profiles with maximal count %u.\n",
- profile_info->runs, (unsigned) profile_info->sum_max);
-
return counts;
}
-
static bool
is_edge_inconsistent (vec<edge, va_gc> *edges)
{
@@ -439,29 +366,7 @@ read_profile_edge_counts (gcov_type *exec_counts)
{
num_edges++;
if (exec_counts)
- {
- edge_gcov_count (e) = exec_counts[exec_counts_pos++];
- if (edge_gcov_count (e) > profile_info->sum_max)
- {
- if (flag_profile_correction)
- {
- static bool informed = 0;
- if (dump_enabled_p () && !informed)
- {
- dump_location_t loc
- = dump_location_t::from_location_t
- (input_location);
- dump_printf_loc (MSG_NOTE, loc,
- "corrupted profile info: edge count"
- " exceeds maximal count\n");
- }
- informed = 1;
- }
- else
- error ("corrupted profile info: edge from %i to %i exceeds maximal count",
- bb->index, e->dest->index);
- }
- }
+ edge_gcov_count (e) = exec_counts[exec_counts_pos++];
else
edge_gcov_count (e) = 0;
@@ -511,12 +416,6 @@ compute_branch_probabilities (unsigned cfg_checksum, unsigned lineno_checksum)
bb_gcov_counts.safe_grow_cleared (last_basic_block_for_fn (cfun));
edge_gcov_counts = new hash_map<edge,gcov_type>;
- if (profile_info->sum_all < profile_info->sum_max)
- {
- error ("corrupted profile info: sum_all is smaller than sum_max");
- exec_counts = NULL;
- }
-
/* Attach extra info block to each bb. */
alloc_aux_for_blocks (sizeof (struct bb_profile_info));
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, next_bb)
@@ -871,10 +770,9 @@ compute_value_histograms (histogram_values values, unsigned cfg_checksum,
continue;
}
- histogram_counts[t] =
- get_coverage_counts (COUNTER_FOR_HIST_TYPE (t),
- n_histogram_counters[t], cfg_checksum,
- lineno_checksum, NULL);
+ histogram_counts[t] = get_coverage_counts (COUNTER_FOR_HIST_TYPE (t),
+ cfg_checksum,
+ lineno_checksum);
if (histogram_counts[t])
any = 1;
act_count[t] = histogram_counts[t];
diff --git a/gcc/profile.h b/gcc/profile.h
index 6b37bb6..183e8d8 100644
--- a/gcc/profile.h
+++ b/gcc/profile.h
@@ -75,6 +75,6 @@ extern void get_working_sets (void);
/* Counter summary from the last set of coverage counts read by
profile.c. */
-extern const struct gcov_summary *profile_info;
+extern struct gcov_summary *profile_info;
#endif /* PROFILE_H */
diff --git a/gcc/read-md.c b/gcc/read-md.c
index 0b5dace..174e471 100644
--- a/gcc/read-md.c
+++ b/gcc/read-md.c
@@ -1003,7 +1003,10 @@ md_reader::md_reader (bool compact)
m_first_dir_md_include (NULL),
m_last_dir_md_include_ptr (&m_first_dir_md_include),
m_first_line (0),
- m_last_line (0)
+ m_last_line (0),
+ m_first_overload (NULL),
+ m_next_overload_ptr (&m_first_overload),
+ m_overloads_htab (NULL)
{
/* Set the global singleton pointer. */
md_reader_ptr = this;
diff --git a/gcc/read-md.h b/gcc/read-md.h
index 07883e7..56d5431 100644
--- a/gcc/read-md.h
+++ b/gcc/read-md.h
@@ -91,6 +91,48 @@ struct enum_type {
unsigned int num_values;
};
+/* Describes one instance of an overloaded_name. */
+struct overloaded_instance {
+ /* The next instance in the chain, or null if none. */
+ overloaded_instance *next;
+
+ /* The values that the overloaded_name arguments should have for this
+ instance to be chosen. Each value is a C token. */
+ vec<const char *> arg_values;
+
+ /* The full (non-overloaded) name of the pattern. */
+ const char *name;
+
+ /* The corresponding define_expand or define_insn. */
+ rtx insn;
+};
+
+/* Describes a define_expand or define_insn whose name was preceded by '@'.
+ Overloads are uniquely determined by their name and the types of their
+ arguments; it's possible to have overloads with the same name but
+ different argument types. */
+struct overloaded_name {
+ /* The next overloaded name in the chain. */
+ overloaded_name *next;
+
+ /* The overloaded name (i.e. the name with "@" character and
+ "<...>" placeholders removed). */
+ const char *name;
+
+ /* The C types of the iterators that determine the underlying pattern,
+ in the same order as in the pattern name. E.g. "<mode>" in the
+ pattern name would give a "machine_mode" argument here. */
+ vec<const char *> arg_types;
+
+ /* The first instance associated with this overloaded_name. */
+ overloaded_instance *first_instance;
+
+ /* Where to chain new overloaded_instances. */
+ overloaded_instance **next_instance_ptr;
+};
+
+struct mapping;
+
/* A class for reading .md files and RTL dump files.
Implemented in read-md.c.
@@ -165,6 +207,7 @@ class md_reader
rtx x, unsigned int index,
const char *name);
struct mapping *read_mapping (struct iterator_group *group, htab_t table);
+ overloaded_name *handle_overloaded_name (rtx, vec<mapping *> *);
const char *get_top_level_filename () const { return m_toplevel_fname; }
const char *get_filename () const { return m_read_md_filename; }
@@ -174,6 +217,8 @@ class md_reader
struct obstack *get_string_obstack () { return &m_string_obstack; }
htab_t get_md_constants () { return m_md_constants; }
+ overloaded_name *get_overloads () const { return m_first_overload; }
+
private:
/* A singly-linked list of filenames. */
struct file_name_list {
@@ -253,6 +298,16 @@ class md_reader
/* If non-zero, filter the input to just this subset of lines. */
int m_first_line;
int m_last_line;
+
+ /* The first overloaded_name. */
+ overloaded_name *m_first_overload;
+
+ /* Where to chain further overloaded_names, */
+ overloaded_name **m_next_overload_ptr;
+
+ /* A hash table of overloaded_names, keyed off their name and the types of
+ their arguments. */
+ htab_t m_overloads_htab;
};
/* Global singleton; constrast with rtx_reader_ptr below. */
diff --git a/gcc/read-rtl.c b/gcc/read-rtl.c
index 341b185..723c3e1 100644
--- a/gcc/read-rtl.c
+++ b/gcc/read-rtl.c
@@ -72,6 +72,9 @@ struct iterator_group {
iterators. */
htab_t attrs, iterators;
+ /* The C++ type of the iterator, such as "machine_mode" for modes. */
+ const char *type;
+
/* Treat the given string as the name of a standard mode, etc., and
return its integer value. */
int (*find_builtin) (const char *);
@@ -80,6 +83,9 @@ struct iterator_group {
If the iterator applies to operands, the second argument gives the
operand index, otherwise it is ignored. */
void (*apply_iterator) (rtx, unsigned int, int);
+
+ /* Return the C token for the given standard mode, code, etc. */
+ const char *(*get_c_token) (int);
};
/* Records one use of an iterator. */
@@ -163,6 +169,12 @@ apply_mode_iterator (rtx x, unsigned int, int mode)
PUT_MODE (x, (machine_mode) mode);
}
+static const char *
+get_mode_token (int mode)
+{
+ return concat ("E_", GET_MODE_NAME (mode), "mode", NULL);
+}
+
/* In compact dumps, the code of insns is prefixed with "c", giving "cinsn",
"cnote" etc, and CODE_LABEL is special-cased as "clabel". */
@@ -206,6 +218,15 @@ apply_code_iterator (rtx x, unsigned int, int code)
PUT_CODE (x, (enum rtx_code) code);
}
+static const char *
+get_code_token (int code)
+{
+ char *name = xstrdup (GET_RTX_NAME (code));
+ for (int i = 0; name[i]; ++i)
+ name[i] = TOUPPER (name[i]);
+ return name;
+}
+
/* Implementations of the iterator_group callbacks for ints. */
/* Since GCC does not construct a table of valid constants,
@@ -228,6 +249,14 @@ apply_int_iterator (rtx x, unsigned int index, int value)
XINT (x, index) = value;
}
+static const char *
+get_int_token (int value)
+{
+ char buffer[HOST_BITS_PER_INT + 1];
+ sprintf (buffer, "%d", value);
+ return xstrdup (buffer);
+}
+
#ifdef GENERATOR_FILE
/* This routine adds attribute or does nothing depending on VALUE. When
@@ -317,10 +346,11 @@ find_subst_iter_by_attr (const char *attr)
}
/* Map attribute string P to its current value. Return null if the attribute
- isn't known. */
+ isn't known. If ITERATOR_OUT is nonnull, store the associated iterator
+ there. */
static struct map_value *
-map_attr_string (const char *p)
+map_attr_string (const char *p, mapping **iterator_out = 0)
{
const char *attr;
struct mapping *iterator;
@@ -369,7 +399,11 @@ map_attr_string (const char *p)
iterator value. */
for (v = m->values; v; v = v->next)
if (v->number == iterator->current_value->number)
- return v;
+ {
+ if (iterator_out)
+ *iterator_out = iterator;
+ return v;
+ }
}
}
return NULL;
@@ -545,6 +579,178 @@ add_current_iterators (void **slot, void *data ATTRIBUTE_UNUSED)
return 1;
}
+/* Return a hash value for overloaded_name UNCAST_ONAME. There shouldn't
+ be many instances of two overloaded_names having the same name but
+ different arguments, so hashing on the name should be good enough in
+ practice. */
+
+static hashval_t
+overloaded_name_hash (const void *uncast_oname)
+{
+ const overloaded_name *oname = (const overloaded_name *) uncast_oname;
+ return htab_hash_string (oname->name);
+}
+
+/* Return true if two overloaded_names are similar enough to share
+ the same generated functions. */
+
+static int
+overloaded_name_eq_p (const void *uncast_oname1, const void *uncast_oname2)
+{
+ const overloaded_name *oname1 = (const overloaded_name *) uncast_oname1;
+ const overloaded_name *oname2 = (const overloaded_name *) uncast_oname2;
+ if (strcmp (oname1->name, oname2->name) != 0
+ || oname1->arg_types.length () != oname2->arg_types.length ())
+ return 0;
+
+ for (unsigned int i = 0; i < oname1->arg_types.length (); ++i)
+ if (strcmp (oname1->arg_types[i], oname2->arg_types[i]) != 0)
+ return 0;
+
+ return 1;
+}
+
+/* Return true if X has an instruction name in XSTR (X, 0). */
+
+static bool
+named_rtx_p (rtx x)
+{
+ switch (GET_CODE (x))
+ {
+ case DEFINE_EXPAND:
+ case DEFINE_INSN:
+ case DEFINE_INSN_AND_SPLIT:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/* Check whether ORIGINAL is a named pattern whose name starts with '@'.
+ If so, return the associated overloaded_name and add the iterator for
+ each argument to ITERATORS. Return null otherwise. */
+
+overloaded_name *
+md_reader::handle_overloaded_name (rtx original, vec<mapping *> *iterators)
+{
+ /* Check for the leading '@'. */
+ if (!named_rtx_p (original) || XSTR (original, 0)[0] != '@')
+ return NULL;
+
+ /* Remove the '@', so that no other code needs to worry about it. */
+ const char *name = XSTR (original, 0);
+ copy_md_ptr_loc (name + 1, name);
+ name += 1;
+ XSTR (original, 0) = name;
+
+ /* Build a copy of the name without the '<...>' attribute strings.
+ Add the iterator associated with each such attribute string to ITERATORS
+ and add an associated argument to TMP_ONAME. */
+ char *copy = ASTRDUP (name);
+ char *base = copy, *start, *end;
+ overloaded_name tmp_oname;
+ tmp_oname.arg_types.create (current_iterators.length ());
+ bool pending_underscore_p = false;
+ while ((start = strchr (base, '<')) && (end = strchr (start, '>')))
+ {
+ *end = 0;
+ mapping *iterator;
+ if (!map_attr_string (start + 1, &iterator))
+ fatal_with_file_and_line ("unknown iterator `%s'", start + 1);
+ *end = '>';
+
+ /* Remove a trailing underscore, so that we don't end a name
+ with "_" or turn "_<...>_" into "__". */
+ if (start != base && start[-1] == '_')
+ {
+ start -= 1;
+ pending_underscore_p = true;
+ }
+
+ /* Add the text between either the last '>' or the start of
+ the string and this '<'. */
+ obstack_grow (&m_string_obstack, base, start - base);
+ base = end + 1;
+
+ /* If there's a character we need to keep after the '>', check
+ whether we should prefix it with a previously-dropped '_'. */
+ if (base[0] != 0 && base[0] != '<')
+ {
+ if (pending_underscore_p && base[0] != '_')
+ obstack_1grow (&m_string_obstack, '_');
+ pending_underscore_p = false;
+ }
+
+ /* Record an argument for ITERATOR. */
+ iterators->safe_push (iterator);
+ tmp_oname.arg_types.safe_push (iterator->group->type);
+ }
+ if (base == copy)
+ fatal_with_file_and_line ("no iterator attributes in name `%s'", name);
+
+ size_t length = obstack_object_size (&m_string_obstack);
+ if (length == 0)
+ fatal_with_file_and_line ("`%s' only contains iterator attributes", name);
+
+ /* Get the completed name. */
+ obstack_grow (&m_string_obstack, base, strlen (base) + 1);
+ char *new_name = XOBFINISH (&m_string_obstack, char *);
+ tmp_oname.name = new_name;
+
+ if (!m_overloads_htab)
+ m_overloads_htab = htab_create (31, overloaded_name_hash,
+ overloaded_name_eq_p, NULL);
+
+ /* See whether another pattern had the same overload name and list
+ of argument types. Create a new permanent one if not. */
+ void **slot = htab_find_slot (m_overloads_htab, &tmp_oname, INSERT);
+ overloaded_name *oname = (overloaded_name *) *slot;
+ if (!oname)
+ {
+ *slot = oname = new overloaded_name;
+ oname->name = tmp_oname.name;
+ oname->arg_types = tmp_oname.arg_types;
+ oname->next = NULL;
+ oname->first_instance = NULL;
+ oname->next_instance_ptr = &oname->first_instance;
+
+ *m_next_overload_ptr = oname;
+ m_next_overload_ptr = &oname->next;
+ }
+ else
+ {
+ obstack_free (&m_string_obstack, new_name);
+ tmp_oname.arg_types.release ();
+ }
+
+ return oname;
+}
+
+/* Add an instance of ONAME for instruction pattern X. ITERATORS[I]
+ gives the iterator associated with argument I of ONAME. */
+
+static void
+add_overload_instance (overloaded_name *oname, vec<mapping *> iterators, rtx x)
+{
+ /* Create the instance. */
+ overloaded_instance *instance = new overloaded_instance;
+ instance->next = NULL;
+ instance->arg_values.create (oname->arg_types.length ());
+ for (unsigned int i = 0; i < iterators.length (); ++i)
+ {
+ int value = iterators[i]->current_value->number;
+ const char *name = iterators[i]->group->get_c_token (value);
+ instance->arg_values.quick_push (name);
+ }
+ instance->name = XSTR (x, 0);
+ instance->insn = x;
+
+ /* Chain it onto the end of ONAME's list. */
+ *oname->next_instance_ptr = instance;
+ oname->next_instance_ptr = &instance->next;
+}
+
/* Expand all iterators in the current rtx, which is given as ORIGINAL.
Build a list of expanded rtxes in the EXPR_LIST pointed to by QUEUE. */
@@ -562,6 +768,10 @@ apply_iterators (rtx original, vec<rtx> *queue)
{
/* Raise an error if any attributes were used. */
apply_attribute_uses ();
+
+ if (named_rtx_p (original) && XSTR (original, 0)[0] == '@')
+ fatal_with_file_and_line ("'@' used without iterators");
+
queue->safe_push (original);
return;
}
@@ -583,6 +793,11 @@ apply_iterators (rtx original, vec<rtx> *queue)
htab_traverse (substs.iterators, add_current_iterators, NULL);
gcc_assert (!current_iterators.is_empty ());
+ /* Check whether this is a '@' overloaded pattern. */
+ auto_vec<mapping *, 16> iterators;
+ overloaded_name *oname
+ = rtx_reader_ptr->handle_overloaded_name (original, &iterators);
+
for (;;)
{
/* Apply the current iterator values. Accumulate a condition to
@@ -616,6 +831,10 @@ apply_iterators (rtx original, vec<rtx> *queue)
v->number);
}
}
+
+ if (oname)
+ add_overload_instance (oname, iterators, x);
+
/* Add the new rtx to the end of the queue. */
queue->safe_push (x);
@@ -692,28 +911,36 @@ initialize_iterators (void)
modes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
modes.iterators = htab_create (13, leading_string_hash,
leading_string_eq_p, 0);
+ modes.type = "machine_mode";
modes.find_builtin = find_mode;
modes.apply_iterator = apply_mode_iterator;
+ modes.get_c_token = get_mode_token;
codes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
codes.iterators = htab_create (13, leading_string_hash,
leading_string_eq_p, 0);
+ codes.type = "rtx_code";
codes.find_builtin = find_code;
codes.apply_iterator = apply_code_iterator;
+ codes.get_c_token = get_code_token;
ints.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
ints.iterators = htab_create (13, leading_string_hash,
leading_string_eq_p, 0);
+ ints.type = "int";
ints.find_builtin = find_int;
ints.apply_iterator = apply_int_iterator;
+ ints.get_c_token = get_int_token;
substs.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
substs.iterators = htab_create (13, leading_string_hash,
leading_string_eq_p, 0);
+ substs.type = "int";
substs.find_builtin = find_int; /* We don't use it, anyway. */
#ifdef GENERATOR_FILE
substs.apply_iterator = apply_subst_iterator;
#endif
+ substs.get_c_token = get_int_token;
lower = add_mapping (&modes, modes.attrs, "mode");
upper = add_mapping (&modes, modes.attrs, "MODE");
diff --git a/gcc/recog.c b/gcc/recog.c
index 0a8fa2c..d7c6943 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -1600,6 +1600,7 @@ decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs,
{
if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
break; /* Past last SET */
+ gcc_assert (GET_CODE (XVECEXP (body, 0, i)) == SET);
if (operands)
operands[i] = SET_DEST (XVECEXP (body, 0, i));
if (operand_locs)
@@ -3715,7 +3716,8 @@ store_data_bypass_p_1 (rtx_insn *out_insn, rtx in_set)
{
rtx out_exp = XVECEXP (out_pat, 0, i);
- if (GET_CODE (out_exp) == CLOBBER || GET_CODE (out_exp) == USE)
+ if (GET_CODE (out_exp) == CLOBBER || GET_CODE (out_exp) == USE
+ || GET_CODE (out_exp) == CLOBBER_HIGH)
continue;
gcc_assert (GET_CODE (out_exp) == SET);
@@ -3746,7 +3748,8 @@ store_data_bypass_p (rtx_insn *out_insn, rtx_insn *in_insn)
{
rtx in_exp = XVECEXP (in_pat, 0, i);
- if (GET_CODE (in_exp) == CLOBBER || GET_CODE (in_exp) == USE)
+ if (GET_CODE (in_exp) == CLOBBER || GET_CODE (in_exp) == USE
+ || GET_CODE (in_exp) == CLOBBER_HIGH)
continue;
gcc_assert (GET_CODE (in_exp) == SET);
@@ -3798,7 +3801,7 @@ if_test_bypass_p (rtx_insn *out_insn, rtx_insn *in_insn)
{
rtx exp = XVECEXP (out_pat, 0, i);
- if (GET_CODE (exp) == CLOBBER)
+ if (GET_CODE (exp) == CLOBBER || GET_CODE (exp) == CLOBBER_HIGH)
continue;
gcc_assert (GET_CODE (exp) == SET);
diff --git a/gcc/recog.h b/gcc/recog.h
index eca6280..3d417ea2 100644
--- a/gcc/recog.h
+++ b/gcc/recog.h
@@ -24,7 +24,7 @@ along with GCC; see the file COPYING3. If not see
a type that has at least MAX_RECOG_ALTERNATIVES + 1 bits, with the extra
bit giving an invalid value that can be used to mean "uninitialized". */
#define MAX_RECOG_ALTERNATIVES 35
-typedef uint64_t alternative_mask;
+typedef uint64_t alternative_mask; /* Keep in sync with genattrtab.c. */
/* A mask of all alternatives. */
#define ALL_ALTERNATIVES ((alternative_mask) -1)
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index 519ea6d..97d758c 100644
--- a/gcc/reg-stack.c
+++ b/gcc/reg-stack.c
@@ -162,6 +162,7 @@
#include "df.h"
#include "insn-config.h"
#include "memmodel.h"
+#include "regs.h"
#include "emit-rtl.h" /* FIXME: Can go away once crtl is moved to rtl.h. */
#include "recog.h"
#include "varasm.h"
@@ -413,8 +414,9 @@ get_true_reg (rtx *pat)
/* Eliminate FP subregister accesses in favor of the
actual FP register in use. */
{
- rtx subreg;
- if (STACK_REG_P (subreg = SUBREG_REG (*pat)))
+ rtx subreg = SUBREG_REG (*pat);
+
+ if (STACK_REG_P (subreg))
{
int regno_off = subreg_regno_offset (REGNO (subreg),
GET_MODE (subreg),
@@ -427,6 +429,12 @@ get_true_reg (rtx *pat)
pat = &XEXP (*pat, 0);
break;
}
+
+ case FLOAT_TRUNCATE:
+ if (!flag_unsafe_math_optimizations)
+ return pat;
+ /* FALLTHRU */
+
case FLOAT:
case FIX:
case FLOAT_EXTEND:
@@ -439,12 +447,6 @@ get_true_reg (rtx *pat)
pat = &XVECEXP (*pat, 0, 0);
return pat;
- case FLOAT_TRUNCATE:
- if (!flag_unsafe_math_optimizations)
- return pat;
- pat = &XEXP (*pat, 0);
- break;
-
default:
return pat;
}
@@ -710,7 +712,7 @@ replace_reg (rtx *reg, int regno)
gcc_assert (IN_RANGE (regno, FIRST_STACK_REG, LAST_STACK_REG));
gcc_assert (STACK_REG_P (*reg));
- gcc_assert (SCALAR_FLOAT_MODE_P (GET_MODE (*reg))
+ gcc_assert (GET_MODE_CLASS (GET_MODE (*reg)) == MODE_FLOAT
|| GET_MODE_CLASS (GET_MODE (*reg)) == MODE_COMPLEX_FLOAT);
*reg = FP_MODE_REG (regno, GET_MODE (*reg));
@@ -764,8 +766,10 @@ get_hard_regnum (stack_ptr regstack, rtx reg)
cases the movdf pattern to pop. */
static rtx_insn *
-emit_pop_insn (rtx_insn *insn, stack_ptr regstack, rtx reg, enum emit_where where)
+emit_pop_insn (rtx_insn *insn, stack_ptr regstack, rtx reg,
+ enum emit_where where)
{
+ machine_mode raw_mode = reg_raw_mode[FIRST_STACK_REG];
rtx_insn *pop_insn;
rtx pop_rtx;
int hard_regno;
@@ -774,8 +778,8 @@ emit_pop_insn (rtx_insn *insn, stack_ptr regstack, rtx reg, enum emit_where wher
CLOBBER and USE expressions. */
if (COMPLEX_MODE_P (GET_MODE (reg)))
{
- rtx reg1 = FP_MODE_REG (REGNO (reg), DFmode);
- rtx reg2 = FP_MODE_REG (REGNO (reg) + 1, DFmode);
+ rtx reg1 = FP_MODE_REG (REGNO (reg), raw_mode);
+ rtx reg2 = FP_MODE_REG (REGNO (reg) + 1, raw_mode);
pop_insn = NULL;
if (get_hard_regnum (regstack, reg1) >= 0)
@@ -790,15 +794,15 @@ emit_pop_insn (rtx_insn *insn, stack_ptr regstack, rtx reg, enum emit_where wher
gcc_assert (hard_regno >= FIRST_STACK_REG);
- pop_rtx = gen_rtx_SET (FP_MODE_REG (hard_regno, DFmode),
- FP_MODE_REG (FIRST_STACK_REG, DFmode));
+ pop_rtx = gen_rtx_SET (FP_MODE_REG (hard_regno, raw_mode),
+ FP_MODE_REG (FIRST_STACK_REG, raw_mode));
if (where == EMIT_AFTER)
pop_insn = emit_insn_after (pop_rtx, insn);
else
pop_insn = emit_insn_before (pop_rtx, insn);
- add_reg_note (pop_insn, REG_DEAD, FP_MODE_REG (FIRST_STACK_REG, DFmode));
+ add_reg_note (pop_insn, REG_DEAD, FP_MODE_REG (FIRST_STACK_REG, raw_mode));
regstack->reg[regstack->top - (hard_regno - FIRST_STACK_REG)]
= regstack->reg[regstack->top];
@@ -819,7 +823,6 @@ static void
emit_swap_insn (rtx_insn *insn, stack_ptr regstack, rtx reg)
{
int hard_regno;
- rtx swap_rtx;
int other_reg; /* swap regno temps */
rtx_insn *i1; /* the stack-reg insn prior to INSN */
rtx i1set = NULL_RTX; /* the SET rtx within I1 */
@@ -977,9 +980,13 @@ emit_swap_insn (rtx_insn *insn, stack_ptr regstack, rtx reg)
return;
}
- swap_rtx = gen_swapxf (FP_MODE_REG (hard_regno, XFmode),
- FP_MODE_REG (FIRST_STACK_REG, XFmode));
-
+ machine_mode raw_mode = reg_raw_mode[FIRST_STACK_REG];
+ rtx op1 = FP_MODE_REG (hard_regno, raw_mode);
+ rtx op2 = FP_MODE_REG (FIRST_STACK_REG, raw_mode);
+ rtx swap_rtx
+ = gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (2, gen_rtx_SET (op1, op2),
+ gen_rtx_SET (op2, op1)));
if (i1)
emit_insn_after (swap_rtx, i1);
else if (current_block)
@@ -2274,13 +2281,7 @@ subst_asm_stack_regs (rtx_insn *insn, stack_ptr regstack)
int regnum = get_hard_regnum (regstack, clobber_reg[i]);
if (regnum >= 0)
- {
- /* Sigh - clobbers always have QImode. But replace_reg knows
- that these regs can't be MODE_INT and will assert. Just put
- the right reg there without calling replace_reg. */
-
- *clobber_loc[i] = FP_MODE_REG (regnum, DFmode);
- }
+ replace_reg (clobber_loc[i], regnum);
}
/* Now remove from REGSTACK any inputs that the asm implicitly popped. */
@@ -2492,6 +2493,7 @@ change_stack (rtx_insn *insn, stack_ptr old, stack_ptr new_stack,
enum emit_where where)
{
int reg;
+ machine_mode raw_mode = reg_raw_mode[FIRST_STACK_REG];
rtx_insn *update_end = NULL;
int i;
@@ -2593,7 +2595,7 @@ change_stack (rtx_insn *insn, stack_ptr old, stack_ptr new_stack,
next--;
dest = next--;
}
- emit_pop_insn (insn, old, FP_MODE_REG (old->reg[dest], DFmode),
+ emit_pop_insn (insn, old, FP_MODE_REG (old->reg[dest], raw_mode),
EMIT_BEFORE);
}
}
@@ -2615,11 +2617,11 @@ change_stack (rtx_insn *insn, stack_ptr old, stack_ptr new_stack,
{
while (TEST_HARD_REG_BIT (new_stack->reg_set, old->reg[next]))
next--;
- emit_pop_insn (insn, old, FP_MODE_REG (old->reg[next], DFmode),
+ emit_pop_insn (insn, old, FP_MODE_REG (old->reg[next], raw_mode),
EMIT_BEFORE);
}
else
- emit_pop_insn (insn, old, FP_MODE_REG (old->reg[old->top], DFmode),
+ emit_pop_insn (insn, old, FP_MODE_REG (old->reg[old->top], raw_mode),
EMIT_BEFORE);
}
@@ -2666,7 +2668,7 @@ change_stack (rtx_insn *insn, stack_ptr old, stack_ptr new_stack,
gcc_assert (reg != -1);
emit_swap_insn (insn, old,
- FP_MODE_REG (old->reg[reg], DFmode));
+ FP_MODE_REG (old->reg[reg], raw_mode));
}
/* See if any regs remain incorrect. If so, bring an
@@ -2677,7 +2679,7 @@ change_stack (rtx_insn *insn, stack_ptr old, stack_ptr new_stack,
if (new_stack->reg[reg] != old->reg[reg])
{
emit_swap_insn (insn, old,
- FP_MODE_REG (old->reg[reg], DFmode));
+ FP_MODE_REG (old->reg[reg], raw_mode));
break;
}
} while (reg >= 0);
diff --git a/gcc/regcprop.c b/gcc/regcprop.c
index 1813242..1f80576 100644
--- a/gcc/regcprop.c
+++ b/gcc/regcprop.c
@@ -237,7 +237,11 @@ static void
kill_clobbered_value (rtx x, const_rtx set, void *data)
{
struct value_data *const vd = (struct value_data *) data;
- if (GET_CODE (set) == CLOBBER)
+ gcc_assert (GET_CODE (set) != CLOBBER_HIGH || REG_P (x));
+
+ if (GET_CODE (set) == CLOBBER
+ || (GET_CODE (set) == CLOBBER_HIGH
+ && reg_is_clobbered_by_clobber_high (x, XEXP (set, 0))))
kill_value (x, vd);
}
@@ -257,7 +261,9 @@ kill_set_value (rtx x, const_rtx set, void *data)
struct kill_set_value_data *ksvd = (struct kill_set_value_data *) data;
if (rtx_equal_p (x, ksvd->ignore_set_reg))
return;
- if (GET_CODE (set) != CLOBBER)
+
+ gcc_assert (GET_CODE (set) != CLOBBER_HIGH || REG_P (x));
+ if (GET_CODE (set) != CLOBBER && GET_CODE (set) != CLOBBER_HIGH)
{
kill_value (x, ksvd->vd);
if (REG_P (x))
diff --git a/gcc/reginfo.c b/gcc/reginfo.c
index f4071da..33befa5 100644
--- a/gcc/reginfo.c
+++ b/gcc/reginfo.c
@@ -782,6 +782,7 @@ globalize_reg (tree decl, int i)
if (global_regs[i])
{
+ auto_diagnostic_group d;
warning_at (loc, 0,
"register of %qD used for multiple global register variables",
decl);
@@ -1100,6 +1101,10 @@ reg_scan_mark_refs (rtx x, rtx_insn *insn)
reg_scan_mark_refs (XEXP (XEXP (x, 0), 0), insn);
break;
+ case CLOBBER_HIGH:
+ gcc_assert (!(MEM_P (XEXP (x, 0))));
+ break;
+
case SET:
/* Count a set of the destination if it is a register. */
for (dest = SET_DEST (x);
diff --git a/gcc/reload1.c b/gcc/reload1.c
index a4cc3ee..3c0c9ff 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -1339,6 +1339,8 @@ maybe_fix_stack_asms (void)
rtx t = XVECEXP (pat, 0, i);
if (GET_CODE (t) == CLOBBER && STACK_REG_P (XEXP (t, 0)))
SET_HARD_REG_BIT (clobbered, REGNO (XEXP (t, 0)));
+ /* CLOBBER_HIGH is only supported for LRA. */
+ gcc_assert (GET_CODE (t) != CLOBBER_HIGH);
}
/* Get the operand values and constraints out of the insn. */
@@ -2879,6 +2881,7 @@ eliminate_regs_1 (rtx x, machine_mode mem_mode, rtx insn,
return x;
case CLOBBER:
+ case CLOBBER_HIGH:
case ASM_OPERANDS:
gcc_assert (insn && DEBUG_INSN_P (insn));
break;
@@ -3089,6 +3092,10 @@ elimination_effects (rtx x, machine_mode mem_mode)
elimination_effects (XEXP (x, 0), mem_mode);
return;
+ case CLOBBER_HIGH:
+ /* CLOBBER_HIGH is only supported for LRA. */
+ return;
+
case SET:
/* Check for setting a register that we know about. */
if (REG_P (SET_DEST (x)))
@@ -3810,6 +3817,9 @@ mark_not_eliminable (rtx dest, const_rtx x, void *data ATTRIBUTE_UNUSED)
if (dest == hard_frame_pointer_rtx)
return;
+ /* CLOBBER_HIGH is only supported for LRA. */
+ gcc_assert (GET_CODE (x) != CLOBBER_HIGH);
+
for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
if (reg_eliminate[i].can_eliminate && dest == reg_eliminate[i].to_rtx
&& (GET_CODE (x) != SET
@@ -4445,6 +4455,7 @@ scan_paradoxical_subregs (rtx x)
case PC:
case USE:
case CLOBBER:
+ case CLOBBER_HIGH:
return;
case SUBREG:
@@ -4899,7 +4910,7 @@ reload_as_needed (int live_known)
to be forgotten later. */
static void
-forget_old_reloads_1 (rtx x, const_rtx ignored ATTRIBUTE_UNUSED,
+forget_old_reloads_1 (rtx x, const_rtx setter,
void *data)
{
unsigned int regno;
@@ -4919,6 +4930,9 @@ forget_old_reloads_1 (rtx x, const_rtx ignored ATTRIBUTE_UNUSED,
if (!REG_P (x))
return;
+ /* CLOBBER_HIGH is only supported for LRA. */
+ gcc_assert (setter == NULL_RTX || GET_CODE (setter) != CLOBBER_HIGH);
+
regno = REGNO (x);
if (regno >= FIRST_PSEUDO_REGISTER)
diff --git a/gcc/reorg.c b/gcc/reorg.c
index 904d91e..f8a986c 100644
--- a/gcc/reorg.c
+++ b/gcc/reorg.c
@@ -397,7 +397,8 @@ find_end_label (rtx kind)
while (NOTE_P (insn)
|| (NONJUMP_INSN_P (insn)
&& (GET_CODE (PATTERN (insn)) == USE
- || GET_CODE (PATTERN (insn)) == CLOBBER)))
+ || GET_CODE (PATTERN (insn)) == CLOBBER
+ || GET_CODE (PATTERN (insn)) == CLOBBER_HIGH)))
insn = PREV_INSN (insn);
/* When a target threads its epilogue we might already have a
@@ -1297,7 +1298,8 @@ try_merge_delay_insns (rtx_insn *insn, rtx_insn *thread)
/* TRIAL must be a CALL_INSN or INSN. Skip USE and CLOBBER. */
if (NONJUMP_INSN_P (trial)
- && (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER))
+ && (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
+ || GET_CODE (pat) == CLOBBER_HIGH))
continue;
if (GET_CODE (next_to_match) == GET_CODE (trial)
@@ -1491,7 +1493,8 @@ redundant_insn (rtx insn, rtx_insn *target, const vec<rtx_insn *> &delay_list)
--insns_to_search;
pat = PATTERN (trial);
- if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
+ if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
+ || GET_CODE (pat) == CLOBBER_HIGH)
continue;
if (GET_CODE (trial) == DEBUG_INSN)
@@ -1589,7 +1592,8 @@ redundant_insn (rtx insn, rtx_insn *target, const vec<rtx_insn *> &delay_list)
--insns_to_search;
pat = PATTERN (trial);
- if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
+ if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
+ || GET_CODE (pat) == CLOBBER_HIGH)
continue;
if (GET_CODE (trial) == DEBUG_INSN)
@@ -1701,7 +1705,8 @@ own_thread_p (rtx thread, rtx label, int allow_fallthrough)
|| LABEL_P (insn)
|| (NONJUMP_INSN_P (insn)
&& GET_CODE (PATTERN (insn)) != USE
- && GET_CODE (PATTERN (insn)) != CLOBBER))
+ && GET_CODE (PATTERN (insn)) != CLOBBER
+ && GET_CODE (PATTERN (insn)) != CLOBBER_HIGH))
return 0;
return 1;
@@ -2024,7 +2029,8 @@ fill_simple_delay_slots (int non_jumps_p)
pat = PATTERN (trial);
/* Stand-alone USE and CLOBBER are just for flow. */
- if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
+ if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
+ || GET_CODE (pat) == CLOBBER_HIGH)
continue;
/* And DEBUG_INSNs never go into delay slots. */
@@ -2150,7 +2156,8 @@ fill_simple_delay_slots (int non_jumps_p)
pat = PATTERN (trial);
/* Stand-alone USE and CLOBBER are just for flow. */
- if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
+ if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
+ || GET_CODE (pat) == CLOBBER_HIGH)
continue;
/* And DEBUG_INSNs do not go in delay slots. */
@@ -2418,7 +2425,8 @@ fill_slots_from_thread (rtx_jump_insn *insn, rtx condition,
}
pat = PATTERN (trial);
- if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
+ if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
+ || GET_CODE (pat) == CLOBBER_HIGH)
continue;
if (GET_CODE (trial) == DEBUG_INSN)
@@ -3818,7 +3826,8 @@ dbr_schedule (rtx_insn *first)
if (! insn->deleted ()
&& NONJUMP_INSN_P (insn)
&& GET_CODE (PATTERN (insn)) != USE
- && GET_CODE (PATTERN (insn)) != CLOBBER)
+ && GET_CODE (PATTERN (insn)) != CLOBBER
+ && GET_CODE (PATTERN (insn)) != CLOBBER_HIGH)
{
if (GET_CODE (PATTERN (insn)) == SEQUENCE)
{
diff --git a/gcc/resource.c b/gcc/resource.c
index 0822dae..fdfab69 100644
--- a/gcc/resource.c
+++ b/gcc/resource.c
@@ -108,6 +108,11 @@ update_live_status (rtx dest, const_rtx x, void *data ATTRIBUTE_UNUSED)
if (GET_CODE (x) == CLOBBER)
for (i = first_regno; i < last_regno; i++)
CLEAR_HARD_REG_BIT (current_live_regs, i);
+ else if (GET_CODE (x) == CLOBBER_HIGH)
+ /* No current target supports both branch delay slots and CLOBBER_HIGH.
+ We'd need more elaborate liveness tracking to handle that
+ combination. */
+ gcc_unreachable ();
else
for (i = first_regno; i < last_regno; i++)
{
@@ -293,6 +298,7 @@ mark_referenced_resources (rtx x, struct resources *res,
return;
case CLOBBER:
+ case CLOBBER_HIGH:
return;
case CALL_INSN:
@@ -668,9 +674,15 @@ mark_set_resources (rtx x, struct resources *res, int in_dest,
for (link = CALL_INSN_FUNCTION_USAGE (call_insn);
link; link = XEXP (link, 1))
- if (GET_CODE (XEXP (link, 0)) == CLOBBER)
- mark_set_resources (SET_DEST (XEXP (link, 0)), res, 1,
- MARK_SRC_DEST);
+ {
+ /* We could support CLOBBER_HIGH and treat it in the same way as
+ HARD_REGNO_CALL_PART_CLOBBERED, but no port needs that
+ yet. */
+ gcc_assert (GET_CODE (XEXP (link, 0)) != CLOBBER_HIGH);
+ if (GET_CODE (XEXP (link, 0)) == CLOBBER)
+ mark_set_resources (SET_DEST (XEXP (link, 0)), res, 1,
+ MARK_SRC_DEST);
+ }
/* Check for a REG_SETJMP. If it exists, then we must
assume that this call can clobber any register. */
@@ -713,6 +725,12 @@ mark_set_resources (rtx x, struct resources *res, int in_dest,
mark_set_resources (XEXP (x, 0), res, 1, MARK_SRC_DEST);
return;
+ case CLOBBER_HIGH:
+ /* No current target supports both branch delay slots and CLOBBER_HIGH.
+ We'd need more elaborate liveness tracking to handle that
+ combination. */
+ gcc_unreachable ();
+
case SEQUENCE:
{
rtx_sequence *seq = as_a <rtx_sequence *> (x);
diff --git a/gcc/rtl.c b/gcc/rtl.c
index 90bbc7c..f9146af 100644
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -304,6 +304,10 @@ copy_rtx (rtx orig)
return orig;
break;
+ case CLOBBER_HIGH:
+ gcc_assert (REG_P (XEXP (orig, 0)));
+ return orig;
+
case CONST:
if (shared_const_p (orig))
return orig;
@@ -857,6 +861,17 @@ rtl_check_failed_code2 (const_rtx r, enum rtx_code code1, enum rtx_code code2,
}
void
+rtl_check_failed_code3 (const_rtx r, enum rtx_code code1, enum rtx_code code2,
+ enum rtx_code code3, const char *file, int line,
+ const char *func)
+{
+ internal_error
+ ("RTL check: expected code '%s', '%s' or '%s', have '%s' in %s, at %s:%d",
+ GET_RTX_NAME (code1), GET_RTX_NAME (code2), GET_RTX_NAME (code3),
+ GET_RTX_NAME (GET_CODE (r)), func, trim_filename (file), line);
+}
+
+void
rtl_check_failed_code_mode (const_rtx r, enum rtx_code code, machine_mode mode,
bool not_mode, const char *file, int line,
const char *func)
diff --git a/gcc/rtl.def b/gcc/rtl.def
index 2578a0c..b4282ab 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -312,6 +312,16 @@ DEF_RTL_EXPR(USE, "use", "e", RTX_EXTRA)
is considered undeletable before reload. */
DEF_RTL_EXPR(CLOBBER, "clobber", "e", RTX_EXTRA)
+/* Indicate that the upper parts of something are clobbered in a way that we
+ don't want to explain. The MODE references the lower bits that will be
+ preserved. Anything above that size will be clobbered.
+
+ CLOBBER_HIGH only occurs as the operand of a PARALLEL rtx. It cannot appear
+ in other contexts, and unlike CLOBBER, it cannot appear on its own.
+ CLOBBER_HIGH can only be used with fixed register rtxes. */
+
+DEF_RTL_EXPR(CLOBBER_HIGH, "clobber_high", "e", RTX_EXTRA)
+
/* Call a subroutine.
Operand 1 is the address to call.
Operand 2 is the number of arguments. */
@@ -1300,7 +1310,7 @@ DEF_RTL_EXPR(EQ_ATTR, "eq_attr", "ss", RTX_EXTRA)
/* A special case of the above representing a set of alternatives. The first
operand is bitmap of the set, the second one is the default value. */
-DEF_RTL_EXPR(EQ_ATTR_ALT, "eq_attr_alt", "ii", RTX_EXTRA)
+DEF_RTL_EXPR(EQ_ATTR_ALT, "eq_attr_alt", "ww", RTX_EXTRA)
/* A conditional expression which is true if the specified flag is
true for the insn being scheduled in reorg.
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 565ce3a..68d3cea 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1100,6 +1100,14 @@ is_a_helper <rtx_note *>::test (rtx_insn *insn)
__FUNCTION__); \
&_rtx->u.fld[_n]; }))
+#define RTL_CHECKC3(RTX, N, C1, C2, C3) __extension__ \
+(*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N); \
+ const enum rtx_code _code = GET_CODE (_rtx); \
+ if (_code != (C1) && _code != (C2) && _code != (C3)) \
+ rtl_check_failed_code3 (_rtx, (C1), (C2), (C3), __FILE__, \
+ __LINE__, __FUNCTION__); \
+ &_rtx->u.fld[_n]; }))
+
#define RTVEC_ELT(RTVEC, I) __extension__ \
(*({ __typeof (RTVEC) const _rtvec = (RTVEC); const int _i = (I); \
if (_i < 0 || _i >= GET_NUM_ELEM (_rtvec)) \
@@ -1190,6 +1198,10 @@ extern void rtl_check_failed_code1 (const_rtx, enum rtx_code, const char *,
extern void rtl_check_failed_code2 (const_rtx, enum rtx_code, enum rtx_code,
const char *, int, const char *)
ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void rtl_check_failed_code3 (const_rtx, enum rtx_code, enum rtx_code,
+ enum rtx_code, const char *, int,
+ const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
extern void rtl_check_failed_code_mode (const_rtx, enum rtx_code, machine_mode,
bool, const char *, int, const char *)
ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
@@ -1208,6 +1220,7 @@ extern void rtvec_check_failed_bounds (const_rtvec, int, const char *, int,
#define RTL_CHECK2(RTX, N, C1, C2) ((RTX)->u.fld[N])
#define RTL_CHECKC1(RTX, N, C) ((RTX)->u.fld[N])
#define RTL_CHECKC2(RTX, N, C1, C2) ((RTX)->u.fld[N])
+#define RTL_CHECKC3(RTX, N, C1, C2, C3) ((RTX)->u.fld[N])
#define RTVEC_ELT(RTVEC, I) ((RTVEC)->elem[I])
#define XWINT(RTX, N) ((RTX)->u.hwint[N])
#define CWI_ELT(RTX, I) ((RTX)->u.hwiv.elem[I])
@@ -1362,6 +1375,7 @@ extern void rtl_check_failed_flag (const char *, const_rtx, const char *,
#define XCVECLEN(RTX, N, C) GET_NUM_ELEM (XCVEC (RTX, N, C))
#define XC2EXP(RTX, N, C1, C2) (RTL_CHECKC2 (RTX, N, C1, C2).rt_rtx)
+#define XC3EXP(RTX, N, C1, C2, C3) (RTL_CHECKC3 (RTX, N, C1, C2, C3).rt_rtx)
/* Methods of rtx_expr_list. */
@@ -2632,7 +2646,7 @@ do { \
/* For a SET rtx, SET_DEST is the place that is set
and SET_SRC is the value it is set to. */
-#define SET_DEST(RTX) XC2EXP (RTX, 0, SET, CLOBBER)
+#define SET_DEST(RTX) XC3EXP (RTX, 0, SET, CLOBBER, CLOBBER_HIGH)
#define SET_SRC(RTX) XCEXP (RTX, 1, SET)
#define SET_IS_RETURN_P(RTX) \
(RTL_FLAG_CHECK1 ("SET_IS_RETURN_P", (RTX), SET)->jump)
@@ -3296,6 +3310,15 @@ extern enum rtx_code unsigned_condition (enum rtx_code);
extern enum rtx_code signed_condition (enum rtx_code);
extern void mark_jump_label (rtx, rtx_insn *, int);
+/* Return true if integer comparison operator CODE interprets its operands
+ as unsigned. */
+
+inline bool
+unsigned_condition_p (enum rtx_code code)
+{
+ return unsigned_condition (code) == code;
+}
+
/* In jump.c */
extern rtx_insn *delete_related_insns (rtx);
@@ -3453,6 +3476,16 @@ extern bool tablejump_p (const rtx_insn *, rtx_insn **, rtx_jump_table_data **);
extern int computed_jump_p (const rtx_insn *);
extern bool tls_referenced_p (const_rtx);
extern bool contains_mem_rtx_p (rtx x);
+extern bool reg_is_clobbered_by_clobber_high (unsigned int, machine_mode,
+ const_rtx);
+
+/* Convenient wrapper for reg_is_clobbered_by_clobber_high. */
+inline bool
+reg_is_clobbered_by_clobber_high (const_rtx x, const_rtx clobber_high_op)
+{
+ return reg_is_clobbered_by_clobber_high (REGNO (x), GET_MODE (x),
+ clobber_high_op);
+}
/* Overload for refers_to_regno_p for checking a single register. */
inline bool
@@ -4228,6 +4261,7 @@ extern void vt_equate_reg_base_value (const_rtx, const_rtx);
extern bool memory_modified_in_insn_p (const_rtx, const_rtx);
extern bool may_be_sp_based_p (rtx);
extern rtx gen_hard_reg_clobber (machine_mode, unsigned int);
+extern rtx gen_hard_reg_clobber_high (machine_mode, unsigned int);
extern rtx get_reg_known_value (unsigned int);
extern bool get_reg_known_equiv_p (unsigned int);
extern rtx get_reg_base_value (unsigned int);
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 9f84d7f..e8b6b9c 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -1198,6 +1198,10 @@ reg_referenced_p (const_rtx x, const_rtx body)
return 1;
return 0;
+ case CLOBBER_HIGH:
+ gcc_assert (REG_P (XEXP (body, 0)));
+ return 0;
+
case COND_EXEC:
if (reg_overlap_mentioned_p (x, COND_EXEC_TEST (body)))
return 1;
@@ -1420,7 +1424,11 @@ set_of_1 (rtx x, const_rtx pat, void *data1)
{
struct set_of_data *const data = (struct set_of_data *) (data1);
if (rtx_equal_p (x, data->pat)
- || (!MEM_P (x) && reg_overlap_mentioned_p (data->pat, x)))
+ || (GET_CODE (pat) == CLOBBER_HIGH
+ && REGNO(data->pat) == REGNO(XEXP (pat, 0))
+ && reg_is_clobbered_by_clobber_high (data->pat, XEXP (pat, 0)))
+ || (GET_CODE (pat) != CLOBBER_HIGH && !MEM_P (x)
+ && reg_overlap_mentioned_p (data->pat, x)))
data->found = pat;
}
@@ -1509,6 +1517,7 @@ single_set_2 (const rtx_insn *insn, const_rtx pat)
{
case USE:
case CLOBBER:
+ case CLOBBER_HIGH:
break;
case SET:
@@ -1663,7 +1672,8 @@ noop_move_p (const rtx_insn *insn)
rtx tem = XVECEXP (pat, 0, i);
if (GET_CODE (tem) == USE
- || GET_CODE (tem) == CLOBBER)
+ || GET_CODE (tem) == CLOBBER
+ || GET_CODE (tem) == CLOBBER_HIGH)
continue;
if (GET_CODE (tem) != SET || ! set_noop_p (tem))
@@ -1805,6 +1815,7 @@ reg_overlap_mentioned_p (const_rtx x, const_rtx in)
recurse:
switch (GET_CODE (x))
{
+ case CLOBBER:
case STRICT_LOW_PART:
case ZERO_EXTRACT:
case SIGN_EXTRACT:
@@ -1895,7 +1906,9 @@ note_stores (const_rtx x, void (*fun) (rtx, const_rtx, void *), void *data)
if (GET_CODE (x) == COND_EXEC)
x = COND_EXEC_CODE (x);
- if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)
+ if (GET_CODE (x) == SET
+ || GET_CODE (x) == CLOBBER
+ || GET_CODE (x) == CLOBBER_HIGH)
{
rtx dest = SET_DEST (x);
@@ -6551,3 +6564,32 @@ tls_referenced_p (const_rtx x)
return true;
return false;
}
+
+/* Return true if reg REGNO with mode REG_MODE would be clobbered by the
+ clobber_high operand in CLOBBER_HIGH_OP. */
+
+bool
+reg_is_clobbered_by_clobber_high (unsigned int regno, machine_mode reg_mode,
+ const_rtx clobber_high_op)
+{
+ unsigned int clobber_regno = REGNO (clobber_high_op);
+ machine_mode clobber_mode = GET_MODE (clobber_high_op);
+ unsigned char regno_nregs = hard_regno_nregs (regno, reg_mode);
+
+ /* Clobber high should always span exactly one register. */
+ gcc_assert (REG_NREGS (clobber_high_op) == 1);
+
+ /* Clobber high needs to match with one of the registers in X. */
+ if (clobber_regno < regno || clobber_regno >= regno + regno_nregs)
+ return false;
+
+ gcc_assert (reg_mode != BLKmode && clobber_mode != BLKmode);
+
+ if (reg_mode == VOIDmode)
+ return clobber_mode != VOIDmode;
+
+ /* Clobber high will clobber if its size might be greater than the size of
+ register regno. */
+ return maybe_gt (exact_div (GET_MODE_SIZE (reg_mode), regno_nregs),
+ GET_MODE_SIZE (clobber_mode));
+}
diff --git a/gcc/sanopt.c b/gcc/sanopt.c
index 223c06a..082f936 100644
--- a/gcc/sanopt.c
+++ b/gcc/sanopt.c
@@ -1165,13 +1165,15 @@ sanitize_rewrite_addressable_params (function *fun)
gimple_add_tmp_var (var);
+ /* We skip parameters that have a DECL_VALUE_EXPR. */
+ if (DECL_HAS_VALUE_EXPR_P (arg))
+ continue;
+
if (dump_file)
fprintf (dump_file,
"Rewriting parameter whose address is taken: %s\n",
IDENTIFIER_POINTER (DECL_NAME (arg)));
- gcc_assert (!DECL_HAS_VALUE_EXPR_P (arg));
-
SET_DECL_PT_UID (var, DECL_PT_UID (arg));
/* Assign value of parameter to newly created variable. */
diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c
index 120b5f0..f89f282 100644
--- a/gcc/sched-deps.c
+++ b/gcc/sched-deps.c
@@ -2319,6 +2319,13 @@ sched_analyze_reg (struct deps_desc *deps, int regno, machine_mode mode,
while (--i >= 0)
note_reg_use (regno + i);
}
+ else if (ref == CLOBBER_HIGH)
+ {
+ gcc_assert (i == 1);
+ /* We don't know the current state of the register, so have to treat
+ the clobber high as a full clobber. */
+ note_reg_clobber (regno);
+ }
else
{
while (--i >= 0)
@@ -2342,6 +2349,8 @@ sched_analyze_reg (struct deps_desc *deps, int regno, machine_mode mode,
else if (ref == USE)
note_reg_use (regno);
else
+ /* For CLOBBER_HIGH, we don't know the current state of the register,
+ so have to treat it as a full clobber. */
note_reg_clobber (regno);
/* Pseudos that are REG_EQUIV to something may be replaced
@@ -2962,7 +2971,7 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx_insn *insn)
sub = COND_EXEC_CODE (sub);
code = GET_CODE (sub);
}
- if (code == SET || code == CLOBBER)
+ else if (code == SET || code == CLOBBER || code == CLOBBER_HIGH)
sched_analyze_1 (deps, sub, insn);
else
sched_analyze_2 (deps, sub, insn);
@@ -2978,6 +2987,10 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx_insn *insn)
{
if (GET_CODE (XEXP (link, 0)) == CLOBBER)
sched_analyze_1 (deps, XEXP (link, 0), insn);
+ else if (GET_CODE (XEXP (link, 0)) == CLOBBER_HIGH)
+ /* We could support CLOBBER_HIGH and treat it in the same way as
+ HARD_REGNO_CALL_PART_CLOBBERED, but no port needs that yet. */
+ gcc_unreachable ();
else if (GET_CODE (XEXP (link, 0)) != SET)
sched_analyze_2 (deps, XEXP (link, 0), insn);
}
diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c
index 5976296..824f1ec 100644
--- a/gcc/sel-sched.c
+++ b/gcc/sel-sched.c
@@ -3330,11 +3330,11 @@ sel_target_adjust_priority (expr_t expr)
else
new_priority = priority;
+ gcc_assert (new_priority >= 0);
+
/* If the priority has changed, adjust EXPR_PRIORITY_ADJ accordingly. */
EXPR_PRIORITY_ADJ (expr) = new_priority - EXPR_PRIORITY (expr);
- gcc_assert (EXPR_PRIORITY_ADJ (expr) >= 0);
-
if (sched_verbose >= 4)
sel_print ("sel_target_adjust_priority: insn %d, %d+%d = %d.\n",
INSN_UID (EXPR_INSN_RTX (expr)), EXPR_PRIORITY (expr),
diff --git a/gcc/selftest-diagnostic.c b/gcc/selftest-diagnostic.c
index 837488b..f3c255e 100644
--- a/gcc/selftest-diagnostic.c
+++ b/gcc/selftest-diagnostic.c
@@ -37,6 +37,7 @@ test_diagnostic_context::test_diagnostic_context ()
{
diagnostic_initialize (this, 0);
show_caret = true;
+ show_labels_p = true;
show_column = true;
start_span = start_span_cb;
}
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index a9f2586..b4c6883 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -3604,7 +3604,10 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
gcc_assert (mode == GET_MODE_INNER (GET_MODE (trueop0)));
gcc_assert (GET_CODE (trueop1) == PARALLEL);
gcc_assert (XVECLEN (trueop1, 0) == 1);
- gcc_assert (CONST_INT_P (XVECEXP (trueop1, 0, 0)));
+
+ /* We can't reason about selections made at runtime. */
+ if (!CONST_INT_P (XVECEXP (trueop1, 0, 0)))
+ return 0;
if (vec_duplicate_p (trueop0, &elt0))
return elt0;
@@ -3703,7 +3706,9 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
{
rtx x = XVECEXP (trueop1, 0, i);
- gcc_assert (CONST_INT_P (x));
+ if (!CONST_INT_P (x))
+ return 0;
+
RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop0,
INTVAL (x));
}
diff --git a/gcc/sort.cc b/gcc/sort.cc
index 293e205..b3be1ea 100644
--- a/gcc/sort.cc
+++ b/gcc/sort.cc
@@ -55,6 +55,7 @@ struct sort_ctx
char *out; // output buffer
size_t n; // number of elements
size_t size; // element size
+ size_t nlim; // limit for network sort
};
/* Helper for netsort. Permute, possibly in-place, 2 or 3 elements,
@@ -178,7 +179,7 @@ do { \
static void
mergesort (char *in, sort_ctx *c, size_t n, char *out, char *tmp)
{
- if (likely (n <= 5))
+ if (likely (n <= c->nlim))
{
c->out = out;
c->n = n;
@@ -221,12 +222,25 @@ gcc_qsort (void *vbase, size_t n, size_t size, cmp_fn *cmp)
{
if (n < 2)
return;
+ size_t nlim = 5;
+ bool stable = (ssize_t) size < 0;
+ if (stable)
+ nlim = 3, size = ~size;
char *base = (char *)vbase;
- sort_ctx c = {cmp, base, n, size};
+ sort_ctx c = {cmp, base, n, size, nlim};
long long scratch[32];
size_t bufsz = (n / 2) * size;
void *buf = bufsz <= sizeof scratch ? scratch : xmalloc (bufsz);
mergesort (base, &c, n, base, (char *)buf);
if (buf != scratch)
free (buf);
+#if CHECKING_P
+ qsort_chk (vbase, n, size, cmp);
+#endif
+}
+
+void
+gcc_stablesort (void *vbase, size_t n, size_t size, cmp_fn *cmp)
+{
+ gcc_qsort (vbase, n, ~size, cmp);
}
diff --git a/gcc/spellcheck.c b/gcc/spellcheck.c
index e2a8b92..690e6fa 100644
--- a/gcc/spellcheck.c
+++ b/gcc/spellcheck.c
@@ -162,6 +162,36 @@ find_closest_string (const char *target,
return bm.get_best_meaningful_candidate ();
}
+/* Generate the maximum edit distance for which we consider a suggestion
+ to be meaningful, given a goal of length GOAL_LEN and a candidate of
+ length CANDIDATE_LEN.
+
+ This is a third of the the length of the candidate or of the goal,
+ whichever is bigger. */
+
+edit_distance_t
+get_edit_distance_cutoff (size_t goal_len, size_t candidate_len)
+{
+ size_t max_length = MAX (goal_len, candidate_len);
+ size_t min_length = MIN (goal_len, candidate_len);
+
+ gcc_assert (max_length >= min_length);
+
+ /* Special case: don't offer suggestions for a pair of
+ length == 1 strings (or empty strings). */
+ if (max_length <= 1)
+ return 0;
+
+ /* If the lengths are close, then round down. */
+ if (max_length - min_length <= 1)
+ /* ...but allow an edit distance of at least 1. */
+ return MAX (max_length / 3, 1);
+
+ /* Otherwise, round up (thus giving a little extra leeway to some cases
+ involving insertions/deletions). */
+ return (max_length + 2) / 3;
+}
+
#if CHECKING_P
namespace selftest {
@@ -171,8 +201,8 @@ namespace selftest {
/* Verify that get_edit_distance (A, B) equals the expected value. */
static void
-test_edit_distance_unit_test_oneway (const char *a, const char *b,
- edit_distance_t expected)
+test_get_edit_distance_one_way (const char *a, const char *b,
+ edit_distance_t expected)
{
edit_distance_t actual = get_edit_distance (a, b);
ASSERT_EQ (actual, expected);
@@ -185,11 +215,169 @@ test_edit_distance_unit_test_oneway (const char *a, const char *b,
equal the expected value, to ensure that the function is symmetric. */
static void
-test_get_edit_distance_unit (const char *a, const char *b,
+test_get_edit_distance_both_ways (const char *a, const char *b,
edit_distance_t expected)
{
- test_edit_distance_unit_test_oneway (a, b, expected);
- test_edit_distance_unit_test_oneway (b, a, expected);
+ test_get_edit_distance_one_way (a, b, expected);
+ test_get_edit_distance_one_way (b, a, expected);
+}
+
+/* Verify get_edit_distance for a variety of pairs of pre-canned
+ inputs, comparing against known-good values. */
+
+static void
+test_edit_distances ()
+{
+ test_get_edit_distance_both_ways ("", "nonempty", strlen ("nonempty"));
+ test_get_edit_distance_both_ways ("saturday", "sunday", 3);
+ test_get_edit_distance_both_ways ("foo", "m_foo", 2);
+ test_get_edit_distance_both_ways ("hello_world", "HelloWorld", 3);
+ test_get_edit_distance_both_ways
+ ("the quick brown fox jumps over the lazy dog", "dog", 40);
+ test_get_edit_distance_both_ways
+ ("the quick brown fox jumps over the lazy dog",
+ "the quick brown dog jumps over the lazy fox",
+ 4);
+ test_get_edit_distance_both_ways
+ ("Lorem ipsum dolor sit amet, consectetur adipiscing elit,",
+ "All your base are belong to us",
+ 44);
+ test_get_edit_distance_both_ways ("foo", "FOO", 3);
+ test_get_edit_distance_both_ways ("fee", "deed", 2);
+ test_get_edit_distance_both_ways ("coorzd1", "coordx1", 2);
+ test_get_edit_distance_both_ways ("assert", "sqrt", 3);
+ test_get_edit_distance_both_ways ("PATH_MAX", "INT8_MAX", 3);
+ test_get_edit_distance_both_ways ("time", "nice", 2);
+ test_get_edit_distance_both_ways ("bar", "carg", 2);
+ test_get_edit_distance_both_ways ("gtk_widget_show_all",
+ "GtkWidgetShowAll", 7);
+ test_get_edit_distance_both_ways ("m_bar", "bar", 2);
+ test_get_edit_distance_both_ways ("MACRO", "MACRAME", 3);
+ test_get_edit_distance_both_ways ("ab", "ac", 1);
+ test_get_edit_distance_both_ways ("ab", "a", 1);
+ test_get_edit_distance_both_ways ("a", "b", 1);
+ test_get_edit_distance_both_ways ("nanl", "name", 2);
+ test_get_edit_distance_both_ways ("char", "bar", 2);
+ test_get_edit_distance_both_ways ("-optimize", "fsanitize", 5);
+ test_get_edit_distance_both_ways ("__DATE__", "__i386__", 4);
+
+ /* Examples where transposition helps. */
+ test_get_edit_distance_both_ways ("ab", "ba", 1);
+ test_get_edit_distance_both_ways ("ba", "abc", 2);
+ test_get_edit_distance_both_ways ("coorzd1", "coordz1", 1);
+ test_get_edit_distance_both_ways ("abcdefghijklmnopqrstuvwxyz",
+ "bacdefghijklmnopqrstuvwxzy", 2);
+ test_get_edit_distance_both_ways ("saturday", "sundya", 4);
+ test_get_edit_distance_both_ways ("signed", "singed", 1);
+}
+
+/* Subroutine of test_get_edit_distance_cutoff, for emulating the
+ spellchecking cutoff in up to GCC 8. */
+
+static edit_distance_t
+get_old_cutoff (size_t goal_len, size_t candidate_len)
+{
+ return MAX (goal_len, candidate_len) / 2;
+}
+
+/* Verify that the cutoff for "meaningfulness" of suggestions is at least as
+ conservative as in older GCC releases.
+
+ This should ensure that we don't offer additional meaningless
+ suggestions (apart from those for which transposition has helped). */
+
+static void
+test_get_edit_distance_cutoff ()
+{
+ for (size_t goal_len = 0; goal_len < 30; goal_len++)
+ for (size_t candidate_len = 0; candidate_len < 30; candidate_len++)
+ ASSERT_TRUE (get_edit_distance_cutoff (goal_len, candidate_len)
+ <= get_old_cutoff (goal_len, candidate_len));
+}
+
+/* Assert that CANDIDATE is offered as a suggestion for TARGET. */
+
+static void
+assert_suggested_for (const location &loc, const char *candidate,
+ const char *target)
+{
+ auto_vec<const char *> candidates;
+ candidates.safe_push (candidate);
+ ASSERT_EQ_AT (loc, candidate, find_closest_string (target, &candidates));
+}
+
+/* Assert that CANDIDATE is offered as a suggestion for TARGET. */
+
+#define ASSERT_SUGGESTED_FOR(CANDIDATE, TARGET) \
+ SELFTEST_BEGIN_STMT \
+ assert_suggested_for (SELFTEST_LOCATION, CANDIDATE, TARGET); \
+ SELFTEST_END_STMT
+
+/* Assert that CANDIDATE is not offered as a suggestion for TARGET. */
+
+static void
+assert_not_suggested_for (const location &loc, const char *candidate,
+ const char *target)
+{
+ auto_vec<const char *> candidates;
+ candidates.safe_push (candidate);
+ ASSERT_EQ_AT (loc, NULL, find_closest_string (target, &candidates));
+}
+
+/* Assert that CANDIDATE is not offered as a suggestion for TARGET. */
+
+#define ASSERT_NOT_SUGGESTED_FOR(CANDIDATE, TARGET) \
+ SELFTEST_BEGIN_STMT \
+ assert_not_suggested_for (SELFTEST_LOCATION, CANDIDATE, TARGET); \
+ SELFTEST_END_STMT
+
+/* Verify that we offer varous suggestions that are meaningful,
+ and that we don't offer various other ones that aren't (PR c/82967). */
+
+static void
+test_suggestions ()
+{
+ /* Good suggestions. */
+
+ ASSERT_SUGGESTED_FOR ("m_bar", "bar");
+ // dist == 2, max_length == 5, min_length == 3
+
+ ASSERT_SUGGESTED_FOR ("MACRO", "MACRAME");
+ // dist == 3, max_length == 7, min_length == 5
+
+ ASSERT_SUGGESTED_FOR ("gtk_widget_show_all", "GtkWidgetShowAll");
+ // dist == 7, max_length == 16, min_length = 19
+
+ ASSERT_SUGGESTED_FOR ("ab", "ac");
+ // dist == 1, max_length == min_length = 2
+
+ ASSERT_SUGGESTED_FOR ("ab", "a");
+ // dist == 1, max_length == 2, min_length = 1
+
+ /* Bad suggestions. */
+
+ ASSERT_NOT_SUGGESTED_FOR ("a", "b");
+ // dist == 1, max_length == min_length = 1
+
+ ASSERT_NOT_SUGGESTED_FOR ("sqrt", "assert");
+ // dist == 3, max_length 6, min_length == 4
+
+ ASSERT_NOT_SUGGESTED_FOR ("INT8_MAX", "PATH_MAX");
+ // dist == 3, max_length == min_length == 8
+
+ ASSERT_NOT_SUGGESTED_FOR ("nice", "time");
+ ASSERT_NOT_SUGGESTED_FOR ("nanl", "name");
+ // dist == 2, max_length == min_length == 4
+
+ ASSERT_NOT_SUGGESTED_FOR ("carg", "bar");
+ ASSERT_NOT_SUGGESTED_FOR ("char", "bar");
+ // dist == 2, max_length == 4, min_length == 3
+
+ ASSERT_NOT_SUGGESTED_FOR ("-optimize", "fsanitize");
+ // dist == 5, max_length == min_length == 9
+
+ ASSERT_NOT_SUGGESTED_FOR ("__DATE__", "__i386__");
+ // dist == 4, max_length == min_length == 8
}
/* Verify that find_closest_string is sane. */
@@ -291,39 +479,14 @@ test_metric_conditions ()
}
}
-/* Verify get_edit_distance for a variety of pairs of pre-canned
- inputs, comparing against known-good values. */
+/* Run all of the selftests within this file. */
void
spellcheck_c_tests ()
{
- test_get_edit_distance_unit ("", "nonempty", strlen ("nonempty"));
- test_get_edit_distance_unit ("saturday", "sunday", 3);
- test_get_edit_distance_unit ("foo", "m_foo", 2);
- test_get_edit_distance_unit ("hello_world", "HelloWorld", 3);
- test_get_edit_distance_unit
- ("the quick brown fox jumps over the lazy dog", "dog", 40);
- test_get_edit_distance_unit
- ("the quick brown fox jumps over the lazy dog",
- "the quick brown dog jumps over the lazy fox",
- 4);
- test_get_edit_distance_unit
- ("Lorem ipsum dolor sit amet, consectetur adipiscing elit,",
- "All your base are belong to us",
- 44);
- test_get_edit_distance_unit ("foo", "FOO", 3);
- test_get_edit_distance_unit ("fee", "deed", 2);
- test_get_edit_distance_unit ("coorzd1", "coordx1", 2);
-
- /* Examples where transposition helps. */
- test_get_edit_distance_unit ("ab", "ba", 1);
- test_get_edit_distance_unit ("ba", "abc", 2);
- test_get_edit_distance_unit ("coorzd1", "coordz1", 1);
- test_get_edit_distance_unit ("abcdefghijklmnopqrstuvwxyz",
- "bacdefghijklmnopqrstuvwxzy", 2);
- test_get_edit_distance_unit ("saturday", "sundya", 4);
- test_get_edit_distance_unit ("signed", "singed", 1);
-
+ test_edit_distances ();
+ test_get_edit_distance_cutoff ();
+ test_suggestions ();
test_find_closest_string ();
test_metric_conditions ();
}
diff --git a/gcc/spellcheck.h b/gcc/spellcheck.h
index 41ac16f..e8fa77c 100644
--- a/gcc/spellcheck.h
+++ b/gcc/spellcheck.h
@@ -66,6 +66,9 @@ struct edit_distance_traits<const char *>
}
};
+extern edit_distance_t get_edit_distance_cutoff (size_t goal_len,
+ size_t candidate_len);
+
/* A type for use when determining the best match against a string,
expressed as a template so that we can match against various
string-like types (const char *, frontend identifiers, and preprocessor
@@ -119,7 +122,7 @@ class best_match
/* If the candidate will be unable to beat the criterion in
get_best_meaningful_candidate, reject it without computing
the exact distance. */
- unsigned int cutoff = MAX (m_goal_len, candidate_len) / 2;
+ edit_distance_t cutoff = get_cutoff (candidate_len);
if (min_candidate_distance > cutoff)
return;
@@ -151,17 +154,25 @@ class best_match
m_best_candidate_len = best_candidate_len;
}
+ /* Generate the maximum edit distance for which we consider a suggestion
+ to be meaningful, given a candidate of length CANDIDATE_LEN. */
+
+ edit_distance_t get_cutoff (size_t candidate_len) const
+ {
+ return ::get_edit_distance_cutoff (m_goal_len, candidate_len);
+ }
+
/* Get the best candidate so far, but applying a filter to ensure
that we return NULL if none of the candidates are close to the goal,
to avoid offering nonsensical suggestions to the user. */
candidate_t get_best_meaningful_candidate () const
{
- /* If more than half of the letters were misspelled, the suggestion is
- likely to be meaningless. */
+ /* If the edit distance is too high, the suggestion is likely to be
+ meaningless. */
if (m_best_candidate)
{
- unsigned int cutoff = MAX (m_goal_len, m_best_candidate_len) / 2;
+ edit_distance_t cutoff = get_cutoff (m_best_candidate_len);
if (m_best_distance > cutoff)
return NULL;
}
diff --git a/gcc/sreal.c b/gcc/sreal.c
index 950937a..e17d93a 100644
--- a/gcc/sreal.c
+++ b/gcc/sreal.c
@@ -64,7 +64,7 @@ along with GCC; see the file COPYING3. If not see
void
sreal::dump (FILE *file) const
{
- fprintf (file, "(%" PRIi64 " * 2^%d)", m_sig, m_exp);
+ fprintf (file, "(%" PRIi64 " * 2^%d)", (int64_t)m_sig, m_exp);
}
DEBUG_FUNCTION void
@@ -114,7 +114,7 @@ sreal::to_int () const
if (m_exp >= SREAL_PART_BITS)
return sign * INTTYPE_MAXIMUM (int64_t);
if (m_exp > 0)
- return sign * (SREAL_ABS (m_sig) << m_exp);
+ return sign * (SREAL_ABS ((int64_t)m_sig) << m_exp);
if (m_exp < 0)
return m_sig >> -m_exp;
return m_sig;
@@ -138,7 +138,8 @@ sreal
sreal::operator+ (const sreal &other) const
{
int dexp;
- sreal tmp, r;
+ sreal tmp;
+ int64_t r_sig, r_exp;
const sreal *a_p = this, *b_p = &other, *bb;
@@ -146,10 +147,14 @@ sreal::operator+ (const sreal &other) const
std::swap (a_p, b_p);
dexp = a_p->m_exp - b_p->m_exp;
- r.m_exp = a_p->m_exp;
+ r_exp = a_p->m_exp;
if (dexp > SREAL_BITS)
{
- r.m_sig = a_p->m_sig;
+ r_sig = a_p->m_sig;
+
+ sreal r;
+ r.m_sig = r_sig;
+ r.m_exp = r_exp;
return r;
}
@@ -162,8 +167,8 @@ sreal::operator+ (const sreal &other) const
bb = &tmp;
}
- r.m_sig = a_p->m_sig + bb->m_sig;
- r.normalize ();
+ r_sig = a_p->m_sig + (int64_t)bb->m_sig;
+ sreal r (r_sig, r_exp);
return r;
}
@@ -174,7 +179,8 @@ sreal
sreal::operator- (const sreal &other) const
{
int dexp;
- sreal tmp, r;
+ sreal tmp;
+ int64_t r_sig, r_exp;
const sreal *bb;
const sreal *a_p = this, *b_p = &other;
@@ -186,10 +192,14 @@ sreal::operator- (const sreal &other) const
}
dexp = a_p->m_exp - b_p->m_exp;
- r.m_exp = a_p->m_exp;
+ r_exp = a_p->m_exp;
if (dexp > SREAL_BITS)
{
- r.m_sig = sign * a_p->m_sig;
+ r_sig = sign * a_p->m_sig;
+
+ sreal r;
+ r.m_sig = r_sig;
+ r.m_exp = r_exp;
return r;
}
if (dexp == 0)
@@ -201,8 +211,8 @@ sreal::operator- (const sreal &other) const
bb = &tmp;
}
- r.m_sig = sign * (a_p->m_sig - bb->m_sig);
- r.normalize ();
+ r_sig = sign * ((int64_t) a_p->m_sig - (int64_t)bb->m_sig);
+ sreal r (r_sig, r_exp);
return r;
}
@@ -212,17 +222,14 @@ sreal
sreal::operator* (const sreal &other) const
{
sreal r;
- if (absu_hwi (m_sig) < SREAL_MIN_SIG || absu_hwi (other.m_sig) < SREAL_MIN_SIG)
+ if (absu_hwi (m_sig) < SREAL_MIN_SIG
+ || absu_hwi (other.m_sig) < SREAL_MIN_SIG)
{
r.m_sig = 0;
r.m_exp = -SREAL_MAX_EXP;
}
else
- {
- r.m_sig = m_sig * other.m_sig;
- r.m_exp = m_exp + other.m_exp;
- r.normalize ();
- }
+ r.normalize (m_sig * (int64_t) other.m_sig, m_exp + other.m_exp);
return r;
}
@@ -233,11 +240,9 @@ sreal
sreal::operator/ (const sreal &other) const
{
gcc_checking_assert (other.m_sig != 0);
- sreal r;
- r.m_sig
- = SREAL_SIGN (m_sig) * (SREAL_ABS (m_sig) << SREAL_PART_BITS) / other.m_sig;
- r.m_exp = m_exp - other.m_exp - SREAL_PART_BITS;
- r.normalize ();
+ sreal r (SREAL_SIGN (m_sig)
+ * ((int64_t)SREAL_ABS (m_sig) << SREAL_PART_BITS) / other.m_sig,
+ m_exp - other.m_exp - SREAL_PART_BITS);
return r;
}
@@ -272,15 +277,15 @@ namespace selftest {
static void
sreal_verify_basics (void)
{
- sreal minimum = INT_MIN;
- sreal maximum = INT_MAX;
+ sreal minimum = INT_MIN/2;
+ sreal maximum = INT_MAX/2;
sreal seven = 7;
sreal minus_two = -2;
sreal minus_nine = -9;
- ASSERT_EQ (INT_MIN, minimum.to_int ());
- ASSERT_EQ (INT_MAX, maximum.to_int ());
+ ASSERT_EQ (INT_MIN/2, minimum.to_int ());
+ ASSERT_EQ (INT_MAX/2, maximum.to_int ());
ASSERT_FALSE (minus_two < minus_two);
ASSERT_FALSE (seven < seven);
diff --git a/gcc/sreal.h b/gcc/sreal.h
index 91ae526..e2ad1a3 100644
--- a/gcc/sreal.h
+++ b/gcc/sreal.h
@@ -20,8 +20,7 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_SREAL_H
#define GCC_SREAL_H
-/* SREAL_PART_BITS has to be an even number. */
-#define SREAL_PART_BITS 32
+#define SREAL_PART_BITS 31
#define UINT64_BITS 64
@@ -45,9 +44,9 @@ public:
sreal () : m_sig (-1), m_exp (-1) {}
/* Construct a sreal. */
- sreal (int64_t sig, int exp = 0) : m_sig (sig), m_exp (exp)
+ sreal (int64_t sig, int exp = 0)
{
- normalize ();
+ normalize (sig, exp);
}
void dump (FILE *) const;
@@ -130,14 +129,14 @@ public:
}
private:
- inline void normalize ();
- inline void normalize_up ();
- inline void normalize_down ();
+ inline void normalize (int64_t new_sig, signed int new_exp);
+ inline void normalize_up (int64_t new_sig, signed int new_exp);
+ inline void normalize_down (int64_t new_sig, signed int new_exp);
void shift_right (int amount);
static sreal signedless_plus (const sreal &a, const sreal &b, bool negative);
static sreal signedless_minus (const sreal &a, const sreal &b, bool negative);
- int64_t m_sig; /* Significant. */
+ int32_t m_sig; /* Significant. */
signed int m_exp; /* Exponent. */
};
@@ -199,23 +198,24 @@ inline sreal operator>> (const sreal &a, int exp)
Make this separate method so inliner can handle hot path better. */
inline void
-sreal::normalize_up ()
+sreal::normalize_up (int64_t new_sig, signed int new_exp)
{
- unsigned HOST_WIDE_INT sig = absu_hwi (m_sig);
+ unsigned HOST_WIDE_INT sig = absu_hwi (new_sig);
int shift = SREAL_PART_BITS - 2 - floor_log2 (sig);
gcc_checking_assert (shift > 0);
sig <<= shift;
- m_exp -= shift;
+ new_exp -= shift;
gcc_checking_assert (sig <= SREAL_MAX_SIG && sig >= SREAL_MIN_SIG);
/* Check underflow. */
- if (m_exp < -SREAL_MAX_EXP)
+ if (new_exp < -SREAL_MAX_EXP)
{
- m_exp = -SREAL_MAX_EXP;
+ new_exp = -SREAL_MAX_EXP;
sig = 0;
}
- if (SREAL_SIGN (m_sig) == -1)
+ m_exp = new_exp;
+ if (SREAL_SIGN (new_sig) == -1)
m_sig = -sig;
else
m_sig = sig;
@@ -226,16 +226,16 @@ sreal::normalize_up ()
Make this separate method so inliner can handle hot path better. */
inline void
-sreal::normalize_down ()
+sreal::normalize_down (int64_t new_sig, signed int new_exp)
{
int last_bit;
- unsigned HOST_WIDE_INT sig = absu_hwi (m_sig);
+ unsigned HOST_WIDE_INT sig = absu_hwi (new_sig);
int shift = floor_log2 (sig) - SREAL_PART_BITS + 2;
gcc_checking_assert (shift > 0);
last_bit = (sig >> (shift-1)) & 1;
sig >>= shift;
- m_exp += shift;
+ new_exp += shift;
gcc_checking_assert (sig <= SREAL_MAX_SIG && sig >= SREAL_MIN_SIG);
/* Round the number. */
@@ -243,16 +243,17 @@ sreal::normalize_down ()
if (sig > SREAL_MAX_SIG)
{
sig >>= 1;
- m_exp++;
+ new_exp++;
}
/* Check overflow. */
- if (m_exp > SREAL_MAX_EXP)
+ if (new_exp > SREAL_MAX_EXP)
{
- m_exp = SREAL_MAX_EXP;
+ new_exp = SREAL_MAX_EXP;
sig = SREAL_MAX_SIG;
}
- if (SREAL_SIGN (m_sig) == -1)
+ m_exp = new_exp;
+ if (SREAL_SIGN (new_sig) == -1)
m_sig = -sig;
else
m_sig = sig;
@@ -261,16 +262,24 @@ sreal::normalize_down ()
/* Normalize *this; the hot path. */
inline void
-sreal::normalize ()
+sreal::normalize (int64_t new_sig, signed int new_exp)
{
- unsigned HOST_WIDE_INT sig = absu_hwi (m_sig);
+ unsigned HOST_WIDE_INT sig = absu_hwi (new_sig);
if (sig == 0)
- m_exp = -SREAL_MAX_EXP;
+ {
+ m_sig = 0;
+ m_exp = -SREAL_MAX_EXP;
+ }
else if (sig > SREAL_MAX_SIG)
- normalize_down ();
+ normalize_down (new_sig, new_exp);
else if (sig < SREAL_MIN_SIG)
- normalize_up ();
+ normalize_up (new_sig, new_exp);
+ else
+ {
+ m_sig = new_sig;
+ m_exp = new_exp;
+ }
}
#endif
diff --git a/gcc/stmt.c b/gcc/stmt.c
index b8df181..0735598 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -81,8 +81,6 @@ struct simple_case_node
/* Label to jump to when node matches. */
tree m_code_label;
};
-
-extern basic_block label_to_block_fn (struct function *, tree);
static bool check_unique_operand_names (tree, tree, tree);
static char *resolve_operand_name_1 (char *, tree, tree, tree);
@@ -907,7 +905,7 @@ expand_case (gswitch *stmt)
/* Find the default case target label. */
tree default_lab = CASE_LABEL (gimple_switch_default_label (stmt));
default_label = jump_target_rtx (default_lab);
- basic_block default_bb = label_to_block_fn (cfun, default_lab);
+ basic_block default_bb = label_to_block (cfun, default_lab);
edge default_edge = find_edge (bb, default_bb);
/* Get upper and lower bounds of case values. */
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index cb377ca..58a3aa3 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -390,7 +390,6 @@ int_mode_for_mode (machine_mode mode)
case MODE_VECTOR_ACCUM:
case MODE_VECTOR_UFRACT:
case MODE_VECTOR_UACCUM:
- case MODE_POINTER_BOUNDS:
return int_mode_for_size (GET_MODE_BITSIZE (mode), 0);
case MODE_RANDOM:
@@ -761,14 +760,19 @@ layout_decl (tree decl, unsigned int known_align)
{
tree size = DECL_SIZE_UNIT (decl);
- if (size != 0 && TREE_CODE (size) == INTEGER_CST
- && compare_tree_int (size, warn_larger_than_size) > 0)
+ if (size != 0 && TREE_CODE (size) == INTEGER_CST)
{
- unsigned HOST_WIDE_INT uhwisize = tree_to_uhwi (size);
-
- warning (OPT_Wlarger_than_, "size of %q+D %wu bytes exceeds "
- "maximum object size %wu",
- decl, uhwisize, warn_larger_than_size);
+ /* -Wlarger-than= argument of HOST_WIDE_INT_MAX is treated
+ as if PTRDIFF_MAX had been specified, with the value
+ being that on the target rather than the host. */
+ unsigned HOST_WIDE_INT max_size = warn_larger_than_size;
+ if (max_size == HOST_WIDE_INT_MAX)
+ max_size = tree_to_shwi (TYPE_MAX_VALUE (ptrdiff_type_node));
+
+ if (compare_tree_int (size, max_size) > 0)
+ warning (OPT_Wlarger_than_, "size of %q+D %E bytes exceeds "
+ "maximum object size %wu",
+ decl, size, max_size);
}
}
@@ -1682,14 +1686,21 @@ place_field (record_layout_info rli, tree field)
{
rli->bitpos = size_binop (PLUS_EXPR, rli->bitpos, DECL_SIZE (field));
- /* If we ended a bitfield before the full length of the type then
- pad the struct out to the full length of the last type. */
- if ((DECL_CHAIN (field) == NULL
- || TREE_CODE (DECL_CHAIN (field)) != FIELD_DECL)
- && DECL_BIT_FIELD_TYPE (field)
+ /* If FIELD is the last field and doesn't end at the full length
+ of the type then pad the struct out to the full length of the
+ last type. */
+ if (DECL_BIT_FIELD_TYPE (field)
&& !integer_zerop (DECL_SIZE (field)))
- rli->bitpos = size_binop (PLUS_EXPR, rli->bitpos,
- bitsize_int (rli->remaining_in_alignment));
+ {
+ /* We have to scan, because non-field DECLS are also here. */
+ tree probe = field;
+ while ((probe = DECL_CHAIN (probe)))
+ if (TREE_CODE (probe) == FIELD_DECL)
+ break;
+ if (!probe)
+ rli->bitpos = size_binop (PLUS_EXPR, rli->bitpos,
+ bitsize_int (rli->remaining_in_alignment));
+ }
normalize_rli (rli);
}
diff --git a/gcc/substring-locations.c b/gcc/substring-locations.c
index 2d7f0c1..db88f20 100644
--- a/gcc/substring-locations.c
+++ b/gcc/substring-locations.c
@@ -26,13 +26,12 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "langhooks.h"
#include "substring-locations.h"
+#include "gcc-rich-location.h"
-/* Emit a warning governed by option OPT, using SINGULAR_GMSGID as the
- format string (or if PLURAL_GMSGID is different from SINGULAR_GMSGID,
- using SINGULAR_GMSGID, PLURAL_GMSGID and N as arguments to ngettext)
- and AP as its arguments.
+/* format_string_diagnostic_t's ctor, giving information for use by
+ the emit_warning* member functions, as follows:
- Attempt to obtain precise location information within a string
+ They attempt to obtain precise location information within a string
literal from FMT_LOC.
Case 1: if substring location is available, and is within the range of
@@ -48,7 +47,7 @@ along with GCC; see the file COPYING3. If not see
Case 2: if the substring location is available, but is not within
the range of the format string, the primary location is that of the
- format string, and an note is emitted showing the substring location.
+ format string, and a note is emitted showing the substring location.
For example:
test.c:90:10: warning: problem with '%i' here [-Wformat=]
@@ -89,6 +88,27 @@ along with GCC; see the file COPYING3. If not see
printf(fmt, msg);
^~~ ~~~
+ If non-NULL, then FMT_LABEL will be used to label the location within the
+ string for cases 1 and 2; if non-NULL, then PARAM_LABEL will be used to label
+ the parameter. For example with case 1:
+
+ test.c:90:16: warning: '%s' here but arg 2 has 'long' type [-Wformat=]
+ printf ("foo %s bar", long_i + long_j);
+ ~^ ~~~~~~~~~~~~~~~
+ |
+ int
+
+ and with case 2:
+
+ test.c:90:10: warning: problem with '%i' here [-Wformat=]
+ printf("hello " INT_FMT " world", msg);
+ ^~~~~~~~~~~~~~~~~~~~~~~~~
+ test.c:19: note: format string is defined here
+ #define INT_FMT "%i"
+ ~^
+ |
+ int
+
If CORRECTED_SUBSTRING is non-NULL, use it for cases 1 and 2 to provide
a fix-it hint, suggesting that it should replace the text within the
substring range. For example:
@@ -98,27 +118,47 @@ along with GCC; see the file COPYING3. If not see
~^
%s
+*/
+
+format_string_diagnostic_t::
+format_string_diagnostic_t (const substring_loc &fmt_loc,
+ const range_label *fmt_label,
+ location_t param_loc,
+ const range_label *param_label,
+ const char *corrected_substring)
+: m_fmt_loc (fmt_loc),
+ m_fmt_label (fmt_label),
+ m_param_loc (param_loc),
+ m_param_label (param_label),
+ m_corrected_substring (corrected_substring)
+{
+}
+
+/* Emit a warning governed by option OPT, using SINGULAR_GMSGID as the
+ format string (or if PLURAL_GMSGID is different from SINGULAR_GMSGID,
+ using SINGULAR_GMSGID, PLURAL_GMSGID and N as arguments to ngettext)
+ and AP as its arguments.
+
Return true if a warning was emitted, false otherwise. */
bool
-format_warning_n_va (const substring_loc &fmt_loc,
- location_t param_loc,
- const char *corrected_substring,
- int opt, unsigned HOST_WIDE_INT n,
- const char *singular_gmsgid,
- const char *plural_gmsgid, va_list *ap)
+format_string_diagnostic_t::emit_warning_n_va (int opt,
+ unsigned HOST_WIDE_INT n,
+ const char *singular_gmsgid,
+ const char *plural_gmsgid,
+ va_list *ap) const
{
bool substring_within_range = false;
location_t primary_loc;
location_t fmt_substring_loc = UNKNOWN_LOCATION;
source_range fmt_loc_range
- = get_range_from_loc (line_table, fmt_loc.get_fmt_string_loc ());
- const char *err = fmt_loc.get_location (&fmt_substring_loc);
+ = get_range_from_loc (line_table, m_fmt_loc.get_fmt_string_loc ());
+ const char *err = m_fmt_loc.get_location (&fmt_substring_loc);
source_range fmt_substring_range
= get_range_from_loc (line_table, fmt_substring_loc);
if (err)
/* Case 3: unable to get substring location. */
- primary_loc = fmt_loc.get_fmt_string_loc ();
+ primary_loc = m_fmt_loc.get_fmt_string_loc ();
else
{
if (fmt_substring_range.m_start >= fmt_loc_range.m_start
@@ -134,17 +174,23 @@ format_warning_n_va (const substring_loc &fmt_loc,
/* Case 2. */
{
substring_within_range = false;
- primary_loc = fmt_loc.get_fmt_string_loc ();
+ primary_loc = m_fmt_loc.get_fmt_string_loc ();
}
}
- rich_location richloc (line_table, primary_loc);
+ /* Only use fmt_label in the initial warning for case 1. */
+ const range_label *primary_label = NULL;
+ if (substring_within_range)
+ primary_label = m_fmt_label;
+
+ auto_diagnostic_group d;
+ gcc_rich_location richloc (primary_loc, primary_label);
- if (param_loc != UNKNOWN_LOCATION)
- richloc.add_range (param_loc, false);
+ if (m_param_loc != UNKNOWN_LOCATION)
+ richloc.add_range (m_param_loc, SHOW_RANGE_WITHOUT_CARET, m_param_label);
- if (!err && corrected_substring && substring_within_range)
- richloc.add_fixit_replace (fmt_substring_range, corrected_substring);
+ if (!err && m_corrected_substring && substring_within_range)
+ richloc.add_fixit_replace (fmt_substring_range, m_corrected_substring);
diagnostic_info diagnostic;
if (singular_gmsgid != plural_gmsgid)
@@ -173,10 +219,12 @@ format_warning_n_va (const substring_loc &fmt_loc,
/* Case 2. */
if (warned)
{
- rich_location substring_richloc (line_table, fmt_substring_loc);
- if (corrected_substring)
+ /* Use fmt_label in the note for case 2. */
+ rich_location substring_richloc (line_table, fmt_substring_loc,
+ m_fmt_label);
+ if (m_corrected_substring)
substring_richloc.add_fixit_replace (fmt_substring_range,
- corrected_substring);
+ m_corrected_substring);
inform (&substring_richloc,
"format string is defined here");
}
@@ -187,47 +235,38 @@ format_warning_n_va (const substring_loc &fmt_loc,
/* Singular-only version of the above. */
bool
-format_warning_va (const substring_loc &fmt_loc,
- location_t param_loc,
- const char *corrected_substring,
- int opt, const char *gmsgid, va_list *ap)
+format_string_diagnostic_t::emit_warning_va (int opt, const char *gmsgid,
+ va_list *ap) const
{
- return format_warning_n_va (fmt_loc, param_loc, corrected_substring, opt,
- 0, gmsgid, gmsgid, ap);
+ return emit_warning_n_va (opt, 0, gmsgid, gmsgid, ap);
}
-/* Variadic call to format_warning_va. */
+/* Variadic version of the above (singular only). */
bool
-format_warning_at_substring (const substring_loc &fmt_loc,
- location_t param_loc,
- const char *corrected_substring,
- int opt, const char *gmsgid, ...)
+format_string_diagnostic_t::emit_warning (int opt, const char *gmsgid,
+ ...) const
{
va_list ap;
va_start (ap, gmsgid);
- bool warned = format_warning_va (fmt_loc, param_loc, corrected_substring,
- opt, gmsgid, &ap);
+ bool warned = emit_warning_va (opt, gmsgid, &ap);
va_end (ap);
return warned;
}
-/* Variadic call to format_warning_n_va. */
+/* Variadic version of the above (singular vs plural). */
bool
-format_warning_at_substring_n (const substring_loc &fmt_loc,
- location_t param_loc,
- const char *corrected_substring,
- int opt, unsigned HOST_WIDE_INT n,
- const char *singular_gmsgid,
- const char *plural_gmsgid, ...)
+format_string_diagnostic_t::emit_warning_n (int opt, unsigned HOST_WIDE_INT n,
+ const char *singular_gmsgid,
+ const char *plural_gmsgid,
+ ...) const
{
va_list ap;
va_start (ap, plural_gmsgid);
- bool warned = format_warning_n_va (fmt_loc, param_loc, corrected_substring,
- opt, n, singular_gmsgid, plural_gmsgid,
- &ap);
+ bool warned = emit_warning_n_va (opt, n, singular_gmsgid, plural_gmsgid,
+ &ap);
va_end (ap);
return warned;
diff --git a/gcc/substring-locations.h b/gcc/substring-locations.h
index fca6fd3..caac537 100644
--- a/gcc/substring-locations.h
+++ b/gcc/substring-locations.h
@@ -74,35 +74,43 @@ class substring_loc
int m_end_idx;
};
-/* Functions for emitting a warning about a format string. */
-
-extern bool format_warning_va (const substring_loc &fmt_loc,
- location_t param_loc,
- const char *corrected_substring,
- int opt, const char *gmsgid, va_list *ap)
- ATTRIBUTE_GCC_DIAG (5, 0);
-
-extern bool format_warning_n_va (const substring_loc &fmt_loc,
- location_t param_loc,
- const char *corrected_substring,
- int opt, unsigned HOST_WIDE_INT n,
- const char *singular_gmsgid,
- const char *plural_gmsgid, va_list *ap)
- ATTRIBUTE_GCC_DIAG (6, 0) ATTRIBUTE_GCC_DIAG (7, 0);
-
-extern bool format_warning_at_substring (const substring_loc &fmt_loc,
- location_t param_loc,
- const char *corrected_substring,
- int opt, const char *gmsgid, ...)
- ATTRIBUTE_GCC_DIAG (5, 6);
-
-extern bool format_warning_at_substring_n (const substring_loc &fmt_loc,
- location_t param_loc,
- const char *corrected_substring,
- int opt, unsigned HOST_WIDE_INT n,
- const char *singular_gmsgid,
- const char *plural_gmsgid, ...)
- ATTRIBUTE_GCC_DIAG (6, 8) ATTRIBUTE_GCC_DIAG (7, 8);
+/* A bundle of state for emitting a diagnostic relating to a format string. */
+
+class format_string_diagnostic_t
+{
+ public:
+ format_string_diagnostic_t (const substring_loc &fmt_loc,
+ const range_label *fmt_label,
+ location_t param_loc,
+ const range_label *param_label,
+ const char *corrected_substring);
+
+ /* Functions for emitting a warning about a format string. */
+
+ bool emit_warning_va (int opt, const char *gmsgid, va_list *ap) const
+ ATTRIBUTE_GCC_DIAG (3, 0);
+
+ bool emit_warning_n_va (int opt, unsigned HOST_WIDE_INT n,
+ const char *singular_gmsgid,
+ const char *plural_gmsgid, va_list *ap) const
+ ATTRIBUTE_GCC_DIAG (4, 0) ATTRIBUTE_GCC_DIAG (5, 0);
+
+ bool emit_warning (int opt, const char *gmsgid, ...) const
+ ATTRIBUTE_GCC_DIAG (3, 4);
+
+ bool emit_warning_n (int opt, unsigned HOST_WIDE_INT n,
+ const char *singular_gmsgid,
+ const char *plural_gmsgid, ...) const
+ ATTRIBUTE_GCC_DIAG (4, 6) ATTRIBUTE_GCC_DIAG (5, 6);
+
+ private:
+ const substring_loc &m_fmt_loc;
+ const range_label *m_fmt_label;
+ location_t m_param_loc;
+ const range_label *m_param_label;
+ const char *m_corrected_substring;
+};
+
/* Implementation detail, for use when implementing
LANG_HOOKS_GET_SUBSTRING_LOCATION. */
diff --git a/gcc/symtab.c b/gcc/symtab.c
index c5464cb..3cf1f62 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -2323,7 +2323,7 @@ symtab_node::output_to_lto_symbol_table_p (void)
return false;
/* FIXME: Builtins corresponding to real functions probably should have
symbol table entries. */
- if (is_builtin_fn (decl))
+ if (TREE_CODE (decl) == FUNCTION_DECL && fndecl_built_in_p (decl))
return false;
/* We have real symbol that should be in symbol table. However try to trim
diff --git a/gcc/system.h b/gcc/system.h
index f87fbaa..100feb5 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -1197,17 +1197,15 @@ helper_const_non_const_cast (const char *p)
/* Get definitions of HOST_WIDE_INT. */
#include "hwint.h"
-/* qsort comparator consistency checking: except in release-checking compilers,
- redirect 4-argument qsort calls to qsort_chk; keep 1-argument invocations
+/* GCC qsort API-compatible functions: except in release-checking compilers,
+ redirect 4-argument qsort calls to gcc_qsort; keep 1-argument invocations
corresponding to vec::qsort (cmp): they use C qsort internally anyway. */
void qsort_chk (void *, size_t, size_t, int (*)(const void *, const void *));
void gcc_qsort (void *, size_t, size_t, int (*)(const void *, const void *));
+void gcc_stablesort (void *, size_t, size_t,
+ int (*)(const void *, const void *));
#define PP_5th(a1, a2, a3, a4, a5, ...) a5
#undef qsort
-#if CHECKING_P
-#define qsort(...) PP_5th (__VA_ARGS__, qsort_chk, 3, 2, qsort, 0) (__VA_ARGS__)
-#else
#define qsort(...) PP_5th (__VA_ARGS__, gcc_qsort, 3, 2, qsort, 0) (__VA_ARGS__)
-#endif
#endif /* ! GCC_SYSTEM_H */
diff --git a/gcc/target.def b/gcc/target.def
index 2598d3c..9e22423 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -4156,6 +4156,46 @@ DEFHOOK
hook_bool_void_true)
DEFHOOK
+(have_speculation_safe_value,
+"This hook is used to determine the level of target support for\n\
+ @code{__builtin_speculation_safe_value}. If called with an argument\n\
+ of false, it returns true if the target has been modified to support\n\
+ this builtin. If called with an argument of true, it returns true\n\
+ if the target requires active mitigation execution might be speculative.\n\
+ \n\
+ The default implementation returns false if the target does not define\n\
+ a pattern named @code{speculation_barrier}. Else it returns true\n\
+ for the first case and whether the pattern is enabled for the current\n\
+ compilation for the second case.\n\
+ \n\
+ For targets that have no processors that can execute instructions\n\
+ speculatively an alternative implemenation of this hook is available:\n\
+ simply redefine this hook to @code{speculation_safe_value_not_needed}\n\
+ along with your other target hooks.",
+bool, (bool active), default_have_speculation_safe_value)
+
+DEFHOOK
+(speculation_safe_value,
+"This target hook can be used to generate a target-specific code\n\
+ sequence that implements the @code{__builtin_speculation_safe_value}\n\
+ built-in function. The function must always return @var{val} in\n\
+ @var{result} in mode @var{mode} when the cpu is not executing\n\
+ speculatively, but must never return that when speculating until it\n\
+ is known that the speculation will not be unwound. The hook supports\n\
+ two primary mechanisms for implementing the requirements. The first\n\
+ is to emit a speculation barrier which forces the processor to wait\n\
+ until all prior speculative operations have been resolved; the second\n\
+ is to use a target-specific mechanism that can track the speculation\n\
+ state and to return @var{failval} if it can determine that\n\
+ speculation must be unwound at a later time.\n\
+ \n\
+ The default implementation simply copies @var{val} to @var{result} and\n\
+ emits a @code{speculation_barrier} instruction if that is defined.",
+rtx, (machine_mode mode, rtx result, rtx val, rtx failval),
+ default_speculation_safe_value)
+
+
+DEFHOOK
(can_use_doloop_p,
"Return true if it is possible to use low-overhead loops (@code{doloop_end}\n\
and @code{doloop_begin}) for a particular loop. @var{iterations} gives the\n\
@@ -4945,21 +4985,22 @@ If this hook is not defined, @var{addr} will be used for function calls.",
DEFHOOKPOD
(custom_function_descriptors,
- "This hook should be defined to a power of 2 if the target will benefit\n\
-from the use of custom descriptors for nested functions instead of the\n\
-standard trampolines. Such descriptors are created at run time on the\n\
-stack and made up of data only, but they are non-standard so the generated\n\
-code must be prepared to deal with them. This hook should be defined to 0\n\
-if the target uses function descriptors for its standard calling sequence,\n\
-like for example HP-PA or IA-64. Using descriptors for nested functions\n\
+ "If the target can use GCC's generic descriptor mechanism for nested\n\
+functions, define this hook to a power of 2 representing an unused bit\n\
+in function pointers which can be used to differentiate descriptors at\n\
+run time. This value gives the number of bytes by which descriptor\n\
+pointers are misaligned compared to function pointers. For example, on\n\
+targets that require functions to be aligned to a 4-byte boundary, a\n\
+value of either 1 or 2 is appropriate unless the architecture already\n\
+reserves the bit for another purpose, such as on ARM.\n\
+\n\
+Define this hook to 0 if the target implements ABI support for\n\
+function descriptors in its standard calling sequence, like for example\n\
+HPPA or IA-64.\n\
+\n\
+Using descriptors for nested functions\n\
eliminates the need for trampolines that reside on the stack and require\n\
-it to be made executable.\n\
-\n\
-The value of the macro is used to parameterize the run-time identification\n\
-scheme implemented to distinguish descriptors from function addresses: it\n\
-gives the number of bytes by which their address is misaligned compared\n\
-with function addresses. The value of 1 will generally work, unless it is\n\
-already reserved by the target for another purpose, like for example on ARM.",\
+it to be made executable.",\
int, -1)
/* Return the number of bytes of its own arguments that a function
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 9b06d7a..afd56f3 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -2154,6 +2154,23 @@ std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
if (indirect)
type = build_pointer_type (type);
+ if (targetm.calls.split_complex_arg
+ && TREE_CODE (type) == COMPLEX_TYPE
+ && targetm.calls.split_complex_arg (type))
+ {
+ tree real_part, imag_part;
+
+ real_part = std_gimplify_va_arg_expr (valist,
+ TREE_TYPE (type), pre_p, NULL);
+ real_part = get_initialized_tmp_var (real_part, pre_p, NULL);
+
+ imag_part = std_gimplify_va_arg_expr (unshare_expr (valist),
+ TREE_TYPE (type), pre_p, NULL);
+ imag_part = get_initialized_tmp_var (imag_part, pre_p, NULL);
+
+ return build2 (COMPLEX_EXPR, type, real_part, imag_part);
+ }
+
align = PARM_BOUNDARY / BITS_PER_UNIT;
boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
@@ -2314,4 +2331,43 @@ default_preferred_else_value (unsigned, tree type, unsigned, tree *)
return build_zero_cst (type);
}
+/* Default implementation of TARGET_HAVE_SPECULATION_SAFE_VALUE. */
+bool
+default_have_speculation_safe_value (bool active ATTRIBUTE_UNUSED)
+{
+#ifdef HAVE_speculation_barrier
+ return active ? HAVE_speculation_barrier : true;
+#else
+ return false;
+#endif
+}
+/* Alternative implementation of TARGET_HAVE_SPECULATION_SAFE_VALUE
+ that can be used on targets that never have speculative execution. */
+bool
+speculation_safe_value_not_needed (bool active)
+{
+ return !active;
+}
+
+/* Default implementation of the speculation-safe-load builtin. This
+ implementation simply copies val to result and generates a
+ speculation_barrier insn, if such a pattern is defined. */
+rtx
+default_speculation_safe_value (machine_mode mode ATTRIBUTE_UNUSED,
+ rtx result, rtx val,
+ rtx failval ATTRIBUTE_UNUSED)
+{
+ emit_move_insn (result, val);
+
+#ifdef HAVE_speculation_barrier
+ /* Assume the target knows what it is doing: if it defines a
+ speculation barrier, but it is not enabled, then assume that one
+ isn't needed. */
+ if (HAVE_speculation_barrier)
+ emit_insn (gen_speculation_barrier ());
+#endif
+
+ return result;
+}
+
#include "gt-targhooks.h"
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 76fcec8..f92ca5c 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -281,4 +281,8 @@ extern bool default_stack_clash_protection_final_dynamic_probe (rtx);
extern void default_select_early_remat_modes (sbitmap);
extern tree default_preferred_else_value (unsigned, tree, unsigned, tree *);
+extern bool default_have_speculation_safe_value (bool);
+extern bool speculation_safe_value_not_needed (bool);
+extern rtx default_speculation_safe_value (machine_mode, rtx, rtx, rtx);
+
#endif /* GCC_TARGHOOKS_H */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7aa44c2..2243179 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,2025 @@
+2018-09-24 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/85070
+ * g++.dg/cpp0x/pr85070.C: New.
+
+2018-09-24 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/82699
+ * gcc.target/i386/pr82699-1.c: New file.
+ * gcc.target/i386/pr82699-2.c: Likewise.
+ * gcc.target/i386/pr82699-3.c: Likewise.
+ * gcc.target/i386/pr82699-4.c: Likewise.
+ * gcc.target/i386/pr82699-5.c: Likewise.
+ * gcc.target/i386/pr82699-6.c: Likewise.
+
+2018-09-24 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/87401
+ * gfortran.dg/intent_out_12.f90: New test.
+
+2018-09-24 Will Schmidt <will_schmidt@vnet.ibm.com>
+
+ PR testsuite/86952
+ * gcc.target/powerpc/p8-vec-xl-xst-v2.c: Add and
+ update expected codegen
+
+2018-09-24 Cesar Philippidis <cesar@codesourcery.com>
+
+ * gfortran.dg/goacc/nested-parallelism.f90: New test.
+
+2018-09-24 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ PR target/80080
+ * gcc.target/s390/risbg-ll-3.c: Expect conditional returns.
+ * gcc.target/s390/zvector/vec-cmp-2.c: Likewise.
+
+2018-09-24 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/85774
+ * g++.dg/asan/pr85774.C: New test.
+
+2018-09-24 Alexandre Oliva <oliva@adacore.com>
+
+ PR middle-end/87054
+ * gcc.dg/pr87054.c: Adjust for no __int128 on x86.
+
+2018-09-23 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/87395
+ * gfortran.dg/intent_out_11.f90: New test.
+
+2018-09-23 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * gfortran.dg/coarray_lib_alloc_4.f90: Fix scan patterns.
+ * gfortran.dg/coarray_lock_7.f90: Likewise.
+
+2018-09-23 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/87395
+ * gfortran.dg/intent_out_10.f90: New test.
+
+2018-09-22 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/41453
+ * gfortran.dg/intent_optimize_2.f90: New test.
+
+2018-09-22 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR fortran/87318
+ * gfortran.dg/dtio_1.f90: Update test to valid code.
+
+2018-09-22 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/85603
+ * gfortran.dg/deferred_character_23.f90 : New test.
+
+2018-09-21 Jeff Law <law@redhat.com>
+
+ * gcc.dg/tree-ssa/vrp113.c: Disable EVRP.
+ * gcc.dg/tree-ssa/vrp120.c: New test.
+
+2018-09-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87372 - __func__ constexpr evaluation.
+ * g++.dg/cpp1y/func_constexpr2.C: New test.
+
+2018-09-21 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/77325
+ * gfortran.dg/deferred_character_22.f90 : New test.
+
+2018-09-21 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/87359
+ * gfortran.dg/finalize_33.f90 : New test.
+
+2018-09-21 David Malcolm <dmalcolm@redhat.com>
+
+ PR tree-optimization/87309
+ * gcc.dg/pr87309.c: New test.
+
+2018-09-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * c-c++-common/dump-ada-spec-14.c: New test.
+
+2018-09-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/nested-func-11.c: New test.
+
+ * lib/target-supports.exp (check_effective_target_tls_runtime): Make
+ more robust and remove target-specific handling.
+
+2018-09-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.c-torture/execute/20180921-1.c: New test.
+
+2018-09-20 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87109 - wrong ctor with maybe-rvalue semantics.
+ * g++.dg/cpp0x/ref-qual19.C: Adjust the expected results.
+ * g++.dg/cpp0x/ref-qual20.C: New test.
+
+2018-09-20 Allan Sandfeld Jensen <allan.jensen@qt.io>
+
+ * g++.dg/ipa/pr64059.C: Removed now redundant -nostdlib.
+ * g++.dg/lto/20081109-1_0.C: Likewise.
+ * g++.dg/lto/20090302_0.C: Likewise.
+ * g++.dg/lto/pr45621_0.C: Likewise.
+ * g++.dg/lto/pr60567_0.C: Likewise.
+ * g++.dg/lto/pr62026.C: Likewise.
+ * gcc.dg/lto/pr45736_0.c: Likewise.
+ * gcc.dg/lto/pr52634_0.c: Likewise.
+ * gfortran.dg/lto/20091016-1_0.f90: Likewise.
+ * gfortran.dg/lto/pr79108_0.f90: Likewise.
+
+2018-09-20 Alexandre Oliva <oliva@adacore.com>
+
+ PR middle-end/87054
+ * gcc.dg/pr87054.c: New.
+
+2018-09-20 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/87288
+ * gcc.dg/vect/pr87288-1.c: New test.
+ * gcc.dg/vect/pr87288-2.c: Likewise,
+ * gcc.dg/vect/pr87288-3.c: Likewise.
+
+2018-09-20 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/86877
+ * gfortran.dg/vect/vect-8-epilogue.F90: New test.
+
+2018-09-19 Marek Polacek <polacek@redhat.com>
+
+ * g++.dg/conversion/op4.C: Add dg-warning.
+ * g++.dg/warn/Wclass-conversion1.C: New test.
+ * g++.dg/warn/Wclass-conversion2.C: New test.
+ * g++.dg/warn/Wconversion5.C: Remove file.
+ * g++.dg/warn/conversion-function-1.C: Use -Wno-class-converison.
+ * g++.old-deja/g++.bugs/900215_01.C: Adjust dg-warning.
+ * g++.old-deja/g++.jason/conversion5.C: Likewise.
+
+2018-09-19 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/87324
+ * g++.dg/cpp0x/desig5.C: New.
+
+2018-09-19 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/84109
+ * gfortran.dg/elemental_function_3.f90 : New test.
+
+2018-09-19 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87357 - missing -Wconversion warning
+ * g++.dg/warn/Wconversion5.C: New test.
+
+2018-09-19 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ * gcc.target/aarch64/atomic-store.c: New.
+
+2018-09-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87349
+ PR tree-optimization/87342
+ * gcc.dg/torture/pr87349-1.c: New testcase.
+ * gcc.dg/torture/pr87349-2.c: Likewise.
+ * gcc.dg/torture/pr87342.c: Likewise.
+
+2018-09-18 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/29550
+ * gfortran.dg/inline_matmul_13.f90: Adjust count for
+ _gfortran_matmul.
+ * gfortran.dg/inline_matmul_16.f90: Likewise.
+ * gfortran.dg/promotion_2.f90: Add -fblas-matmul-limit=1. Scan
+ for dgemm instead of dgemm_. Add call to random_number to make
+ standard conforming.
+ * gfortran.dg/matmul_blas_1.f90: New test.
+ * gfortran.dg/matmul_bounds_14.f: New test.
+ * gfortran.dg/matmul_bounds_15.f: New test.
+ * gfortran.dg/matmul_bounds_16.f: New test.
+ * gfortran.dg/blas_gemm_routines.f: New test / additional file for
+ preceding tests.
+
+2018-09-18 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/87239
+ * gfortran.dg/elemental_function_2.f90 : New test.
+
+2018-09-18 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/87336
+ * gfortran.dg/pointer_array_10.f90 : New test.
+ * gfortran.dg/assign_10.f90 : Increase 'parm' count to 20.
+ * gfortran.dg/transpose_optimization_2.f90 : Increase 'parm'
+ count to 72.
+
+2018-09-18 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/85065
+ * g++.dg/concepts/pr85065.C: New.
+
+2018-09-18 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR testsuite/87339
+ * gcc.dg/warn-abs-1.c: Require float128 target.
+ Skip if large_long_double newlib target.
+
+2018-09-18 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/86881
+ * g++.dg/warn/pr86881.C: New.
+
+2018-09-18 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.target/aarch64/spellcheck_1.c:
+ Make architecture suggestion optional.
+ * gcc.target/aarch64/spellcheck_4.c:
+ Likewise.
+
+2018-09-18 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.target/aarch64/combine_bfxil.c: Avoid passing pointers to
+ functions.
+
+2018-09-17 Cesar Philippidis <cesar@codesourcery.com>
+ Bernd Schmidt <bernds_cb1@t-online.de>
+
+ * gcc.target/nvptx/atomic-fetch-2.c: Rename to ...
+ * gcc.target/nvptx/atomic_fetch-2.c: ... this.
+ * gcc.target/nvptx/atomic_fetch-3.c: New test.
+
+2018-09-17 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87328
+ * gcc.dg/torture/pr87328.c: New testcase.
+
+2018-09-17 Martin Jambor <mjambor@suse.cz>
+
+ PR c/63886
+ * gcc.dg/warn-abs-1.c: New test.
+ * gcc.dg/dfp/warn-abs-2.c: Likewise.
+
+2018-09-17 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * gcc.target/x86_64/abi/ms-sysv/ms-sysv.exp: Don't pass
+ TEST_ALWAYS_FLAGS to HOSTCXX.
+
+2018-09-17 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/64120
+ * gfortran.dg/allocatable_scalar_14.f90 : New test.
+
+2018-09-17 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87301
+ * gcc.dg/torture/pr87301.c: New testcase.
+
+2018-09-17 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/85954
+ * gfortran.dg/deferred_character_21.f90 : New test.
+
+2018-09-16 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/86484
+ PR fortran/84543
+ * gfortran.dg/class_assign_2.f90: New test case.
+ * gfortran.dg/class_assign_3.f90: New test case.
+
+2018-09-16 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/37802
+ * gfortran.dg/matmul_bounds_13.f90: New test case.
+ * gfortran.dg/inline_matmul_15.f90: Adjust test for runtime
+ error.
+ * gfortran.dg/matmul_5.f90: Likewise.
+ * gfortran.dg/matmul_bounds_10.f90: Likewise.
+ * gfortran.dg/matmul_bounds_11.f90: Likewise.
+ * gfortran.dg/matmul_bounds_2.f90: Likewise.
+ * gfortran.dg/matmul_bounds_4.f90: Likewise.
+ * gfortran.dg/matmul_bounds_5.f90: Likewise.
+
+2018-09-15 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.c-torture/compile/20180915-1.c: New test.
+
+2018-09-14 David Malcolm <dmalcolm@redhat.com>
+
+ PR c/82967
+ * c-c++-common/attributes-1.c: Remove bogus suggestion from
+ dg-prune-output.
+ * gcc.dg/diagnostic-token-ranges.c (undeclared_identifier): Remove
+ bogus suggestion.
+ * gcc.dg/spellcheck-identifiers-4.c: New test.
+
+2018-09-14 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * gcc.dg/warn-strlen-no-nul.c: Add some missing test cases.
+
+2018-09-14 Martin Sebor <msebor@redhat.com>
+
+ * gcc.dg/warn-stpcpy-no-nul.c: New test.
+
+2018-09-14 Martin Sebor <msebor@redhat.com>
+ Jeff Law <law@redhat.com>
+
+ * gcc.dg/warn-strcpy-no-nul.c: New test.
+
+2018-09-14 Martin Sebor <msebor@redhat.com>
+
+ c++/61941
+ * g++.dg/pr61941.C: New test.
+
+2018-09-14 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.target/aarch64/combine_bfi_1.c: Scan for bfi instruction
+ rather than pattern name in combine dump.
+
+2018-09-14 Sam Tebbs <sam.tebbs@arm.com>
+
+ PR target/85628
+ * gcc.target/aarch64/combine_bfxil.c (combine_zero_extended_int, foo6):
+ New functions.
+
+2018-09-14 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR tree-optimization/87259
+ * gcc.dg/pr87259.c: New test.
+
+2018-09-13 Martin Sebor <msebor@redhat.com>
+ Jeff Law <law@redhat.com>
+
+ * gcc.dg/warn-strlen-no-nul.c: New test.
+
+2018-09-13 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87263
+ * gcc.dg/torture/pr87263.c: New testcase.
+ * gcc.dg/torture/ssa-fre-2.c: Likewise.
+ * gcc.dg/torture/ssa-fre-3.c: Likewise.
+ * gcc.dg/torture/ssa-fre-4.c: Likewise.
+
+2018-09-13 Omar Sandoval <osandov@osandov.com>
+ Tom de Vries <tdevries@suse.de>
+
+ PR debug/86985
+ * gcc.dg/guality/zero-length-array.c: New test.
+
+2018-09-13 Sam Tebbs <sam.tebbs@arm.com>
+
+ PR target/85628
+ * gcc.target/aarch64/combine_bfxil.c: New file.
+ * gcc.target/aarch64/combine_bfxil_2.c: New file.
+
+2018-09-13 Jakub Jelinek <jakub@redhat.com>
+ Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR middle-end/87290
+ * gcc.target/i386/pr87290.c: New test.
+ * gcc.c-torture/execute/pr87290.c: New test.
+
+2018-09-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/87287
+ * gcc.dg/tree-ssa/pr87287.c: New test.
+
+2018-09-12 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/85110
+ * g++.dg/cpp0x/explicit4.C: Update expected output to reflect
+ special-casing of diagnostic for a single non-viable candidate due
+ to a bad argument.
+ * g++.dg/diagnostic/param-type-mismatch-2.C: Likewise.
+ Add test coverage for an unmatched overloaded operator.
+ * g++.dg/expr/pmf-1.C: Likewise.
+ * g++.old-deja/g++.bugs/900330_02.C: Likewise.
+ * g++.old-deja/g++.jason/conversion11.C: Likewise.
+ * g++.old-deja/g++.law/arg11.C: Likewise.
+ * g++.old-deja/g++.law/arm9.C: Likewise.
+ * g++.old-deja/g++.robertl/eb131.C: Likewise.
+
+2018-09-12 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/87284
+ * gfortran.dg/allocate_with_mold_2.f90: New test.
+
+2018-09-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/82853
+ * gcc.target/i386/pr82853-1.c: New test.
+ * gcc.target/i386/pr82853-2.c: New test.
+
+2018-09-12 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87280
+ * gcc.dg/torture/pr87280.c: New testcase.
+
+2018-09-12 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87266
+ * gcc.dg/torture/pr87266-1.c: New testcase.
+ * gcc.dg/torture/pr87266-2.c: Likewise.
+ * gcc.dg/torture/pr87266-3.c: Likewise.
+ * gcc.dg/torture/pr87266-4.c: Likewise.
+
+2018-09-12 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * gcc.target/s390/dfp_to_bfp_rounding.c: New test.
+
+2018-09-12 Jakub Jelinek <jakub@redhat.com>
+ Andreas Krebbel <krebbel@linux.ibm.com>
+
+ PR tree-optimization/86844
+ * gcc.c-torture/execute/pr86844.c: New test.
+ * gcc.dg/store_merging_22.c: New test.
+ * gcc.dg/store_merging_23.c: New test.
+
+2018-09-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/87248
+ * c-c++-common/torture/pr87248.c: New test.
+
+2018-09-11 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/87172
+ * gfortran.dg/iso_c_binding_only_2.f90: New test case.
+
+2018-09-11 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/87277
+ * gfortran.dg/select_type_43.f90: New test.
+
+2018-09-11 Nathan Sidwell <nathan@acm.org>
+
+ * gcc.dg/driver-specs.c: New.
+
+2018-09-11 Joey Ye <joey.ye@arm.com>
+
+ * lib/gcov.exp (verify-intermediate): Add missing close.
+
+2018-09-11 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/86830
+ * gfortran.dg/typebound_call_30.f90: New test case.
+
+2018-09-10 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/85395
+ * gfortran.dg/proc_ptr_comp_52.f90: New test case.
+
+2018-09-08 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87150 - wrong ctor with maybe-rvalue semantics.
+ * g++.dg/cpp0x/move-return2.C: New test.
+
+2018-09-08 Marek Polacek <polacek@redhat.com>
+
+ * c-c++-common/array-init.c: Add dg-prune-output.
+ * g++.dg/cpp0x/lambda/lambda-const-this.C: Add dg-warning.
+ * g++.dg/cpp0x/lambda/lambda-in-class-neg.C: Likewise.
+ * g++.dg/cpp0x/lambda/lambda-in-class.C: Likewise.
+ * g++.dg/cpp0x/lambda/lambda-nested.C: Likewise.
+ * g++.dg/cpp0x/lambda/lambda-nsdmi1.C: Likewise.
+ * g++.dg/cpp0x/lambda/lambda-nsdmi4.C: Likewise.
+ * g++.dg/cpp0x/lambda/lambda-this.C: Likewise.
+ * g++.dg/cpp0x/lambda/lambda-this17.C: Likewise.
+ * g++.dg/cpp0x/lambda/lambda-this18.C: Likewise.
+ * g++.dg/cpp0x/lambda/lambda-this2.C: Likewise.
+ * g++.dg/cpp0x/lambda/lambda-this8.C: Likewise.
+ * g++.dg/cpp1y/pr64382.C: Likewise.
+ * g++.dg/cpp1y/pr77739.C: Likewise.
+ * g++.dg/cpp1z/lambda-this1.C: Likewise.
+ * g++.dg/cpp1z/lambda-this2.C: Likewise.
+ * g++.dg/template/crash84.C: Adjust dg-error.
+
+2018-09-07 Marek Polacek <polacek@redhat.com>
+
+ * g++.dg/cpp1z/direct-enum-init1.C: Remove "inside" from diagnostic
+ messages.
+
+2018-09-07 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87152 - range-based for loops with initializer broken in templates.
+ * g++.dg/cpp2a/range-for11.C: New test.
+ * g++.dg/cpp2a/range-for12.C: New test.
+ * g++.dg/cpp2a/range-for13.C: New test.
+ * g++.dg/cpp2a/range-for14.C: New test.
+ * g++.dg/cpp2a/range-for15.C: New test.
+ * g++.dg/cpp2a/range-for16.C: New test.
+ * g++.dg/cpp2a/range-for17.C: New test.
+ * g++.dg/cpp2a/range-for18.C: New test.
+ * g++.dg/parse/error61.C (foo): Adjust dg-error.
+
+2018-09-06 Will Schmidt <will_schmidt@vnet.ibm.com>
+
+ PR target/86731
+ * gcc.target/powerpc/pr86731.c: New test.
+ * gcc.target/powerpc/pr86731-longlong.c: New test.
+ * gcc.target/powerpc/pr86731-fwrapv.c: New test.
+ * gcc.target/powerpc/pr86731-fwrapv-longlong.c: New test.
+ * gcc.target/powerpc/pr86731-nogimplefold.c: New test.
+ * gcc.target/powerpc/pr86731-nogimplefold-longlong.c: New test.
+
+2018-09-06 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ PR target/80080
+ * gcc.target/s390/pr80080-3.c: New test.
+ * gcc.target/s390/s390.exp: Make sure the new test passes
+ on all optimization levels.
+
+2018-09-05 Marek Polacek <polacek@redhat.com>
+
+ PR c++/86982, -Wreturn-local-addr and std::move and std::forward.
+ * g++.dg/warn/Wreturn-local-addr-5.C: New test.
+
+2018-09-05 Cesar Philippidis <cesar@codesourcery.com>
+ Bernd Schmidt <bernds_cb1@t-online.de>
+
+ * gcc.target/nvptx/atomic_fetch-1.c: New test.
+ * gcc.target/nvptx/atomic_fetch-1.c: New test.
+
+2018-09-05 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87109, wrong overload with ref-qualifiers.
+ * g++.dg/cpp0x/ref-qual19.C: New test.
+
+2018-09-05 Bernhard Reutner-Fischer <aldot@gcc.gnu.org>
+
+ PR testsuite/52665
+ * lib/gcc-dg.exp (gcc-dg-test-1): Iterate over _required_options.
+ * lib/target-supports.exp (scan-assembler_required_options,
+ scan-assembler-not_required_options,
+ scan-assembler-times_required_options): Add -fno-ident.
+ * lib/scanasm.exp (scan-assembler-times): Fix error message.
+ * c-c++-common/ident-0a.c: New test.
+ * c-c++-common/ident-0b.c: New test.
+ * c-c++-common/ident-1a.c: New test.
+ * c-c++-common/ident-1b.c: New test.
+ * c-c++-common/ident-2a.c: New test.
+ * c-c++-common/ident-2b.c: New test.
+
+2018-09-05 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.dg/recip_sqrt_mult_1.c: New test.
+ * gcc.dg/recip_sqrt_mult_2.c: Likewise.
+ * gcc.dg/recip_sqrt_mult_3.c: Likewise.
+ * gcc.dg/recip_sqrt_mult_4.c: Likewise.
+ * gcc.dg/recip_sqrt_mult_5.c: Likewise.
+ * g++.dg/recip_sqrt_mult_1.C: Likewise.
+ * g++.dg/recip_sqrt_mult_2.C: Likewise.
+
+2018-09-05 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/87205
+ * gcc.dg/tree-ssa/pr87205-2.c: New test.
+ * gcc.dg/tree-ssa/pr87205.c: New test.
+
+2018-09-05 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87217
+ * gfortran.dg/pr87217.f: New testcase.
+
+2018-09-05 Pádraig Brady p@draigbrady.com
+
+ PR c++/87137
+ * g++.dg/abi/pr87137.C: New.
+
+ PR c++/87185
+ * g++.dg/pr87185.C: New.
+
+2018-09-05 Martin Liska <mliska@suse.cz>
+
+ PR testsuite/87216
+ * gcc.dg/tree-prof/pr59521-3.c: Update scanned pattern
+ to support Darwin names.
+
+2018-09-05 Martin Liska <mliska@suse.cz>
+
+ * g++.dg/gcov/loop.C: Update test to support new format.
+
+2018-09-04 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR debug/86593
+ * g++.dg/pr86593.C: New test.
+
+2018-09-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/87198
+ * gcc.target/i386/pr87198.c: New test.
+
+2018-09-04 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ PR target/86744
+ * gcc.target/i386/addr-sel-1.c: Don't xfail "b\\+1" scan.
+
+2018-09-04 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87211
+ * gcc.dg/torture/pr87211.c: New testcase.
+
+2018-09-04 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87176
+ * gcc.dg/torture/pr87176.c: New testcase.
+ * gcc.dg/torture/ssa-fre-1.c: Likewise.
+
+2018-09-03 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ * gfortran.dg/modulo_check: New test.
+
+2018-09-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87177
+ * gcc.dg/torture/pr87177.c: New testcase.
+ * gcc.dg/torture/pr87177-2.c: Likewise.
+
+2018-09-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87200
+ * gcc.dg/torture/pr87200.c: New testcase.
+
+2018-09-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87197
+ * gcc.dg/torture/pr87197.c: New testcase.
+
+ PR tree-optimization/87169
+ * gcc.dg/torture/pr87169.c: New testcase.
+
+2018-09-03 Martin Liska <mliska@suse.cz>
+
+ PR driver/83193
+ * gcc.dg/completion-4.c: New test.
+
+2018-09-03 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/84980
+ * g++.dg/concepts/pr84980.C: New.
+
+2018-09-03 Martin Liska <mliska@suse.cz>
+
+ PR middle-end/59521
+ * c-c++-common/pr59521-1.c: New test.
+ * c-c++-common/pr59521-2.c: New test.
+ * gcc.dg/tree-prof/pr59521-3.c: New test.
+
+2018-09-02 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * c-c++-common/array-init.c: New test.
+ * g++.dg/init/string2.C: Remove selector.
+
+2018-09-01 Michael Matz <matz@suse.de>
+
+ PR tree-optimization/87074
+ * gcc.dg/pr87074.c: New test.
+
+2018-08-31 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87168
+ * gcc.dg/torture/pr87168.c: New testcase.
+
+2018-08-31 Vlad Lazar <vlad.lazar@arm.com>
+
+ * gcc.target/aarch64/scalar_intrinsics.c (test_vnegd_s64): New.
+ * gcc.target/aarch64/vneg_s.c (RUN_TEST_SCALAR): New.
+ (test_vnegd_s64): Likewise.
+ * gcc.target/aarch64/vnegd_64.c: New.
+ * gcc.target/aarch64/vabsd_64.c: New.
+ * gcc.tartget/aarch64/vabs_intrinsic_3.c: New.
+
+2018-08-31 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/87155
+ PR c++/84707
+ * g++.dg/cpp0x/pr87155.C: New.
+ * g++.dg/cpp0x/inline-ns10.C: Adjust.
+
+2018-08-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/87138
+ * gcc.target/i386/avx512bw-pr87138.c: New test.
+
+2018-08-31 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/86328
+ PR fortran/86760
+ * gfortran.dg/pr86328.f90 : New test.
+ in comment 12 of the PR.
+ * gfortran.dg/pr86760.f90 : New test.
+
+2018-08-30 Sandra Loosemore <sandra@codesourcery.com>
+
+ * g++.dg/cpp0x/noexcept30.C: Make dependence on
+ -fdelete-null-pointer-checks explicit.
+ * g++.dg/cpp1y/constexpr-82218.C: Likewise.
+ * g++.dg/expr/pmf-3.C: Likewise.
+ * g++.dg/ext/attr-returns-nonnull.C: Likewise.
+ * g++.dg/tree-ssa/lifetime-dse1.C: Likewise.
+ * g++.dg/tree-ssa/pr61034.C: Likewise.
+ * gcc.dg/addr_equal-1.c: Likewise.
+ * gcc.dg/ipa/pr85734.c: Likewise.
+ * gcc.dg/ipa/propmalloc-1.c: Likewise.
+ * gcc.dg/ipa/propmalloc-2.c: Likewise.
+ * gcc.dg/ipa/propmalloc-3.c: Likewise.
+ * gcc.dg/tree-ssa/pr78154.c: Likewise.
+ * gcc.dg/tree-ssa/pr83648.c: Likewise.
+
+2018-08-30 Martin Sebor <msebor@redhat.com>
+
+ PR testsuite/87158
+ * gcc.c-torture/execute/memchr-1.c: Correct big-endian expectations.
+
+2018-08-30 Qing Zhao <qing.zhao@oracle.com>
+
+ PR testsuite/86519
+ gcc.dg/strcmpopt_6.c: Remove.
+ gcc.target/aarch64/strcmpopt_6.c: New testcase.
+ gcc.target/i386/strcmpopt_6.c: Likewise.
+
+2018-08-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87147
+ * gcc.dg/torture/pr87147.c: New testcase.
+
+2018-08-30 Tamar Christina <tamar.christina@arm.com>
+
+ * gcc.target/aarch64/large_struct_copy_2.c: New.
+
+2018-08-29 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR middle-end/87053
+ * gcc.c-torture/execute/pr87053.c: New test.
+
+2018-08-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/87095
+ * g++.dg/ubsan/vptr-13.C: New test.
+
+2018-08-29 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/85265
+ * g++.dg/concepts/pr85265.C: New.
+
+2018-08-29 Martin Sebor <msebor@redhat.com>
+ Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR tree-optimization/86714
+ PR tree-optimization/86711
+ * gcc.c-torture/execute/memchr-1.c: New test.
+ * gcc.c-torture/execute/pr86714.c: New test.
+ * gcc.c-torture/execute/widechar-3.c: New test.
+ * gcc.dg/strlenopt-58.c: New test.
+
+2018-08-29 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87132
+ * gcc.dg/torture/pr87132.c: New testcase.
+
+2018-08-29 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/85110
+ * g++.dg/diagnostic/param-type-mismatch-2.C: Update expected
+ output to reflect underlining of pertinent parameter in decl
+ for "no known conversion" messages.
+
+2018-08-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/87122
+ * g++.dg/cpp1z/decomp47.C: New test.
+
+2018-08-29 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ * gcc.target/aarch64/simd/vect_su_add_sub.c: Use 32 and 64-bit types
+ where appropriate.
+
+2018-08-29 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87117
+ * gfortran.dg/pr87117.f90: New testcase.
+
+2018-08-29 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87126
+ * gcc.dg/tree-ssa/pr87126.c: New testcase.
+
+2018-08-28 MCC CS <deswurstes@users.noreply.github.com>
+
+ PR tree-optimization/87009
+ * gcc.dg/pr87009.c: New test.
+
+2018-08-28 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/86631
+ * g++.dg/Walloca1.C: Adjust.
+
+2018-08-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/86546
+ * g++.dg/other/switch4.C: New.
+
+2018-08-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87124
+ * g++.dg/torture/pr87124.C: New testcase.
+
+2017-08-28 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/80477
+ * gfortran.dg/class_result_7.f90: New test.
+ * gfortran.dg/class_result_8.f90: New test.
+ * gfortran.dg/class_result_9.f90: New test.
+
+ PR fortran/86481
+ * gfortran.dg/allocate_with_source_25.f90: New test.
+
+2018-08-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/87099
+ * gcc.dg/pr87099.c: New test.
+
+2018-08-28 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR testsuite/87078
+ * gcc.dg/vect/slp-37.c: Restrict scan tests to vect_hw_misalign.
+
+2018-08-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87117
+ * gcc.dg/pr87117-1.c: New testcase.
+
+2018-08-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87117
+ * gcc.dg/pr87117-2.c: New testcase.
+
+2018-08-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87117
+ * gcc.dg/lvalue-5.c: New testcase.
+
+2018-08-27 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/87110
+ * gcc.c-torture/compile/pr87110.c: New test.
+
+2018-08-27 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/86914
+ * gcc.dg/strlenopt-57.c: New test.
+
+2018-08-27 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/87112
+ * gcc.dg/pr87112.c: New test.
+
+2018-08-27 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/63392
+ * g++.dg/diagnostic/missing-typename.C: New test.
+
+2018-08-27 Jeff Law <law@redhat.com>
+
+ * gcc.c-torture/compile/dse.c: New test.
+
+2018-08-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/86993
+ * g++.dg/diagnostic/pr86993.C: New test.
+
+2018-08-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/86927
+ * gcc.dg/vect/pr86927.c: New testcase.
+
+2018-08-27 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/87091
+ * gcc.dg/empty.h: New file.
+ * gcc.dg/fixits-pr84852-1.c: Update for move of fix-it hint to
+ top of file and removal of redundant second printing of warning
+ location.
+ * gcc.dg/fixits-pr84852-2.c: Likewise.
+ * gcc.dg/missing-header-fixit-3.c: Likewise.
+ * gcc.dg/missing-header-fixit-4.c: New test.
+ * gcc.dg/plugin/diagnostic_plugin_test_show_locus.c: Update for
+ conversion of show_caret_p to a tri-state.
+
+2018-08-27 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/87091
+ * g++.dg/pr85523.C: Extend expected output to show line
+ before line-insertion fix-it hint.
+ * gcc.dg/plugin/diagnostic-test-show-locus-bw-line-numbers.c
+ (test_fixit_insert_newline): Add previous line to expected output.
+ * gcc.dg/plugin/diagnostic-test-show-locus-bw.c: Likewise.
+ * gcc.dg/plugin/diagnostic-test-show-locus-color.c: Likewise.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/86962
+ * gcc.dg/asan/pr86962.c: New test.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ * gcc.dg/tree-prof/val-prof-10.c: New test.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/86847
+ * gcc.dg/tree-ssa/switch-3.c: New test.
+ * gcc.dg/tree-ssa/vrp105.c: Remove.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ * gcc.dg/tree-ssa/switch-2.c: New test.
+
+2018-08-27 Richard Biener <rguenther@suse.de>
+
+ * g++.dg/torture/20180705-1.C: New testcase.
+ * gcc.dg/tree-ssa/ssa-fre-67.c: Likewise.
+ * gcc.dg/tree-ssa/ssa-ccp-14.c: Scan FRE dump.
+ * gcc.dg/tree-ssa/ssa-fre-46.c: Use -O2.
+ * gcc.dg/tree-ssa/vrp92.c: Disable FRE.
+ * gcc.dg/pr83666.c: Drop --param=sccvn-max-scc-size option.
+ * gcc.dg/pr85195.c: Likewise.
+ * gcc.dg/pr85467.c: Likewise.
+ * gcc.dg/torture/pr81790.c: Likewise.
+
+ * gfortran.dg/reassoc_4.f: Change max-completely-peeled-insns
+ param to current default.
+
+2018-08-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/87065
+ * gcc.target/i386/pr87065.c: New test.
+
+2018-08-26 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87080
+ * g++.dg/cpp0x/Wpessimizing-move5.C: New test.
+
+ PR c++/87029, Implement -Wredundant-move.
+ * g++.dg/cpp0x/Wredundant-move1.C: New test.
+ * g++.dg/cpp0x/Wredundant-move2.C: New test.
+ * g++.dg/cpp0x/Wredundant-move3.C: New test.
+ * g++.dg/cpp0x/Wredundant-move4.C: New test.
+
+2018-08-25 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR libfortran/86704
+ * gfortran.dg/matmul_19.f90: New test.
+
+2018-08-25 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/86545
+ * gfortran.dg/generic_35.f90: New test case.
+
+2018-08-24 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/87091
+ * gcc.dg/missing-header-fixit-3.c: Update for changes to how
+ line spans are printed with -fdiagnostics-show-line-numbers.
+
+2018-08-24 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/86837
+ * gfortran.dg/implied_do_io_6.f90: New test.
+
+2018-08-24 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR middle-end/87092
+ * gcc.dg/pr87092.c: New test.
+
+2018-08-24 Marek Polacek <polacek@redhat.com>
+
+ PR c++/67012
+ PR c++/86942
+ * g++.dg/cpp0x/auto52.C: New test.
+ * g++.dg/cpp1y/auto-fn52.C: New test.
+ * g++.dg/cpp1y/auto-fn53.C: New test.
+ * g++.dg/cpp1y/auto-fn54.C: New test.
+
+2018-08-24 Richard Sandiford <richard.sandiford@arm.com>
+
+ * lib/target-supports.exp (vect_perm_supported): Only return
+ false for variable-length vectors if the permute size is not
+ a power of 2.
+ (check_effective_target_vect_perm)
+ (check_effective_target_vect_perm_byte)
+ (check_effective_target_vect_perm_short): Remove check for
+ variable-length vectors.
+ * gcc.dg/vect/slp-23.c: Add an XFAIL for variable-length SVE.
+ * gcc.dg/vect/slp-perm-10.c: Likewise.
+ * gcc.dg/vect/slp-perm-9.c: Add an XFAIL for variable-length vectors.
+
+2018-08-24 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/bswap_1.c: New test.
+ * gcc.target/aarch64/sve/bswap_2.c: Likewise.
+ * gcc.target/aarch64/sve/bswap_3.c: Likewise.
+
+2018-08-24 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/slp_perm_1.c: New test.
+ * gcc.target/aarch64/sve/slp_perm_2.c: Likewise.
+ * gcc.target/aarch64/sve/slp_perm_3.c: Likewise.
+ * gcc.target/aarch64/sve/slp_perm_4.c: Likewise.
+ * gcc.target/aarch64/sve/slp_perm_5.c: Likewise.
+ * gcc.target/aarch64/sve/slp_perm_6.c: Likewise.
+ * gcc.target/aarch64/sve/slp_perm_7.c: Likewise.
+
+2018-08-24 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR debug/79342
+ * gcc.dg/pr79342.: New test.
+
+2018-08-23 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/87072
+ * gcc.dg/Warray-bounds-35.c: New test.
+
+2018-08-23 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/87024
+ * gcc.dg/pr87024.c: New testcase.
+
+2018-08-23 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/vect/no-vfa-vect-depend-2.c: Remove XFAIL.
+ * gcc.dg/vect/no-vfa-vect-depend-3.c: Likewise.
+ * gcc.dg/vect/pr65947-13.c: Update for vect_fold_extract_last.
+ * gcc.dg/vect/pr80631-2.c: Likewise.
+
+2017-08-23 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/86863
+ * gfortran.dg/submodule_32.f08: New test.
+
+2018-08-22 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/86935
+ * gfortran.dg/associate_3.f90: Update error message.
+ * gfortran.dg/associate_39.f90: New test case.
+
+2018-08-22 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/86888
+ * gfortran.dg/alloc_comp_basics_6.f90: Update an error message and add
+ an additional case.
+ * gfortran.dg/alloc_comp_basics_7.f90: New test case.
+ * gfortran.dg/class_17.f03: Update error message.
+ * gfortran.dg/class_55.f90: Ditto.
+ * gfortran.dg/dtio_11.f90: Update error messages.
+ * gfortran.dg/implicit_actual.f90: Add an error message.
+ * gfortran.dg/typebound_proc_12.f90: Update error message.
+
+2018-08-22 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/87052
+ * gcc.dg/pr87052.c: New test.
+ * gcc.dg/tree-ssa/dump-3.c: Adjust.
+
+2018-08-22 Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+ * gfortran.dg/max_fmax_aarch64.f90: Rename to...
+ * gfortran.dg/max_expr.f90: ...this.
+ * gfortran.dg/min_fmin_aarch64.f90: Rename to...
+ * gfortran.dg/min_expr.f90: ...this.
+
+2018-08-22 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/86725
+ * gcc.dg/vect/no-scevccp-pr86725-2.c: New test.
+ * gcc.dg/vect/no-scevccp-pr86725-3.c: Likewise.
+ * gcc.dg/vect/no-scevccp-pr86725-4.c: Likewise.
+ * gcc.dg/vect/no-scevccp-pr86725-5.c: Likewise.
+
+2018-08-22 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/86725
+ * gcc.dg/vect/no-scevccp-pr86725-1.c: New test.
+
+2018-08-22 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/vect/vect-avg-16.c: New test.
+ * gcc.dg/vect/slp-37.c: Expect the loop to be vectorized.
+ * gcc.dg/vect/vect-strided-u8-i8-gap4.c,
+ * gcc.dg/vect/vect-strided-u8-i8-gap4-big-array.c: Likewise for
+ the second loop in main1.
+
+2018-08-22 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.dg/lto/pr85248_0.c (test_alias):
+ Stringify __USER_LABEL_PREFIX__.
+ (test_noreturn): Likewise.
+
+2018-08-22 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/86988
+ * g++.dg/pr86988.C: New testcase.
+
+2018-08-22 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/86945
+ * tree-cfg.c (generate_range_test): Use unsigned arithmetic.
+
+2018-08-21 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * gfortran.dg/nan_1.f90: Remove tests that test MAX/MIN with NaNs.
+
+2018-08-21 Nicolas Koenig <koenigni@gcc.gnu.org>
+ Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/25829
+ * gfortran.dg/f2003_inquire_1.f03: Add write statement.
+ * gfortran.dg/f2003_io_1.f03: Add wait statement.
+
+2018-08-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/86981, Implement -Wpessimizing-move.
+ * g++.dg/cpp0x/Wpessimizing-move1.C: New test.
+ * g++.dg/cpp0x/Wpessimizing-move2.C: New test.
+ * g++.dg/cpp0x/Wpessimizing-move3.C: New test.
+ * g++.dg/cpp0x/Wpessimizing-move4.C: New test.
+ * g++.dg/cpp1z/Wpessimizing-move1.C: New test.
+
+ PR c++/65043
+ * g++.dg/concepts/pr67595.C: Add dg-warning.
+ * g++.dg/cpp0x/Wnarrowing11.C: New test.
+ * g++.dg/cpp0x/Wnarrowing12.C: New test.
+ * g++.dg/cpp0x/rv-cast5.C: Add static_cast.
+
+ PR c++/86499
+ * g++.dg/cpp0x/lambda/lambda-non-local.C: New test.
+ * g++.dg/cpp0x/lambda/lambda-this10.C: Adjust dg-error.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * gnat.dg/expr_func7.adb, gnat.dg/expr_func7.ads: New testcase.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * gnat.dg/expr_func6.adb, gnat.dg/expr_func6.ads: New testcase.
+
+2018-08-21 Javier Miranda <miranda@adacore.com>
+
+ * gnat.dg/spark2.adb, gnat.dg/spark2.ads: New testcase.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * gnat.dg/prot6.adb, gnat.dg/prot6.ads: New testcase.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * gnat.dg/access5.adb, gnat.dg/access5.ads: New testcase.
+
+2018-08-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/rep_clause7.adb: New testcase.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * gnat.dg/task1.adb, gnat.dg/task1.ads, gnat.dg/task1_pkg.adb,
+ gnat.dg/task1_pkg.ads: New testcase.
+
+2018-08-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * gnat.dg/linkedlist.adb: New testcase.
+
+2018-08-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * gnat.dg/elab6.adb, gnat.dg/elab6.ads, gnat.dg/elab6_pkg.adb,
+ gnat.dg/elab6_pkg.ads: New testcase.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * gnat.dg/expr_func5.adb: New testcase.
+
+2018-08-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * gnat.dg/dynhash.adb: New testcase.
+
+2018-08-21 Javier Miranda <miranda@adacore.com>
+
+ * gnat.dg/enum4.adb: New testcase.
+
+2018-08-21 Tamar Christina <tamar.christina@arm.com>
+
+ * gcc.target/aarch64/large_struct_copy.c: New test.
+
+2018-08-21 Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+ * g++.dg/torture/pr86763.C: Restrict to *-*-linux*.
+
+2018-08-21 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR middle-end/86121
+ * gcc.dg/Wstringop-overflow-6.c: Remove xfail.
+
+2018-08-21 Tom de Vries <tdevries@suse.de>
+
+ * gcc.c-torture/unsorted/dump-noaddr.x: Use -gno-record-gcc-switches
+ to avoid mismatch in .debug and .earlydebug dump files.
+
+2018-08-20 Michael Meissner <meissner@linux.ibm.com>
+
+ PR target/87033
+ * gcc.target/powerpc/pr87033.c: New test.
+
+2018-08-20 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/87034
+ * gcc.dg/builtin-sprintf-warn-20.c: New test.
+
+2018-08-20 David Malcolm <dmalcolm@redhat.com>
+
+ PR other/84889
+ * gcc.dg/plugin/diagnostic-group-test-1.c: New test.
+ * gcc.dg/plugin/diagnostic_group_plugin.c: New test.
+ * gcc.dg/plugin/plugin.exp (plugin_test_list): Add the new tests.
+
+2018-08-20 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/87014
+ * g++.dg/torture/pr87014.C: New file.
+
+2018-08-20 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR target/86984
+ * gcc.target/alpha/pr86984.c: New test.
+
+2018-08-20 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/78655
+ * gcc.dg/tree-ssa/evrp11.c: New testcase.
+
+2018-08-18 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.dg/debug/dwarf2/pr80263.c: Suppress pubtypes output
+ for Darwin.
+
+2018-08-18 Iain Sandoe <iain@sandoe.co.uk>
+
+ * g++.dg/debug/dwarf2/pr85302.C: Skip unsupported split DWARF
+ test on Darwin.
+ * g++.dg/debug/dwarf2/pr85302.C: Likewise.
+ * gcc.dg/lto/pr83719_0.c: Likewise.
+
+2018-08-17 Martin Sebor <msebor@redhat.com>
+
+ PR testsuite/86996
+ * gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Adjust.
+
+2018-08-17 David Malcolm <dmalcolm@redhat.com>
+
+ * g++.dg/conversion/Wwrite-strings.C: New test.
+
+2018-08-17 Sandra Loosemore <sandra@codesourcery.com>
+ Chung-Lin Tang <cltang@codesourcery.com>
+ Xianmiao Qu <xianmiao_qu@c-sky.com>
+
+ C-SKY port: Testsuite
+
+ * g++.dg/Wno-frame-address.C: Adjust for C-SKY.
+ * g++.dg/torture/type-generic-1.C: Likewise.
+ * gcc.c-torture/compile/20000804-1.c: Likewise.
+ * gcc.c-torture/execute/20101011-1.c: Likewise.
+ * gcc.c-torture/execute/ieee/mul-subnormal-single-1.x: Likewise.
+ * gcc.dg/20020312-2.c: Likewise.
+ * gcc.dg/Wno-frame-address.c: Likewise.
+ * gcc.dg/c11-true_min-1.c: Likewise.
+ * gcc.dg/sibcall-10.c: Likewise.
+ * gcc.dg/sibcall-9.c: Likewise.
+ * gcc.dg/stack-usage-1.c: Likewise.
+ * gcc.dg/torture/float32-tg-3.c: Likewise.
+ * gcc.dg/torture/float32x-tg-3.c: Likewise.
+ * gcc.dg/torture/float64-tg-3.c: Likewise.
+ * gcc.dg/torture/float64x-tg-3.c: Likewise.
+ * gcc.dg/torture/type-generic-1.c: Likewise.
+ * gcc.target/csky/*: New.
+ * lib/target-supports.exp (check_profiling_available): Add
+ csky-*-elf.
+ (check_effective_target_hard_float): Handle C-SKY targets with
+ single-precision hard float only.
+ (check_effective_target_logical_op_short_circuit): Handle C-SKY.
+
+2018-08-17 David Malcolm <dmalcolm@redhat.com>
+
+ * gcc.dg/format/gcc_diag-1.c: Fix typo. Add test coverage for
+ gcc_dump_printf.
+ * gcc.dg/format/gcc_diag-10.c: Add gimple typedef. Add test
+ coverage for gcc_dump_printf.
+
+2018-08-17 Martin Liska <mliska@suse.cz>
+
+ * g++.dg/opt/mpx.C: Fix scanned pattern.
+ * gcc.target/i386/mpx.c: Likewise.
+ * g++.dg/warn/Wunreachable-code-1.C: Remove.
+ * g++.dg/warn/Wunreachable-code-2.C: Likewise.
+ * gcc.dg/torture/pr52969.c: Likewise.
+ * g++.dg/warn/pr31246-2.C: Likewise.
+ * g++.dg/warn/pr31246.C: Likewise.
+ * gcc.dg/pr33092.c: Likewise.
+ * g++.dg/opt/eh1.C: Remove a deprecated option.
+ * g++.dg/template/inline1.C: Likewise.
+ * g++.dg/tree-ssa/pr81408.C: Likewise.
+ * gcc.dg/pr41837.c: Likewise.
+ * gcc.dg/pr41841.c: Likewise.
+ * gcc.dg/pr42250.c: Likewise.
+ * gcc.dg/pr43084.c: Likewise.
+ * gcc.dg/pr43317.c: Likewise.
+ * gcc.dg/pr51879-18.c: Likewise.
+ * gcc.dg/torture/pr36066.c: Likewise.
+ * gcc.dg/tree-ssa/ifc-8.c: Likewise.
+ * gcc.dg/tree-ssa/ifc-cd.c: Likewise.
+ * gcc.dg/tree-ssa/pr19210-1.c: Likewise.
+ * gcc.dg/tree-ssa/pr45122.c: Likewise.
+ * gcc.target/i386/pr45352-2.c: Likewise.
+ * gcc.target/i386/zee.c: Likewise.
+ * gfortran.dg/auto_char_len_2.f90: Likewise.
+ * gfortran.dg/auto_char_len_4.f90: Likewise.
+ * gfortran.dg/c_ptr_tests_15.f90: Likewise.
+ * gfortran.dg/char_array_structure_constructor.f90: Likewise.
+ * gfortran.dg/gomp/pr47331.f90: Likewise.
+ * gfortran.dg/pr40999.f: Likewise.
+ * gfortran.dg/pr41011.f: Likewise.
+ * gfortran.dg/pr42051.f03: Likewise.
+ * gfortran.dg/pr46804.f90: Likewise.
+ * gfortran.dg/pr83149_1.f90: Likewise.
+ * gfortran.dg/pr83149_b.f90: Likewise.
+ * gfortran.dg/whole_file_1.f90: Likewise.
+ * gfortran.dg/whole_file_10.f90: Likewise.
+ * gfortran.dg/whole_file_11.f90: Likewise.
+ * gfortran.dg/whole_file_12.f90: Likewise.
+ * gfortran.dg/whole_file_13.f90: Likewise.
+ * gfortran.dg/whole_file_14.f90: Likewise.
+ * gfortran.dg/whole_file_15.f90: Likewise.
+ * gfortran.dg/whole_file_16.f90: Likewise.
+ * gfortran.dg/whole_file_17.f90: Likewise.
+ * gfortran.dg/whole_file_18.f90: Likewise.
+ * gfortran.dg/whole_file_19.f90: Likewise.
+ * gfortran.dg/whole_file_2.f90: Likewise.
+ * gfortran.dg/whole_file_20.f03: Likewise.
+ * gfortran.dg/whole_file_3.f90: Likewise.
+ * gfortran.dg/whole_file_4.f90: Likewise.
+ * gfortran.dg/whole_file_5.f90: Likewise.
+ * gfortran.dg/whole_file_6.f90: Likewise.
+ * gfortran.dg/whole_file_7.f90: Likewise.
+ * gfortran.dg/whole_file_8.f90: Likewise.
+ * gfortran.dg/whole_file_9.f90: Likewise.
+ * gcc.dg/vect/vect.exp: Likewise.
+
+2018-08-17 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/86505
+ * gcc.dg/torture/pr86505.c: New testcase.
+
+2018-08-16 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/86853
+ * gcc.dg/tree-ssa/builtin-sprintf-10.c: New test.
+ * gcc.dg/tree-ssa/builtin-sprintf-11.c: New test.
+ * gcc.dg/tree-ssa/builtin-sprintf-warn-18.c: Adjust.
+
+2018-08-16 David Malcolm <dmalcolm@redhat.com>
+
+ * gcc.dg/missing-header-fixit-3.c: New test.
+
+2018-08-16 David Malcolm <dmalcolm@redhat.com>
+
+ * gcc.dg/plugin/diagnostic-test-show-locus-bw-line-numbers.c
+ (test_fixit_insert_newline): Update expected output to show '+'
+ characters in margin of line-insertion fix-it hint.
+
+2018-08-16 Nathan Sidwell <nathan@acm.org>
+
+ * gcc.dg/cpp/macsyntx.c: Adjust expected errors.
+ * gcc.dg/cpp/macsyntx2.c: likewise.
+
+2018-08-15 Uros Bizjak <ubizjak@gmail.com>
+
+ PR testsuite/86745
+ * gcc.target/i386/avx-cvt-2.c: Loosen scan-assembler strings.
+ * gcc.target/i386/avx-cvt-2.c: Ditto.
+
+2018-08-16 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/70693
+ * c-c++-common/Wmisleading-indentation-pr70693.c: New test.
+
+2018-08-16 Vlad Lazar <vlad.lazar@arm.com>
+
+ * gcc.target/aarch64/imm_choice_comparison.c: New test.
+
+2018-08-16 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.dg/memcmp-1.c (lib_memcmp): Apply __USER_LABEL_PREFIX__.
+ (lib_strncmp): Likewise.
+
+2018-08-16 Iain Sandoe <iain@sandoe.co.uk>
+
+ * c-c++-common/asan/pointer-subtract-3.c: Skip for Darwin.
+ * c-c++-common/asan/pointer-subtract-4.c: Likewise.
+ * g++.dg/torture/pr44295.C : Likewise.
+
+2018-08-16 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR testsuite/78544
+ * gcc.dg/tree-prof/section-attr-1.c: Add Darwin-specific section
+ attributes and matching.
+ * gcc.dg/tree-prof/section-attr-2.c: Likewise.
+ * gcc.dg/tree-prof/section-attr-3.c: Likewise.
+
+2018-08-16 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.dg/asan/pr81923.c: Stringify __USER_LABEL_PREFIX__.
+
+2018-08-15 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/rop1.c: Remove.
+ * gcc.target/i386/pr83554 (dg-options): Remove -mmitigate-rop.
+
+2018-08-15 Will Schmidt <will_schmidt@vnet.ibm.com>
+
+ * gcc.target/powerpc/fold-vec-splat-char.c: New.
+ * gcc.target/powerpc/fold-vec-splat-floatdouble.c: New.
+ * gcc.target/powerpc/fold-vec-splat-int.c: New.
+ * gcc.target/powerpc/fold-vec-splat-longlong.c: New.
+ * gcc.target/powerpc/fold-vec-splat-pixel.c: New.
+ * gcc.target/powerpc/fold-vec-splat-short.c: New.
+
+2018-08-15 David Malcolm <dmalcolm@redhat.com>
+
+ * g++.dg/diagnostic/aka3.C: New test.
+ * g++.dg/diagnostic/param-type-mismatch-2.C: Update expected
+ output to show range labels.
+ * g++.dg/diagnostic/param-type-mismatch.C: Likewise.
+ * g++.dg/plugin/plugin.exp (plugin_test_list): Add...
+ * g++.dg/plugin/show-template-tree-color-labels.C: New test.
+ * gcc.dg/bad-binary-ops.c: Update expected output to show range
+ labels. Add an "aka" example.
+ * gcc.dg/cpp/pr66415-1.c: Update expected output to show range
+ labels.
+ * gcc.dg/format/diagnostic-ranges.c: Likewise.
+ * gcc.dg/format/pr72858.c: Likewise.
+ * gcc.dg/format/pr78498.c: Likewise.
+ * gcc.dg/param-type-mismatch.c: Add "-Wpointer-sign" to options.
+ Update expected output to show range labels. Add examples of
+ -Wincompatible-pointer-types and -Wpointer-sign for parameters.
+ * gcc.dg/plugin/diagnostic-test-show-locus-bw-line-numbers.c:
+ Update expected output to show range labels.
+ * gcc.dg/plugin/diagnostic-test-show-locus-bw.c: Likewise.
+ (test_very_wide_line): Adjust so that label is at left-clipping
+ boundary.
+ (test_very_wide_line_2): New test.
+ * gcc.dg/plugin/diagnostic-test-show-locus-color-line-numbers.c:
+ Update expected output to show range labels.
+ * gcc.dg/plugin/diagnostic-test-show-locus-color.c: Likewise.
+ * gcc.dg/plugin/diagnostic-test-show-locus-no-labels.c: New test.
+ * gcc.dg/plugin/diagnostic_plugin_show_trees.c (show_tree): Update
+ for new param to gcc_rich_location::add_expr.
+ * gcc.dg/plugin/diagnostic_plugin_test_show_locus.c (add_range):
+ Add "label" param.
+ (test_show_locus): Add examples of labels to various tests. Tweak
+ the "very wide_line" test case and duplicate it, to cover the
+ boundary values for clipping of labels against the left-margin.
+ * gcc.dg/plugin/plugin.exp (plugin_test_list): Add
+ diagnostic-test-show-locus-no-labels.c.
+ * gcc.dg/pr69554-1.c: Update expected output to show range labels.
+ Update line numbers of dg-locus directives.
+ * gcc.dg/pr69627.c: Update expected output to show range labels.
+ * lib/multiline.exp (proc _build_multiline_regex): Remove
+ special-case handling of lines with trailing '|'.
+
+2018-08-15 Qing Zhao <qing.zhao@oracle.com>
+
+ PR testsuite/86519
+ * gcc.dg/strcmpopt_6.c: Scan the assembly file instead of
+ the .expand file.
+
+2018-08-15 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ * gcc.dg/wmain.c: New test.
+
+2018-08-15 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c/19315
+ * gcc.dg/graphite/pr82451.c: Make array 'a' an extern.
+ * gcc.dg/redecl-10.c: Expect warnings for the static vars with
+ unknown size.
+
+2018-08-15 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/86925
+ * gcc.dg/predict-20.c: New test.
+ * gcc.dg/predict-21.c: New test.
+
+2018-08-15 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * g++.dg/init/goto3.C: Adjust for error instead of permerror.
+
+2018-08-14 Allan Sandfeld Jensen <allan.jensen@qt.io>
+
+ * gcc.target/i386/sse2-movs.c: New test.
+
+2018-08-14 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/86650
+ * gcc.dg/Warray-bounds-34.c: New test.
+
+2018-08-14 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/86116
+ * gfortran.dg/generic_34.f90: New test case.
+
+2018-08-13 Marek Polacek <polacek@redhat.com>
+
+ PR c++/57891
+ * g++.dg/cpp0x/Wnarrowing6.C: New test.
+ * g++.dg/cpp0x/Wnarrowing7.C: New test.
+ * g++.dg/cpp0x/Wnarrowing8.C: New test.
+ * g++.dg/cpp0x/Wnarrowing9.C: New test.
+ * g++.dg/cpp0x/Wnarrowing10.C: New test.
+ * g++.dg/cpp0x/constexpr-47969.C: Adjust dg-error.
+ * g++.dg/cpp0x/constexpr-ex2.C: Likewise.
+ * g++.dg/cpp0x/constexpr-targ.C: Likewise.
+ * g++.dg/cpp0x/scoped_enum2.C: Likewise.
+ * g++.dg/ext/stmtexpr15.C: Likewise.
+ * g++.dg/gomp/pr47963.C: Likewise.
+ * g++.dg/init/new37.C: Likewise.
+ * g++.dg/init/new43.C: Likewise.
+ * g++.dg/other/fold1.C: Likewise.
+ * g++.dg/parse/array-size2.C: Likewise.
+ * g++.dg/template/dependent-name3.C: Likewise.
+ * g++.dg/cpp0x/constexpr-data2.C: Add dg-error.
+ * g++.dg/other/vrp1.C: Likewise.
+ * g++.dg/template/char1.C: Likewise.
+
+2018-08-13 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * gcc.target/powerpc/pr56605.c: The generated code can have an AND
+ instead of a ZERO_EXTEND.
+
+2018-08-13 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/71625
+ * c-c++-common/attr-nonstring-3.c: Temporarily xfail a test case.
+ * g++.dg/init/string2.C: New test.
+ * g++.dg/init/string3.C: New test.
+ * g++.dg/init/string4.C: New test.
+ * gcc.dg/init-string-3.c: New test.
+ * gcc.dg/strlenopt-55.c: New test.
+ * gcc.dg/strlenopt-56.c: New test.
+
+2018-08-13 Marek Polacek <polacek@redhat.com>
+
+ P0806R2 - Deprecate implicit capture of this via [=]
+ * g++.dg/cpp2a/lambda-this1.C: New test.
+ * g++.dg/cpp2a/lambda-this2.C: New test.
+ * g++.dg/cpp2a/lambda-this3.C: New test.
+
+2018-08-13 Marek Polacek <polacek@redhat.com>
+
+ PR c++/86915
+ * g++.dg/diagnostic/auto1.C: New test.
+
+2018-08-12 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/66679
+ * gfortran.dg/transfer_class_3.f90: New test.
+
+2018-08-12 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/86906
+ * gfortran.dg/use_rename_9.f90: New test.
+
+2018-08-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/86835
+ * gcc.dg/pr86835.c: New test.
+
+2018-08-10 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/57160
+ * gfortran.dg/actual_pointer_function_1.f90: Fix invalid test case.
+ * gfortran.dg/inline_matmul_23.f90: Add option "-ffrontend-optimize".
+ * gfortran.dg/short_circuiting_2.f90: New test case.
+ * gfortran.dg/short_circuiting_3.f90: New test case.
+
+2018-08-10 Alexander Monakov <amonakov@ispras.ru>
+
+ PR target/82418
+ * gcc.target/i386/pr82418.c: New test.
+
+2018-08-10 Martin Liska <mliska@suse.cz>
+
+ PR target/83610
+ * gcc.dg/predict-17.c: New test.
+ * gcc.dg/predict-18.c: New test.
+ * gcc.dg/predict-19.c: New test.
+
+2018-08-10 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/85799
+ * gcc.dg/pr85799.c: New test.
+
+2018-08-09 Jeff Law <law@redhat.com>
+
+ PR middle-end/86897
+ * gcc.dg/uninit-suppress_2.c: Disable DOM.
+
+2018-08-09 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/reduc_8.c: New test.
+
+2018-08-09 David Malcolm <dmalcolm@redhat.com>
+
+ PR other/84889
+ * gcc.dg/plugin/diagnostic-test-show-locus-bw-line-numbers.c: New
+ test.
+ * gcc.dg/plugin/diagnostic-test-show-locus-color-line-numbers.c:
+ New test.
+ * gcc.dg/plugin/plugin.exp (plugin_test_list): Add the new tests.
+ * lib/prune.exp: Add -fno-diagnostics-show-line-numbers to
+ TEST_ALWAYS_FLAGS.
+
+2018-08-09 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/86858
+ * gcc.dg/vect/pr86858.c: New test.
+
+2018-08-09 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/86871
+ * gcc.dg/vect/pr86871.c: New test.
+
+2018-08-09 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * g++.old-deja/g++.mike/p784.C: Add -fpermissive.
+
+2018-08-09 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * gcc.target/s390/target-attribute/tattr-arch-tune-1.c: Decrement
+ arch and tune numbers by 2.
+ * gcc.target/s390/target-attribute/tattr-arch-tune-2.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-1.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-10.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-11.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-12.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-13.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-14.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-15.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-16.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-17.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-18.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-19.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-2.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-20.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-21.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-22.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-23.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-24.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-25.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-26.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-27.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-28.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-29.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-3.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-30.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-31.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-32.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-4.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-5.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-6.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-7.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-8.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m31-9.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-1.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-10.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-11.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-12.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-13.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-14.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-15.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-16.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-17.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-18.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-19.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-2.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-20.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-21.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-22.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-23.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-24.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-25.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-26.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-27.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-28.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-29.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-3.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-30.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-31.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-32.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-33.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-4.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-5.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-6.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-7.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-8.c: Likewise.
+ * gcc.target/s390/target-attribute/tattr-m64-9.c: Likewise.
+
+2018-08-09 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ PR target/84332
+ * gcc.target/s390/pr84332.c: New testcase.
+
+2018-08-08 Andreas Schwab <schwab@linux-m68k.org>
+
+ PR target/46179
+ * gcc.target/m68k/tls-dimode.c: New file.
+
+2018-08-08 Nathan Sidwell <nathan@acm.org>
+
+ * c-c++-common/inc-from-1a.h, c-c++-common/inc-from-1b.h,
+ c-c++-common/inc-from-1.c: New
+
+2018-08-08 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ PR target/85295
+ * gcc.target/s390/TI-constants-lra.c: New testcase.
+ * gcc.target/s390/TI-constants-nolra.c: New testcase.
+
+2018-08-08 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * gcc.target/s390/hotpatch-8.c: Remove.
+ * gcc.target/s390/hotpatch-9.c: Remove.
+ * gcc.target/s390/mnop-mcount-m31-fpic.c: Remove.
+ * gcc.target/s390/mnop-mcount-m31.c: Remove.
+
+2018-08-08 Jakub Jelinek <jakub@redhat.com>
+
+ P0595R1 - is_constant_evaluated
+ * g++.dg/cpp2a/is-constant-evaluated1.C: New test.
+
+ PR c++/86836
+ * g++.dg/cpp1z/decomp46.C: New test.
+
+ PR c++/86738
+ * g++.dg/opt/pr86738.C: New test.
+
+2018-08-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR target/86838
+ * gcc.target/aarch64/frecpe_1.c: New test.
+ * gcc.target/aarch64/frecpe_2.c: Likewise.
+
+2018-08-07 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/59480, DR 136
+ * g++.dg/other/friend8.C: New.
+ * g++.dg/other/friend9.C: Likewise.
+ * g++.dg/other/friend10.C: Likewise.
+ * g++.dg/other/friend11.C: Likewise.
+ * g++.dg/other/friend12.C: Likewise.
+ * g++.dg/other/friend13.C: Likewise.
+ * g++.dg/other/friend14.C: Likewise.
+ * g++.dg/other/friend15.C: Likewise.
+ * g++.dg/parse/defarg4.C: Compile with -fpermissive -w.
+ * g++.dg/parse/defarg8.C: Likewise.
+
+2018-08-07 Martin Liska <mliska@suse.cz>
+
+ PR middle-end/83023
+ * gcc.dg/predict-16.c: New test.
+ * g++.dg/predict-1.C: New test.
+
+2018-08-07 Steve Ellcey <sellcey@cavium.com>
+ Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ PR tree-optimization/80925
+ * gcc.dg/vect/no-section-anchors-vect-69.c: Expect 3 loops
+ vectorized on !vect_hw_misalign targets.
+
+2018-08-06 Marek Polacek <polacek@redhat.com>
+
+ PR c++/86767
+ * g++.dg/cpp1y/constexpr-86767.C: New test.
+
+2018-08-06 Uros Bizjak <ubizjak@gmail.com>
+
+ * g++.dg/torture/pr86763.C (dg-additional-options): Add -lrt
+ for target *-*-linux-gnu.
+
+2018-08-06 Alan Hayward <alan.hayward@arm.com>
+
+ * gcc.target/aarch64/sve/tls_preserve_1.c: New test.
+ * gcc.target/aarch64/sve/tls_preserve_2.c: New test.
+ * gcc.target/aarch64/sve/tls_preserve_3.c: New test.
+
+2018-08-06 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * gcc.target/s390/nomemloopunroll-1.c: New test.
+
+2018-08-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/86386
+ * gcc.target/i386/pr86386.c: New file.
+
+2018-08-04 Tom de Vries <tdevries@suse.de>
+
+ * lib/gcc-gdb-test.exp: Use absolute line number in pass/fail line.
+
+2018-08-04 Andreas Schwab <schwab@linux-m68k.org>
+
+ * gcc.dg/guality/const-volatile.c: Remove duplicate test
+ "type:cvip".
+
+2018-08-04 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/45521
+ * gfortran.dg/interface_assignment_6.f90: New test case.
+
+2018-08-04 Uros Bizjak <ubizjak@gmail.com>
+
+ PR testsuite/86153
+ * g++.dg/pr83239.C (dg-options): Add -finline-limit=500.
+
+2018-08-03 David Malcolm <dmalcolm@redhat.com>
+ Jonathan Wakely <jwakely@redhat.com>
+
+ PR c++/85523
+ * g++.dg/pr85523.C: New test.
+
+2018-08-03 Bogdan Harjoc <harjoc@gmail.com>
+
+ PR c/86690
+ * gcc.dg/union-duplicate-field.c: New test.
+
+2018-08-03 Jason Merrill <jason@redhat.com>
+
+ PR c++/86706
+ * g++.dg/template/pr86706.C: New test.
+
+2018-08-03 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/vect/bb-slp-over-widen-1.c: Expect AVG_FLOOR to be used
+ on vect_avg_qi targets.
+ * gcc.dg/vect/bb-slp-over-widen-2.c: Likewise.
+ * gcc.dg/vect/bb-slp-pow-1.c: New test.
+ * gcc.dg/vect/vect-avg-15.c: Likewise.
+
+2018-08-03 Martin Liska <mliska@suse.cz>
+
+ * gcc.dg/predict-1.c: Adjust scanned pattern to cover 2 digits.
+ * gcc.dg/predict-13.c: Likewise.
+ * gcc.dg/predict-3.c: Likewise.
+ * gcc.dg/predict-4.c: Likewise.
+ * gcc.dg/predict-5.c: Likewise.
+ * gcc.dg/predict-6.c: Likewise.
+ * gcc.dg/predict-9.c: Likewise.
+ * gfortran.dg/predict-1.f90: Likewise.
+
+2018-08-02 Richard Biener <rguenther@suse.de>
+
+ PR c++/86763
+ * g++.dg/torture/pr86763.C: New testcase.
+
+2018-08-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/86816
+ * g++.dg/torture/pr86816.C: New testcase.
+
+2018-08-02 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/f16_mov_immediate_1.c: Expect fmov immediate
+ to be used.
+ * gcc.target/aarch64/f16_mov_immediate_2.c: Likewise.
+ * gcc.target/aarch64/f16_mov_immediate_3.c: Force +nofp16.
+ * gcc.target/aarch64/sve/single_1.c: Except fmov immediate to be used
+ for .h.
+ * gcc.target/aarch64/sve/single_2.c: Likewise.
+ * gcc.target/aarch64/sve/single_3.c: Likewise.
+ * gcc.target/aarch64/sve/single_4.c: Likewise.
+
+2018-08-02 Jackson Woodruff <jackson.woodruff@arm.com>
+
+ PR target/86014
+ * gcc.target/aarch64/ldp_stp_13.c: New test.
+
+2018-08-01 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/86650
+ * gcc.dg/format/gcc_diag-10.c: Adjust.
+
+2018-08-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/var_stride_2.c: Update expected form
+ of range check.
+ * gcc.target/aarch64/sve/var_stride_4.c: Likewise.
+
+2018-08-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR target/86753
+ * gcc.target/aarch64/sve/vcond_4.c: XFAIL positive tests.
+ * gcc.target/aarch64/sve/vcond_5.c: Likewise.
+
+2018-08-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/pointer-range-check-1.c: New test.
+ * gcc.dg/pointer-range-check-2.c: Likewise.
+
+2018-08-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/86749
+ * gcc.dg/vect/pr86749.c: New test.
+
+2018-08-01 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/86661
+ * g++.dg/lookup/name-clash12.C: New.
+
+2018-08-01 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/ssa-fre-68.c: New testcase.
+
+2018-08-01 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.dg/plugin/poly-int-07_plugin.c (dg-options): Use -O0.
+
+2018-08-01 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.dg/tree-ssa/pr84512.c: Xfail on alpha*-*-*.
+
+2018-08-01 Martin Liska <mliska@suse.cz>
+
+ * gcc.dg/tree-prof/stringop-1.c: Adjust scanned pattern.
+ * gcc.dg/tree-prof/stringop-2.c: Likewise.
+ * gcc.dg/tree-prof/val-prof-1.c: Likewise.
+ * gcc.dg/tree-prof/val-prof-2.c: Likewise.
+ * gcc.dg/tree-prof/val-prof-3.c: Likewise.
+ * gcc.dg/tree-prof/val-prof-4.c: Likewise.
+ * gcc.dg/tree-prof/val-prof-5.c: Likewise.
+ * gcc.dg/tree-prof/val-prof-7.c: Likewise.
+
+2018-08-01 Martin Liska <mliska@suse.cz>
+
+ PR value-prof/35543
+ * gcc.dg/tree-prof/val-prof-7.c: Add __builtin_memmove.
+
+2018-08-01 Sam Tebbs <sam.tebbs@arm.com>
+
+ * gcc.target/aarch64/extract_zero_extend.c: New file.
+
+2018-08-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/85704
+ * gcc.c-torture/compile/pr85704.c: New test.
+
+2018-07-31 Alexandre Oliva <oliva@adacore.com>
+ Olivier Hainque <hainque@adacore.com>
+
+ * gnat.dg/dinst.adb: New.
+ * gnat.dg/dinst_pkg.ads, gnat.dg/dinst_pkg.adb: New.
+
+2018-07-31 David Malcolm <dmalcolm@redhat.com>
+
+ * gcc.dg/format/gcc_diag-1.c (foo): Update the %v tests for
+ tdiag and cxxdiag.
+ * gcc.dg/format/gcc_diag-10.c (test_diag): Update tests of %G
+ and %K.
+
+2018-07-31 Richard Earnshaw <rearnsha@arm.com>
+
+ * c-c++-common/spec-barrier-1.c: New test.
+ * c-c++-common/spec-barrier-2.c: New test.
+ * gcc.dg/spec-barrier-3.c: New test.
+
+2018-07-31 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/86741
+ * gcc.dg/Warray-bounds-33.c: New test.
+
+2018-07-31 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * gcc.target/s390/memset-1.c: Improve testcase.
+
+2018-07-31 Tom de Vries <tdevries@suse.de>
+
+ PR debug/86687
+ * g++.dg/guality/pr86687.C: New test.
+
+2018-07-31 Jakub Jelinek <jakub@redhat.com>
+
+ P1008R1 - prohibit aggregates with user-declared constructors
+ * g++.dg/ext/is_aggregate.C: Add tests with deleted or defaulted ctor.
+ * g++.dg/cpp0x/defaulted1.C (main): Ifdef out for C++2a B b = {1};.
+ * g++.dg/cpp0x/deleted2.C: Expect error for C++2a.
+ * g++.dg/cpp2a/aggr1.C: New test.
+ * g++.dg/cpp2a/aggr2.C: New test.
+
2018-07-31 Segher Boessenkool <segher@kernel.crashing.org>
PR target/86640
@@ -90,7 +2112,7 @@
2018-07-26 Martin Liska <mliska@suse.cz>
- PR gcov-profile/86536
+ PR gcov-profile/86536
* gcc.misc-tests/gcov-pr86536.c: New test.
2018-07-25 Martin Sebor <msebor@redhat.com>
@@ -131,7 +2153,7 @@
2018-07-24 Matthew Malcomson <matthew.malcomson@arm.com>
- * gcc.target/aarch64/vect-su-add-sub.c: New.
+ * gcc.target/aarch64/simd/vect_su_add_sub.c: New.
2018-07-24 Jakub Jelinek <jakub@redhat.com>
@@ -411,7 +2433,8 @@
2018-07-17 Hristian Kirtchev <kirtchev@adacore.com>
- * gnat.dg/config_pragma1.adb, gnat.dg/config_pragma1_pkg.ads: New testcase.
+ * gnat.dg/config_pragma1.adb, gnat.dg/config_pragma1_pkg.ads:
+ New testcase.
2018-07-17 Ed Schonberg <schonberg@adacore.com>
@@ -427,7 +2450,8 @@
2018-07-17 Hristian Kirtchev <kirtchev@adacore.com>
- * gnat.dg/bip_case_expr.adb, gnat.dg/bip_case_expr_pkg.ads: New testcase.
+ * gnat.dg/bip_case_expr.adb, gnat.dg/bip_case_expr_pkg.ads:
+ New testcase.
2018-07-16 Carl Love <cel@us.ibm.com>
@@ -440,7 +2464,7 @@
* gcc.target/powerpc/divkc3-2.c: Add dg-require-effective-target
longdouble128.
* gcc.target/powerpc/divkc3-3.c: Ditto.
- * gcc.target/powerpc/mulkc3-2.c: Ditto.
+ * gcc.target/powerpc/mulkc3-2.c: Ditto.
* gcc.target/powerpc/mulkc3-3.c: Ditto.
* gcc.target/powerpc/fold-vec-mergehl-double.c: Update counts.
* gcc.target/powerpc/pr85456.c: Make check Linux and AIX specific.
@@ -469,10 +2493,10 @@
2018-07-16 Carl Love <cel@us.ibm.com>
- * gcc.target/powerpc/divkc3-2.c: Add dg-require-effective-target
+ * gcc.target/powerpc/divkc3-2.c: Add dg-require-effective-target
longdouble128.
* gcc.target/powerpc/divkc3-3.c: Ditto.
- * gcc.target/powerpc/mulkc3-2.c: Ditto.
+ * gcc.target/powerpc/mulkc3-2.c: Ditto.
* gcc.target/powerpc/mulkc3-3.c: Ditto.
* gcc.target/powerpc/fold-vec-mergehl-double.c: Update counts.
* gcc.target/powerpc/pr85456.c: Make check Linux and AIX specific.
@@ -542,7 +2566,7 @@
2018-07-16 Martin Liska <mliska@suse.cz>
- PR ipa/86529
+ PR ipa/86529
* g++.dg/ipa/pr86529.C: New test.
2018-07-16 Tom de Vries <tdevries@suse.de>
@@ -636,7 +2660,7 @@
2018-07-12 Kito Cheng <kito.cheng@gmail.com>
- * gcc.target/riscv/interrupt-conflict-mode.c: New.
+ * gcc.target/riscv/interrupt-conflict-mode.c: New.
2018-07-12 Jakub Jelinek <jakub@redhat.com>
@@ -769,7 +2793,7 @@
2018-07-10 Martin Liska <mliska@suse.cz>
- PR testsuite/86445
+ PR testsuite/86445
* gcc.dg/pr84100.c: Change it back to dg-bogus.
2018-07-10 Jakub Jelinek <jakub@redhat.com>
@@ -1181,7 +3205,7 @@
2018-07-02 Martin Liska <mliska@suse.cz>
- PR testsuite/86366
+ PR testsuite/86366
* gcc.dg/profile-dir-1.c: Fix scanned pattern.
* gcc.dg/profile-dir-2.c: Likewise.
* gcc.dg/profile-dir-3.c: Likewise.
@@ -1215,12 +3239,12 @@
2018-07-02 Martin Liska <mliska@suse.cz>
- PR ipa/86279
+ PR ipa/86279
* gcc.dg/ipa/pr86279.c: New test.
2018-07-02 Martin Liska <mliska@suse.cz>
- PR ipa/86323
+ PR ipa/86323
* g++.dg/ipa/pr86323.C: New test.
2018-07-01 Tom de Vries <tdevries@suse.de>
@@ -1343,7 +3367,7 @@
2018-06-29 Martin Liska <mliska@suse.cz>
- PR tree-optimization/86263
+ PR tree-optimization/86263
* gcc.dg/tree-ssa/pr86263.c: New test.
2018-06-28 Carl Love <cel@us.ibm.com>
@@ -1389,7 +3413,7 @@
* gcc.target/vsx-vector-abss.c: New file to test vec_abss.
-2018-06-27 Tamar Christina <tamar.christina@arm.com>
+2018-06-27 Tamar Christina <tamar.christina@arm.com>
PR target/85769
* gcc.target/aarch64/f16_mov_immediate_3.c: New.
@@ -1456,7 +3480,7 @@
2018-06-25 Carl Love <cel@us.ibm.com>
* gcc.target/powerpc/p9-extract-1.c: Make second argument of
- vec_extract a signed int. Add vec_extract tests for bool char
+ vec_extract a signed int. Add vec_extract tests for bool char
and bool int.
* gcc.target/powerpc/p9-extract-4.c: New test file for long long
vec_extract tests.
@@ -1534,14 +3558,14 @@
2018-06-22 Carl Love <cel@us.ibm.com>
- * gcc.target/powerpc/altivec-7.c: Add qualifiers for counts on AIX
+ * gcc.target/powerpc/altivec-7.c: Add qualifiers for counts on AIX
versus Linux. Change checks for xxlnor, xxland and xxlxor to also look
for the vnor, vand and vxor instructions.
* gcc.target/powerpc/builtins-1.c: Move vec_or tests to a new file.
Remove counts for xxlor. Fix match on bl __divdi3 and bl __udivdi3.
* gcc.target/powerpc/builtins-4.c: Fix matching for vsl instructions.
* gcc.target/powerpc/builtins-5.c: New test file for vec_or test cases.
- * gcc.target/powerpc/vsx-vector-6.p7.c: Fix xxlnor BE expected count.
+ * gcc.target/powerpc/vsx-vector-6.p7.c: Fix xxlnor BE expected count.
Add -dp to dg-options, update expected counts.
2018-06-22 Paul Koning <ni1d@arrl.net>
@@ -2071,7 +4095,7 @@
2018-06-11 Martin Liska <mliska@suse.cz>
- PR tree-optimization/86089
+ PR tree-optimization/86089
* gcc.dg/tree-ssa/pr86089.c: New test.
2018-06-11 Julia Koval <julia.koval@intel.com>
@@ -2189,18 +4213,18 @@
2018-06-08 Carl Love <cel@us.ibm.com>
- * gcc.target/powerpc/p8vector-builtin-3.c: Add vec_pack test. Update
+ * gcc.target/powerpc/p8vector-builtin-3.c: Add vec_pack test. Update
vpkudum counts.
- * gcc.target/powerpc/p9-extract-3.c: Make second argument of
+ * gcc.target/powerpc/p9-extract-3.c: Make second argument of
vec_extract a signed int.
- * gcc.target/powerpc/vec-cmp.c: Add vec_cmple, vec_cmpge tests. Update,
+ * gcc.target/powerpc/vec-cmp.c: Add vec_cmple, vec_cmpge tests. Update,
vcmpgtsb, vcmpgtub, vcmpgtsh, vcmpgtuh, vcmpgtsw, vcmpgtsw, vcmpgtuw,
vcmpgtsd, vcmpgtud.
* gcc.target/powerpc/vsx-extract-4.c: Make second argument of
vec_extract a signed int.
* gcc.target/powerpc/vsx-extract-5.c: Make second argument of
vec_extract a signed int.
- * gcc.target/powerpc/vsx-vector-7.c (foo): Add tests for vec_sel and
+ * gcc.target/powerpc/vsx-vector-7.c (foo): Add tests for vec_sel and
vec_xor builtins. Update xxsel, xxlxor counts.
2018-06-08 Steven G. Kargl <kargl@gcc.gnu.org>
@@ -2635,8 +4659,8 @@
2018-06-07 Carl Love <cel@us.ibm.com>
- * gcc.target/powerpc/vsu/vec-cntlz-lsbb-2.c (dg-error): Update expected
- error message.
+ * gcc.target/powerpc/vsu/vec-cntlz-lsbb-2.c (dg-error): Update expected
+ error message.
2018-06-07 Marek Polacek <polacek@redhat.com>
@@ -3947,7 +5971,7 @@
* g++.dg/cpp0x/initlist-throw1.C: New test.
* g++.dg/cpp0x/initlist-throw2.C: New test.
-2018-05-16 Carl Love <cel@us.ibm.com>
+2018-05-16 Carl Love <cel@us.ibm.com>
* gcc.target/powerpc/vsx-vector-6-be.c: Remove file.
* gcc.target/powerpc/vsx-vector-6-le.c (dg-final): Update counts for
@@ -4497,7 +6521,7 @@
* gcc.target/arc/store-merge-1.c: New test.
* gcc.target/arc/add_n-combine.c: Update test.
-2018-04-30 Andrew Sadek <andrew.sadek.se@gmail.com>
+2018-04-30 Andrew Sadek <andrew.sadek.se@gmail.com>
Microblaze Target: PIC data text relative
@@ -11240,7 +13264,7 @@
2018-02-01 Marek Polacek <polacek@redhat.com>
PR c++/84125
- * g++.dg/cpp1y/lambda-generic-84125.C:New test.
+ * g++.dg/cpp1y/lambda-generic-84125.C: New test.
2018-01-30 Jeff Law <law@redhat.com>
diff --git a/gcc/testsuite/c-c++-common/Wmisleading-indentation-pr70693.c b/gcc/testsuite/c-c++-common/Wmisleading-indentation-pr70693.c
new file mode 100644
index 0000000..0869b11
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wmisleading-indentation-pr70693.c
@@ -0,0 +1,12 @@
+/* { dg-options "-Wmisleading-indentation" } */
+
+int in_what; /* */
+
+void process_char(char c) {
+ switch( 0 ) {
+ case 0:
+ if( c == '>' ) in_what = 0;
+ break;
+
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/array-init.c b/gcc/testsuite/c-c++-common/array-init.c
new file mode 100644
index 0000000..3cc5722
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/array-init.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-prune-output "sorry, unimplemented: non-trivial designated initializers not supported" } */
+/* { dg-prune-output "all initializer clauses should be designated" } */
+
+char x[] = { [-1] = 1, 2, 3 }; /* { dg-error "array index in initializer exceeds array bounds" "" { target c } } */
diff --git a/gcc/testsuite/c-c++-common/asan/pointer-subtract-3.c b/gcc/testsuite/c-c++-common/asan/pointer-subtract-3.c
index 7cae91b..b434aaa 100644
--- a/gcc/testsuite/c-c++-common/asan/pointer-subtract-3.c
+++ b/gcc/testsuite/c-c++-common/asan/pointer-subtract-3.c
@@ -1,4 +1,5 @@
/* { dg-do run { target pthread_h } } */
+/* { dg-skip-if "no pthread_barrier" { *-*-darwin* } } */
/* { dg-set-target-env-var ASAN_OPTIONS "detect_invalid_pointer_pairs=2:halt_on_error=1" } */
/* { dg-options "-fsanitize=address,pointer-subtract" } */
/* { dg-additional-options "-pthread" { target pthread } } */
diff --git a/gcc/testsuite/c-c++-common/asan/pointer-subtract-4.c b/gcc/testsuite/c-c++-common/asan/pointer-subtract-4.c
index af65c59..4931c21 100644
--- a/gcc/testsuite/c-c++-common/asan/pointer-subtract-4.c
+++ b/gcc/testsuite/c-c++-common/asan/pointer-subtract-4.c
@@ -1,4 +1,5 @@
/* { dg-do run { target pthread_h } } */
+/* { dg-skip-if "no pthread_barrier" { *-*-darwin* } } */
/* { dg-shouldfail "asan" } */
/* { dg-set-target-env-var ASAN_OPTIONS "detect_invalid_pointer_pairs=2:halt_on_error=1" } */
/* { dg-options "-fsanitize=address,pointer-subtract" } */
diff --git a/gcc/testsuite/c-c++-common/attr-nonstring-3.c b/gcc/testsuite/c-c++-common/attr-nonstring-3.c
index b1eb8b6..a2aaf7b 100644
--- a/gcc/testsuite/c-c++-common/attr-nonstring-3.c
+++ b/gcc/testsuite/c-c++-common/attr-nonstring-3.c
@@ -406,7 +406,7 @@ void test_strlen (struct MemArrays *p, char *s NONSTRING, size_t n)
{
char a[] __attribute__ ((nonstring)) = { 1, 2, 3 };
- T (strlen (a)); /* { dg-warning "argument 1 declared attribute .nonstring." } */
+ T (strlen (a)); /* { dg-warning "argument 1 declared attribute .nonstring." "pr86688" { xfail *-*-* } } */
}
{
diff --git a/gcc/testsuite/c-c++-common/attributes-1.c b/gcc/testsuite/c-c++-common/attributes-1.c
index c76339f..1657da1 100644
--- a/gcc/testsuite/c-c++-common/attributes-1.c
+++ b/gcc/testsuite/c-c++-common/attributes-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-prune-output "undeclared here \\(not in a function\\); did you mean .char..|\[^\n\r\]* was not declared in this scope" } */
+/* { dg-prune-output "undeclared here \\(not in a function\\)|\[^\n\r\]* was not declared in this scope" } */
void* my_calloc(unsigned, unsigned) __attribute__((alloc_size(1,bar))); /* { dg-warning "outside range" } */
void* my_realloc(void*, unsigned) __attribute__((alloc_size(bar))); /* { dg-warning "outside range" } */
diff --git a/gcc/testsuite/c-c++-common/dump-ada-spec-14.c b/gcc/testsuite/c-c++-common/dump-ada-spec-14.c
new file mode 100644
index 0000000..bfdec61
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/dump-ada-spec-14.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-ada-spec" } */
+
+struct __attribute__((packed)) S /* { dg-warning "unsupported record layout" } */
+{
+ char c;
+ int t;
+};
+
+/* { dg-final { cleanup-ada-spec } } */
diff --git a/gcc/testsuite/c-c++-common/ident-0a.c b/gcc/testsuite/c-c++-common/ident-0a.c
new file mode 100644
index 0000000..900d206
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ident-0a.c
@@ -0,0 +1,6 @@
+/* PR testsuite/52665
+ * Make sure scan-assembler-not turns off .ident */
+/* { dg-do compile } */
+int i;
+
+/* { dg-final { scan-assembler-not "GCC: " } } */
diff --git a/gcc/testsuite/c-c++-common/ident-0b.c b/gcc/testsuite/c-c++-common/ident-0b.c
new file mode 100644
index 0000000..e08126d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ident-0b.c
@@ -0,0 +1,10 @@
+/* PR testsuite/52665
+ * Make sure scan-assembler-not turns off .ident unless -fident in testcase */
+/* { dg-do compile } */
+/* { dg-options "-fident" } */
+int i;
+
+/* { dg-final { scan-assembler-not "GCC: " { xfail *-*-* } } } */
+/* The testsuite saw scan-assembler-not and turned off .ident so the above
+ * has to fail for proper operation since the testsuite itself forced
+ * -fident on again. */
diff --git a/gcc/testsuite/c-c++-common/ident-1a.c b/gcc/testsuite/c-c++-common/ident-1a.c
new file mode 100644
index 0000000..867ee43
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ident-1a.c
@@ -0,0 +1,8 @@
+/* PR testsuite/52665
+ * Make sure scan-assembler turns off .ident */
+/* { dg-do compile } */
+int i;
+
+/* { dg-final { scan-assembler "GCC: " { xfail *-*-* } } } */
+/* The testsuite saw scan-assembler and turned off .ident so the above
+ * has to fail for proper operation. */
diff --git a/gcc/testsuite/c-c++-common/ident-1b.c b/gcc/testsuite/c-c++-common/ident-1b.c
new file mode 100644
index 0000000..2431086
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ident-1b.c
@@ -0,0 +1,7 @@
+/* PR testsuite/52665
+ * Make sure scan-assembler turns off .ident unless -fident in testcase */
+/* { dg-do compile } */
+/* { dg-options "-fident" } */
+int i;
+
+/* { dg-final { scan-assembler "GCC: " } } */
diff --git a/gcc/testsuite/c-c++-common/ident-2a.c b/gcc/testsuite/c-c++-common/ident-2a.c
new file mode 100644
index 0000000..131b867
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ident-2a.c
@@ -0,0 +1,6 @@
+/* PR testsuite/52665
+ * Make sure scan-assembler-times turns off .ident */
+/* { dg-do compile } */
+int i;
+
+/* { dg-final { scan-assembler-times "GCC: " 0 } } */ /* internal test, keep -times 0 ! */
diff --git a/gcc/testsuite/c-c++-common/ident-2b.c b/gcc/testsuite/c-c++-common/ident-2b.c
new file mode 100644
index 0000000..a21e25f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ident-2b.c
@@ -0,0 +1,7 @@
+/* PR testsuite/52665
+ * Make sure scan-assembler-times turns off .ident unless -fident in testcase */
+/* { dg-do compile } */
+/* { dg-options "-fident" } */
+int ident;
+
+/* { dg-final { scan-assembler-times "GCC: " 1 } } */
diff --git a/gcc/testsuite/c-c++-common/inc-from-1.c b/gcc/testsuite/c-c++-common/inc-from-1.c
new file mode 100644
index 0000000..7e95c2a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/inc-from-1.c
@@ -0,0 +1,5 @@
+#include "inc-from-1b.h"
+
+/* { dg-error "" "" { target *-*-* } 1 } */
+
+/* { dg-regexp "In file included from \[^\n]*inc-from-1b.h:1,\n *from \[^\n]*inc-from-1.c:1:\n" } */
diff --git a/gcc/testsuite/c-c++-common/inc-from-1a.h b/gcc/testsuite/c-c++-common/inc-from-1a.h
new file mode 100644
index 0000000..684e812
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/inc-from-1a.h
@@ -0,0 +1 @@
+void bleah;
diff --git a/gcc/testsuite/c-c++-common/inc-from-1b.h b/gcc/testsuite/c-c++-common/inc-from-1b.h
new file mode 100644
index 0000000..40fae4a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/inc-from-1b.h
@@ -0,0 +1 @@
+#include "inc-from-1a.h"
diff --git a/gcc/testsuite/c-c++-common/pr59521-1.c b/gcc/testsuite/c-c++-common/pr59521-1.c
new file mode 100644
index 0000000..32320b5
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr59521-1.c
@@ -0,0 +1,15 @@
+/* { dg-options "-O2" } */
+/* { dg-do compile } */
+
+extern int puts (const char *);
+
+void
+f(int ch) {
+ switch (ch) {
+ case 3: puts("a"); break;
+ case 42: puts("e"); break;
+ case 333: puts("i"); break;
+ }
+}
+
+/* { dg-final { scan-assembler "cmp.*42,.*cmp.*333,.*cmp.*3," { target i?86-*-* x86_64-*-* } } } */
diff --git a/gcc/testsuite/c-c++-common/pr59521-2.c b/gcc/testsuite/c-c++-common/pr59521-2.c
new file mode 100644
index 0000000..3c48825
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr59521-2.c
@@ -0,0 +1,15 @@
+/* { dg-options "-O2" } */
+/* { dg-do compile } */
+
+extern int puts (const char *);
+
+void
+f(int ch) {
+ switch (__builtin_expect(ch, 333)) {
+ case 3: puts("a"); break;
+ case 42: puts("e"); break;
+ case 333: puts("i"); break;
+ }
+}
+
+/* { dg-final { scan-assembler "cmp.*333,.*cmp.*3,.*cmp.*42," { target i?86-*-* x86_64-*-* } } } */
diff --git a/gcc/testsuite/c-c++-common/spec-barrier-1.c b/gcc/testsuite/c-c++-common/spec-barrier-1.c
new file mode 100644
index 0000000..e4b44f2
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/spec-barrier-1.c
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+/* { dg-options "-O" } */
+
+/* Test that __builtin_speculation_safe_value returns the correct value. */
+/* This test will cause an unfiltered warning to be emitted on targets
+ that have not implemented support for speculative execution
+ barriers. They should fix that rather than disabling this
+ test. */
+char a = 1;
+short b = 2;
+int c = 3;
+long d = 4;
+long long e = 5;
+int *f = (int*) &c;
+#ifdef __SIZEOF_INT128__
+__int128 g = 9;
+#endif
+
+int main ()
+{
+ if (__builtin_speculation_safe_value (a) != 1)
+ __builtin_abort ();
+ if (__builtin_speculation_safe_value (b) != 2)
+ __builtin_abort ();
+ if (__builtin_speculation_safe_value (c) != 3)
+ __builtin_abort ();
+ if (__builtin_speculation_safe_value (d) != 4)
+ __builtin_abort ();
+ if (__builtin_speculation_safe_value (e) != 5)
+ __builtin_abort ();
+ if (__builtin_speculation_safe_value (f) != &c)
+ __builtin_abort ();
+#ifdef __SIZEOF_INT128__
+ if (__builtin_speculation_safe_value (g) != 9)
+ __builtin_abort ();
+#endif
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/spec-barrier-2.c b/gcc/testsuite/c-c++-common/spec-barrier-2.c
new file mode 100644
index 0000000..b09567e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/spec-barrier-2.c
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+
+/* Even on targets that don't need the optional failval parameter,
+ side-effects on the operand should still be calculated. */
+
+int x = 3;
+volatile int y = 9;
+
+int main ()
+{
+ int z = __builtin_speculation_safe_value (x, y++);
+ if (z != 3 || y != 10)
+ __builtin_abort ();
+ return 0;
+}
+
+/* { dg-prune-output "this target does not define a speculation barrier;" } */
diff --git a/gcc/testsuite/c-c++-common/torture/pr87248.c b/gcc/testsuite/c-c++-common/torture/pr87248.c
new file mode 100644
index 0000000..6f89bc9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/pr87248.c
@@ -0,0 +1,36 @@
+/* PR middle-end/87248 */
+/* { dg-do run } */
+
+void
+foo (signed char *p, int q)
+{
+ *p = q & (-__SCHAR_MAX__ - 1) ? (-__SCHAR_MAX__ - 1) : 0;
+}
+
+int
+bar (long long x)
+{
+ return x & (-__INT_MAX__ - 1) ? (-__INT_MAX__ - 1) : 0;
+}
+
+int
+main ()
+{
+#if __INT_MAX__ > 4 * __SCHAR_MAX__
+ signed char a[4];
+ foo (a, __SCHAR_MAX__ + 1U);
+ foo (a + 1, 2 * (__SCHAR_MAX__ + 1U));
+ foo (a + 2, -__INT_MAX__ - 1);
+ foo (a + 3, (__SCHAR_MAX__ + 1U) / 2);
+ if (a[0] != (-__SCHAR_MAX__ - 1) || a[1] != a[0] || a[2] != a[0] || a[3] != 0)
+ __builtin_abort ();
+#endif
+#if __LONG_LONG_MAX__ > 4 * __INT_MAX__
+ if (bar (__INT_MAX__ + 1LL) != (-__INT_MAX__ - 1)
+ || bar (2 * (__INT_MAX__ + 1LL)) != (-__INT_MAX__ - 1)
+ || bar (-__LONG_LONG_MAX__ - 1) != (-__INT_MAX__ - 1)
+ || bar ((__INT_MAX__ + 1LL) / 2) != 0)
+ __builtin_abort ();
+#endif
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/Walloca1.C b/gcc/testsuite/g++.dg/Walloca1.C
index b860a42..2985ac9 100644
--- a/gcc/testsuite/g++.dg/Walloca1.C
+++ b/gcc/testsuite/g++.dg/Walloca1.C
@@ -1,7 +1,9 @@
-/* PR middle-end/79809 */
+/* PR middle-end/79809 - ICE in alloca_call_type, at gimple-ssa-warn-alloca.c */
/* { dg-do compile } */
/* { dg-options "-Walloca-larger-than=4207115063 -Wvla-larger-than=1233877270 -O2" } */
/* { dg-require-effective-target alloca } */
int a;
-char *b = static_cast<char *>(__builtin_alloca (a)); // { dg-warning "argument to .alloca. may be too large|unbounded use of" }
+char *b = static_cast<char *>(__builtin_alloca (a));
+
+// { dg-prune-output "argument to .alloca." }
diff --git a/gcc/testsuite/g++.dg/Wno-frame-address.C b/gcc/testsuite/g++.dg/Wno-frame-address.C
index a2df034..54a02fe 100644
--- a/gcc/testsuite/g++.dg/Wno-frame-address.C
+++ b/gcc/testsuite/g++.dg/Wno-frame-address.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-skip-if "Cannot access arbitrary stack frames." { arm*-*-* hppa*-*-* ia64-*-* } }
+// { dg-skip-if "Cannot access arbitrary stack frames." { arm*-*-* hppa*-*-* ia64-*-* csky*-*-* } }
// { dg-options "-Werror" }
// { dg-additional-options "-mbackchain" { target s390*-*-* } }
diff --git a/gcc/testsuite/g++.dg/abi/pr87137.C b/gcc/testsuite/g++.dg/abi/pr87137.C
new file mode 100644
index 0000000..ffb8b01
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/pr87137.C
@@ -0,0 +1,40 @@
+// PR c++/87137
+
+// Empty macro args are undefined in C++ 98
+// { dg-do compile { target c++11 } }
+
+// We got confused by non-field decls separating bitfields when
+// ms_bitfield_layout was in effect.
+
+#if defined (__x86_64__) || defined (__i686__) || defined (__powerpc__)
+#define ATTRIB __attribute__((ms_struct))
+#elif defined (__superh__)
+#define ATTRIB __attribute__((renesas))
+#else
+#define ATTRIB
+#endif
+
+#define DEFINE(NAME,BASE,THING) \
+ struct ATTRIB NAME BASE { \
+ unsigned one : 12; \
+ THING \
+ unsigned two : 4; \
+ }
+
+template<unsigned I, unsigned J> struct Test;
+template<unsigned I> struct Test<I,I> {};
+
+#define TEST(NAME,BASE,THING) \
+ DEFINE(NAME##_WITH,BASE,THING); \
+ DEFINE(NAME##_WITHOUT,BASE,); \
+ int NAME = sizeof (Test<sizeof(NAME##_WITH),sizeof (NAME##_WITHOUT)>)
+
+TEST(NSFun,,int fun (););
+TEST(SFun,,static int fun (););
+TEST(Tdef,,typedef int tdef;);
+
+TEST(Var,,static int var;);
+struct base { int f; };
+TEST(Use,:base,using base::f;);
+TEST(Tmpl,,template<unsigned> class X {};);
+TEST(TmplFN,,template<unsigned> void fu (););
diff --git a/gcc/testsuite/g++.dg/asan/pr85774.C b/gcc/testsuite/g++.dg/asan/pr85774.C
new file mode 100644
index 0000000..c033abf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/pr85774.C
@@ -0,0 +1,51 @@
+/* PR sanitizer/85774 */
+/* { dg-do run } */
+
+#include <functional>
+
+void
+DoSomething ()
+{
+}
+
+void
+DoFunc (const std::function<void(void)> &func)
+{
+ func ();
+}
+
+void
+Setup ()
+{
+ switch (1)
+ {
+ case 1:
+ {
+ DoFunc ([]() {});
+ break;
+ }
+ case 2:
+ {
+ DoFunc ([]() {});
+ break;
+ }
+ default:
+ break;
+ }
+
+ DoSomething ();
+}
+
+void
+DemostrateBadPoisoning ()
+{
+ DoFunc ([]() {});
+}
+
+int
+main ()
+{
+ Setup ();
+ DemostrateBadPoisoning ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/concepts/pr67595.C b/gcc/testsuite/g++.dg/concepts/pr67595.C
index 63162fb..76d1fe6 100644
--- a/gcc/testsuite/g++.dg/concepts/pr67595.C
+++ b/gcc/testsuite/g++.dg/concepts/pr67595.C
@@ -4,7 +4,7 @@ template <class X> concept bool allocatable = requires{{new X}->X * };
template <class X> concept bool semiregular = allocatable<X>;
template <class X> concept bool readable = requires{requires semiregular<X>};
template <class> int weak_input_iterator = requires{{0}->readable};
-template <class X> bool input_iterator{weak_input_iterator<X>};
+template <class X> bool input_iterator{weak_input_iterator<X>}; // { dg-warning "narrowing conversion" }
template <class X> bool forward_iterator{input_iterator<X>};
template <class X> bool bidirectional_iterator{forward_iterator<X>};
template <class X>
diff --git a/gcc/testsuite/g++.dg/concepts/pr84980.C b/gcc/testsuite/g++.dg/concepts/pr84980.C
new file mode 100644
index 0000000..619c0bd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr84980.C
@@ -0,0 +1,6 @@
+// { dg-do compile { target c++14 } }
+// { dg-additional-options "-fconcepts" }
+
+template<T> concept bool C = true; // { dg-error "has not been declared" }
+
+template<C...> struct A;
diff --git a/gcc/testsuite/g++.dg/concepts/pr85065.C b/gcc/testsuite/g++.dg/concepts/pr85065.C
new file mode 100644
index 0000000..861a838
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr85065.C
@@ -0,0 +1,6 @@
+// { dg-do compile { target c++14 } }
+// { dg-additional-options "-fconcepts" }
+
+template<int> concept bool C = true;
+
+C c = 0; // { dg-error "invalid reference to concept" }
diff --git a/gcc/testsuite/g++.dg/concepts/pr85265.C b/gcc/testsuite/g++.dg/concepts/pr85265.C
new file mode 100644
index 0000000..86124ce
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr85265.C
@@ -0,0 +1,6 @@
+// { dg-do compile { target c++14 } }
+// { dg-additional-options "-fconcepts" }
+
+template<typename> concept bool C = true;
+
+C{} void foo(); // { dg-error "expected identifier" }
diff --git a/gcc/testsuite/g++.dg/conversion/Wwrite-strings.C b/gcc/testsuite/g++.dg/conversion/Wwrite-strings.C
new file mode 100644
index 0000000..f6dbb15
--- /dev/null
+++ b/gcc/testsuite/g++.dg/conversion/Wwrite-strings.C
@@ -0,0 +1,24 @@
+// { dg-options "-fdiagnostics-show-caret" }
+
+/* Verify that -Wwrite-strings underlines the string literal in question. */
+
+extern int callee (const char *one, char *two, const char *three);
+
+int test_1 ()
+{
+ return callee ("first", "second", "third"); // { dg-warning "string constant to 'char\\*'" }
+ /* { dg-begin-multiline-output "" }
+ return callee ("first", "second", "third");
+ ^~~~~~~~
+ { dg-end-multiline-output "" } */
+ // TODO: underline the pertinent param in the decl of callee
+}
+
+char *test_2 (void)
+{
+ return "foo"; // { dg-warning "string constant to 'char\\*'" }
+ /* { dg-begin-multiline-output "" }
+ return "foo";
+ ^~~~~
+ { dg-end-multiline-output "" } */
+}
diff --git a/gcc/testsuite/g++.dg/conversion/op4.C b/gcc/testsuite/g++.dg/conversion/op4.C
index cb99a38..3fb850c 100644
--- a/gcc/testsuite/g++.dg/conversion/op4.C
+++ b/gcc/testsuite/g++.dg/conversion/op4.C
@@ -4,7 +4,7 @@
struct X {
int x;
X (int i = 0) : x (i) {}
- operator X& (void) const {
+ operator X& (void) const { // { dg-warning "will never use" }
return *(new X);
}
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wnarrowing10.C b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing10.C
new file mode 100644
index 0000000..8414b53
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing10.C
@@ -0,0 +1,5 @@
+// PR c++/57891
+// { dg-do compile { target c++11 } }
+
+template<int N, unsigned char M = N> struct S { char a[N]; };
+S<1000> s; // { dg-error "narrowing conversion" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wnarrowing11.C b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing11.C
new file mode 100644
index 0000000..5b73236
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing11.C
@@ -0,0 +1,30 @@
+// PR c++/65043
+// { dg-do compile { target c++11 } }
+
+struct X
+{
+ X(bool) { }
+};
+
+struct Y
+{
+ Y(char) { }
+};
+
+struct Z
+{
+ Z(char16_t) { }
+};
+
+struct W
+{
+ W(char32_t) { }
+};
+
+int main()
+{
+ X x{1.2}; // { dg-error "narrowing conversion" }
+ Y y{1.2}; // { dg-error "narrowing conversion" }
+ Z z{1.2}; // { dg-error "narrowing conversion" }
+ W w{1.2}; // { dg-error "narrowing conversion" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wnarrowing12.C b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing12.C
new file mode 100644
index 0000000..83b4d3a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing12.C
@@ -0,0 +1,32 @@
+// PR c++/65043
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wnarrowing" }
+
+struct X
+{
+ X(bool) { }
+};
+
+struct Y
+{
+ Y(char) { }
+};
+
+struct Z
+{
+ Z(char16_t) { }
+};
+
+struct W
+{
+ W(char32_t) { }
+};
+
+int main()
+{
+ double d = 1.2;
+ X x{d}; // { dg-warning "narrowing conversion" }
+ Y y{d}; // { dg-warning "narrowing conversion" }
+ Z z{d}; // { dg-warning "narrowing conversion" }
+ W w{d}; // { dg-warning "narrowing conversion" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wnarrowing6.C b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing6.C
new file mode 100644
index 0000000..989d277
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing6.C
@@ -0,0 +1,8 @@
+// PR c++/57891
+// { dg-do compile { target c++11 } }
+
+template<unsigned int> struct A {};
+A<-1> a; // { dg-error "narrowing conversion" }
+
+template<signed char> struct B {};
+B<1000> b; // { dg-error "narrowing conversion" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wnarrowing7.C b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing7.C
new file mode 100644
index 0000000..099fdfb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing7.C
@@ -0,0 +1,9 @@
+// PR c++/57891
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wno-narrowing" }
+
+template<unsigned int> struct A {};
+A<-1> a;
+
+template<signed char> struct B {};
+B<1000> b; // { dg-warning "overflow" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wnarrowing8.C b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing8.C
new file mode 100644
index 0000000..39c924c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing8.C
@@ -0,0 +1,6 @@
+// PR c++/57891
+// { dg-do compile { target c++11 } }
+
+struct X { constexpr operator int () { return 1000; } };
+template<signed char> struct C {};
+C<X{}> c; // { dg-error "narrowing conversion" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wnarrowing9.C b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing9.C
new file mode 100644
index 0000000..bc8a736
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing9.C
@@ -0,0 +1,6 @@
+// PR c++/57891
+// { dg-do compile { target c++11 } }
+
+// N is value-dependent, don't warn.
+template<int N> struct S { char a[N]; }; // { dg-bogus "narrowing conversion" }
+S<1> s;
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move1.C b/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move1.C
new file mode 100644
index 0000000..858bed6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move1.C
@@ -0,0 +1,132 @@
+// PR c++/86981
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wpessimizing-move" }
+
+// Define std::move.
+namespace std {
+ template<typename _Tp>
+ struct remove_reference
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ struct remove_reference<_Tp&>
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ struct remove_reference<_Tp&&>
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ constexpr typename std::remove_reference<_Tp>::type&&
+ move(_Tp&& __t) noexcept
+ { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
+}
+
+struct T {
+ T() { }
+ T(const T&) { }
+ T(T&&) { }
+};
+struct U {
+ U() { }
+ U(const U&) { }
+ U(U&&) { }
+ U(T) { }
+};
+
+T g;
+
+T
+fn1 ()
+{
+ T t;
+ return std::move (t); // { dg-warning "moving a local object in a return statement prevents copy elision" }
+}
+
+T
+fn2 ()
+{
+ // Not a local variable.
+ return std::move (g);
+}
+
+int
+fn3 ()
+{
+ int i = 42;
+ // Not a class type.
+ return std::move (i);
+}
+
+T
+fn4 (bool b)
+{
+ T t;
+ if (b)
+ throw std::move (t);
+ return std::move (t); // { dg-warning "moving a local object in a return statement prevents copy elision" }
+}
+
+T
+fn5 (T t)
+{
+ // Function parameter; std::move is redundant but not pessimizing.
+ return std::move (t);
+}
+
+U
+fn6 (T t, U u, bool b)
+{
+ if (b)
+ return std::move (t);
+ else
+ // Function parameter; std::move is redundant but not pessimizing.
+ return std::move (u);
+}
+
+U
+fn6 (bool b)
+{
+ T t;
+ U u;
+ if (b)
+ return std::move (t);
+ else
+ return std::move (u); // { dg-warning "moving a local object in a return statement prevents copy elision" }
+}
+
+T
+fn7 ()
+{
+ static T t;
+ // Non-local; don't warn.
+ return std::move (t);
+}
+
+T
+fn8 ()
+{
+ return T();
+}
+
+T
+fn9 (int i)
+{
+ T t;
+
+ switch (i)
+ {
+ case 1:
+ return std::move ((t)); // { dg-warning "moving a local object in a return statement prevents copy elision" }
+ case 2:
+ return (std::move (t)); // { dg-warning "moving a local object in a return statement prevents copy elision" }
+ default:
+ return (std::move ((t))); // { dg-warning "moving a local object in a return statement prevents copy elision" }
+ }
+}
+
+int
+fn10 ()
+{
+ return std::move (42);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move2.C b/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move2.C
new file mode 100644
index 0000000..0ee6e05
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move2.C
@@ -0,0 +1,14 @@
+// PR c++/86981
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wpessimizing-move" }
+
+#include <string>
+#include <tuple>
+#include <utility>
+
+std::tuple<std::string, std::string>
+foo ()
+{
+ std::pair<std::string, std::string> p;
+ return std::move (p);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move3.C b/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move3.C
new file mode 100644
index 0000000..a1af123
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move3.C
@@ -0,0 +1,59 @@
+// PR c++/86981
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wpessimizing-move" }
+
+// Define std::move.
+namespace std {
+ template<typename _Tp>
+ struct remove_reference
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ struct remove_reference<_Tp&>
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ struct remove_reference<_Tp&&>
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ constexpr typename std::remove_reference<_Tp>::type&&
+ move(_Tp&& __t) noexcept
+ { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
+}
+
+struct T { };
+struct U { U(T); };
+
+template<typename Tp>
+T
+fn1 ()
+{
+ T t;
+ // Non-dependent type.
+ return std::move (t); // { dg-warning "moving a local object in a return statement prevents copy elision" }
+}
+
+template<typename Tp1, typename Tp2>
+Tp1
+fn2 ()
+{
+ Tp2 t;
+ return std::move (t); // { dg-warning "moving a local object in a return statement prevents copy elision" }
+}
+
+template<typename Tp1, typename Tp2>
+Tp1
+fn3 ()
+{
+ Tp2 t;
+ return std::move (t);
+}
+
+int
+main ()
+{
+ fn1<T>();
+ fn2<T, T>();
+ fn3<U, T>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move4.C b/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move4.C
new file mode 100644
index 0000000..59e148e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move4.C
@@ -0,0 +1,46 @@
+// PR c++/86981
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wpessimizing-move" }
+
+// Define std::move.
+namespace std {
+ template<typename _Tp>
+ struct remove_reference
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ struct remove_reference<_Tp&>
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ struct remove_reference<_Tp&&>
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ constexpr typename std::remove_reference<_Tp>::type&&
+ move(_Tp&& __t) noexcept
+ { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
+}
+
+struct T { };
+
+T
+fn1 ()
+{
+ T t;
+ return (1, std::move (t));
+}
+
+T
+fn2 ()
+{
+ T t;
+ return [&](){ return std::move (t); }();
+}
+
+T
+fn3 ()
+{
+ T t;
+ return [=](){ return std::move (t); }();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move5.C b/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move5.C
new file mode 100644
index 0000000..02ad211
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move5.C
@@ -0,0 +1,14 @@
+// PR c++/87080
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wpessimizing-move" }
+
+struct a {
+ template<typename b> a &operator<<(b);
+};
+a c();
+template<typename>
+a fn2()
+{
+ int d = 42;
+ return c() << d;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wredundant-move1.C b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move1.C
new file mode 100644
index 0000000..5d4a25d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move1.C
@@ -0,0 +1,106 @@
+// PR c++/87029
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wredundant-move" }
+
+// Define std::move.
+namespace std {
+ template<typename _Tp>
+ struct remove_reference
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ struct remove_reference<_Tp&>
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ struct remove_reference<_Tp&&>
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ constexpr typename std::remove_reference<_Tp>::type&&
+ move(_Tp&& __t) noexcept
+ { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
+}
+
+struct T {
+ T() { }
+ T(const T&) { }
+ T(T&&) { }
+};
+
+struct U {
+ U() { }
+ U(const U&) { }
+ U(U&&) { }
+ U(T) { }
+};
+
+T
+fn1 (T t)
+{
+ return t;
+}
+
+T
+fn2 (T t)
+{
+ // Will use move even without std::move.
+ return std::move (t); // { dg-warning "redundant move in return statement" }
+}
+
+T
+fn3 (const T t)
+{
+ // t is const: will decay into copy.
+ return t;
+}
+
+T
+fn4 (const T t)
+{
+ // t is const: will decay into copy despite std::move, so it's redundant.
+ return std::move (t); // { dg-warning "redundant move in return statement" }
+}
+
+int
+fn5 (int i)
+{
+ // Not a class type.
+ return std::move (i);
+}
+
+T
+fn6 (T t, bool b)
+{
+ if (b)
+ throw std::move (t);
+ return std::move (t); // { dg-warning "redundant move in return statement" }
+}
+
+U
+fn7 (T t)
+{
+ // Core 1579 means we'll get a move here.
+ return t;
+}
+
+U
+fn8 (T t)
+{
+ // Core 1579 means we'll get a move here. Even without std::move.
+ return std::move (t); // { dg-warning "redundant move in return statement" }
+}
+
+T
+fn9 (T& t)
+{
+ // T is a reference and the move isn't redundant.
+ return std::move (t);
+}
+
+T
+fn10 (T&& t)
+{
+ // T is a reference and the move isn't redundant.
+ return std::move (t);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wredundant-move2.C b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move2.C
new file mode 100644
index 0000000..f181afe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move2.C
@@ -0,0 +1,57 @@
+// PR c++/87029
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wredundant-move" }
+
+// Define std::move.
+namespace std {
+ template<typename _Tp>
+ struct remove_reference
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ struct remove_reference<_Tp&>
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ struct remove_reference<_Tp&&>
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ constexpr typename std::remove_reference<_Tp>::type&&
+ move(_Tp&& __t) noexcept
+ { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
+}
+
+struct T { };
+struct U { U(T); };
+
+template<typename Tp>
+T
+fn1 (T t)
+{
+ // Non-dependent type.
+ return std::move (t); // { dg-warning "redundant move in return statement" }
+}
+
+template<typename Tp1, typename Tp2>
+Tp1
+fn2 (Tp2 t)
+{
+ return std::move (t); // { dg-warning "redundant move in return statement" }
+}
+
+template<typename Tp1, typename Tp2>
+Tp1
+fn3 (Tp2 t)
+{
+ return std::move (t); // { dg-warning "redundant move in return statement" }
+}
+
+int
+main ()
+{
+ T t;
+ fn1<T>(t);
+ fn2<T, T>(t);
+ fn3<U, T>(t);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wredundant-move3.C b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move3.C
new file mode 100644
index 0000000..7084134
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move3.C
@@ -0,0 +1,43 @@
+// PR c++/87029
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wredundant-move" }
+
+// Define std::move.
+namespace std {
+ template<typename _Tp>
+ struct remove_reference
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ struct remove_reference<_Tp&>
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ struct remove_reference<_Tp&&>
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ constexpr typename std::remove_reference<_Tp>::type&&
+ move(_Tp&& __t) noexcept
+ { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
+}
+
+struct T { };
+
+T
+fn1 (T t)
+{
+ return (1, std::move (t));
+}
+
+T
+fn2 (T t)
+{
+ return [&](){ return std::move (t); }();
+}
+
+T
+fn3 (T t)
+{
+ return [=](){ return std::move (t); }();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wredundant-move4.C b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move4.C
new file mode 100644
index 0000000..aa89e46
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wredundant-move4.C
@@ -0,0 +1,86 @@
+// PR c++/87029
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wredundant-move" }
+
+// Define std::move.
+namespace std {
+ template<typename _Tp>
+ struct remove_reference
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ struct remove_reference<_Tp&>
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ struct remove_reference<_Tp&&>
+ { typedef _Tp type; };
+
+ template<typename _Tp>
+ constexpr typename std::remove_reference<_Tp>::type&&
+ move(_Tp&& __t) noexcept
+ { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
+}
+
+struct T {
+ T() { }
+ T(const T&) { }
+ T(T&&) { }
+};
+
+struct U {
+ U() { }
+ U(const U&) { }
+ U(U&&) { }
+ U(T) { }
+};
+
+U
+fn1 (T t, bool b)
+{
+ if (b)
+ return t;
+ else
+ return std::move (t); // { dg-warning "redundant move in return statement" }
+}
+
+U
+fn2 (bool b)
+{
+ T t;
+ if (b)
+ return t;
+ else
+ return std::move (t); // { dg-warning "redundant move in return statement" }
+}
+
+U
+fn3 (bool b)
+{
+ static T t;
+ if (b)
+ return t;
+ else
+ return std::move (t);
+}
+
+T g;
+
+U
+fn4 (bool b)
+{
+ if (b)
+ return g;
+ else
+ return std::move (g);
+}
+
+long int
+fn5 (bool b)
+{
+ int i = 42;
+ if (b)
+ return i;
+ else
+ return std::move (i);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto52.C b/gcc/testsuite/g++.dg/cpp0x/auto52.C
new file mode 100644
index 0000000..9bfe7c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/auto52.C
@@ -0,0 +1,6 @@
+// PR c++/86942
+// { dg-do compile { target c++11 } }
+
+using T = auto() -> int;
+using U = void() -> int; // { dg-error "function with trailing return type not declared with .auto." }
+using W = auto(); // { dg-error "invalid use of .auto." }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-47969.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-47969.C
index 933831b..201ee17 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-47969.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-47969.C
@@ -8,4 +8,4 @@ struct A
constexpr A a = A();
-int ar[a]; // { dg-error "has non-integral type" }
+int ar[a]; // { dg-error "could not convert|has non-integral type" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-data2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-data2.C
index 8981021..dee5ed8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-data2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-data2.C
@@ -43,4 +43,4 @@ extern template struct A3<int, 510>;
// Use.
A3<int, 1111> a31;
-A3<char, 9999> a32; // { dg-warning "overflow" }
+A3<char, 9999> a32; // { dg-error "narrowing conversion" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex2.C
index 34b557c..ceae9cb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex2.C
@@ -18,5 +18,5 @@ constexpr A a = 42;
X<a> x; // OK: unique conversion to int
int ar[X<a>::i]; // also OK
-int ary[a]; // { dg-error "ambiguous|conversion|array" } ambiguous conversion
+int ary[a]; // { dg-error "could not convert|ambiguous|conversion|array" } ambiguous conversion
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-targ.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-targ.C
index 98bb502..0f1f113 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-targ.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-targ.C
@@ -10,4 +10,4 @@ struct B
{ };
constexpr A a { };
-B<a> b; // { dg-error "template argument|converted constant" }
+B<a> b; // { dg-error "template argument|converted constant|could not convert" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual5.C
index 2465f9d..5f9ab4d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual5.C
@@ -2,5 +2,5 @@
// { dg-do compile { target c++11 } }
struct S {
- constexpr virtual int f() { return 1; } // { dg-error "13:member .f. cannot be declared both .virtual. and .constexpr." }
+ constexpr virtual int f() { return 1; } // { dg-error "13:member .f. can be declared both .virtual. and .constexpr." "" { target c++17_down } }
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted1.C b/gcc/testsuite/g++.dg/cpp0x/defaulted1.C
index 4956e88..0ed81fb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted1.C
@@ -23,7 +23,9 @@ struct B
int main()
{
A a1, a2;
+#if __cplusplus <= 201703L
B b = {1};
+#endif
a1 = a2;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/deleted2.C b/gcc/testsuite/g++.dg/cpp0x/deleted2.C
index 8590c49..5576be3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/deleted2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/deleted2.C
@@ -6,4 +6,4 @@ struct A {
A() = delete;
};
-A a = {1};
+A a = {1}; // { dg-error "could not convert" "" { target c++2a } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/desig5.C b/gcc/testsuite/g++.dg/cpp0x/desig5.C
new file mode 100644
index 0000000..ed27629
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/desig5.C
@@ -0,0 +1,13 @@
+// PR c++/87324
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wno-pedantic" }
+
+struct {
+ struct {
+ double a;
+ struct {
+ short b;
+ };
+ };
+ int c;
+} d{.a = 7, .a = 8.09}; // { dg-error "designator used multiple times in the same initializer list" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit4.C b/gcc/testsuite/g++.dg/cpp0x/explicit4.C
index 346a6e2..065a473 100644
--- a/gcc/testsuite/g++.dg/cpp0x/explicit4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/explicit4.C
@@ -13,5 +13,5 @@ int main()
{
B b;
(A(b)); // OK
- (A(b,1)); // { dg-error "no match" }
+ (A(b,1)); // { dg-error "cannot convert" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/inline-ns10.C b/gcc/testsuite/g++.dg/cpp0x/inline-ns10.C
index 3ab425f..68e8034 100644
--- a/gcc/testsuite/g++.dg/cpp0x/inline-ns10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/inline-ns10.C
@@ -2,7 +2,10 @@
// { dg-do compile { target c++11 } }
inline namespace {
- namespace {}
+ namespace {} // not this one
+ void a ();
}
-namespace {} // { dg-error "conflicts" }
+namespace {
+ int a (); // { dg-error "ambiguating" "" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const-this.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const-this.C
index 220ac91..f51055d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const-this.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const-this.C
@@ -5,5 +5,6 @@ struct S {
void f();
void g() const {
[=] { f(); } (); // { dg-error "no match|qualifiers" }
+// { dg-warning "implicit capture" "" { target c++2a } .-1 }
}
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-in-class-neg.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-in-class-neg.C
index 92a165d..cff3d37 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-in-class-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-in-class-neg.C
@@ -18,8 +18,9 @@ class C {
[&] () -> void { this->m_i = 3; } ();
assert(m_i == 3);
[=] () -> void { m_i = 4; } (); // copies 'this' or --copies-m_i--?
+// { dg-warning "implicit capture" "" { target c++2a } .-1 }
assert(m_i == 4);
- [=] () -> void { this->m_i = 5; } ();
+ [=] () -> void { this->m_i = 5; } (); // { dg-warning "implicit capture" "" { target c++2a } }
assert(m_i == 5);
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-in-class.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-in-class.C
index 9298110..f2b54e58 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-in-class.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-in-class.C
@@ -18,8 +18,9 @@ class C {
[&] () -> void { this->m_i = 3; } ();
assert(m_i == 3);
[=] () -> void { m_i = 4; } (); // copies 'this' or --copies-m_i--?
+// { dg-warning "implicit capture" "" { target c++2a } .-1 }
assert(m_i == 4);
- [=] () -> void { this->m_i = 5; } ();
+ [=] () -> void { this->m_i = 5; } (); // { dg-warning "implicit capture" "" { target c++2a } }
assert(m_i == 5);
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested.C
index c8ea46a..3848938 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested.C
@@ -7,7 +7,7 @@ struct A {
A(): i(42) { }
int f() {
return [this]{
- return [=]{ return i; }();
+ return [=]{ return i; }(); // { dg-warning "implicit capture" "" { target c++2a } }
}();
}
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-non-local.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-non-local.C
new file mode 100644
index 0000000..005f8f3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-non-local.C
@@ -0,0 +1,10 @@
+// PR c++/86499
+// { dg-do compile { target c++11 } }
+
+auto l1 = [=]{}; // { dg-error "non-local lambda expression cannot have a capture-default" }
+auto l2 = [&]{}; // { dg-error "non-local lambda expression cannot have a capture-default" }
+
+namespace {
+ auto l3 = [=]{}; // { dg-error "non-local lambda expression cannot have a capture-default" }
+ auto l4 = [&]{}; // { dg-error "non-local lambda expression cannot have a capture-default" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi1.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi1.C
index 94dc254..b697289 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi1.C
@@ -1,7 +1,7 @@
// PR c++/56464
// { dg-do run { target c++11 } }
-struct bug { bug*a = [&]{ return [=]{return this;}(); }(); };
+struct bug { bug*a = [&]{ return [=]{return this;}(); }(); }; // { dg-warning "implicit capture" "" { target c++2a } }
int main()
{
bug b;
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi4.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi4.C
index b592f15..127bd26 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi4.C
@@ -10,5 +10,5 @@ struct function
struct testee
{
function l1 = []() { };
- function l2 = [=]() { l1; };
+ function l2 = [=]() { l1; }; // { dg-warning "implicit capture" "" { target c++2a } }
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-shadow3.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-shadow3.C
new file mode 100644
index 0000000..8364321
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-shadow3.C
@@ -0,0 +1,6 @@
+// { dg-do compile { target c++11 } }
+
+int main() {
+ int x = 42;
+ auto lambda = [x](int x) {}; // { dg-error "previously declared as a capture" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this.C
index b32f8d7..7a27cf4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this.C
@@ -6,8 +6,9 @@ struct A
int i;
void f()
{
- [=] { i = 0; };
+ [=] { i = 0; }; // { dg-warning "implicit capture" "" { target c++2a } }
[&] { i = 0; };
[=] { this = 0; }; // { dg-error "lvalue" }
+// { dg-warning "implicit capture" "" { target c++2a } .-1 }
}
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this10.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this10.C
index b4b8e72..e8e9477 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this10.C
@@ -1,4 +1,4 @@
// PR c++/54383
// { dg-do compile { target c++11 } }
-auto foo = [&](int a) { return a > this->b; }; // { dg-error "this" }
+auto foo = [&](int a) { return a > this->b; }; // { dg-error "non-local|this" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this17.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this17.C
index 2386e6b..b7cdf31 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this17.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this17.C
@@ -7,7 +7,7 @@ struct Test {
struct TestPickled : Test {
template<typename... Args> void triggerTest (Args&&... fargs) {
- [=](Args... as) {
+ [=](Args... as) { // { dg-warning "implicit capture" "" { target c++2a } }
Test::triggerTest (as...);
} ();
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this18.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this18.C
index fec2da6..3cfd3c0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this18.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this18.C
@@ -18,7 +18,7 @@ template <class U>
void
A<T>::bar ()
{
- auto f = [this] () { auto g = [=] () { a.foo (); }; g (); };
+ auto f = [this] () { auto g = [=] () { a.foo (); }; g (); }; // { dg-warning "implicit capture" "" { target c++2a } }
f ();
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this2.C
index 5029a4a..56d6b0c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this2.C
@@ -7,7 +7,7 @@ struct S1 {
int i;
void g();
void f() {
- [=]() {
+ [=]() { // { dg-warning "implicit capture" "" { target c++2a } }
i;
g();
S1::g();
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this8.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this8.C
index d7c5d2c..e62cd08 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this8.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this8.C
@@ -6,21 +6,21 @@
struct test {
template<typename T>
std::function<void()> broken(int x) {
- return [=] { +x; print<T>(); };
+ return [=] { +x; print<T>(); }; // { dg-warning "implicit capture" "" { target c++2a } }
}
std::function<void()> works0() {
- return [=] { print<int>(); };
+ return [=] { print<int>(); }; // { dg-warning "implicit capture" "" { target c++2a } }
}
template<typename T>
std::function<void()> works1() {
- return [=] { print<int>(); };
+ return [=] { print<int>(); }; // { dg-warning "implicit capture" "" { target c++2a } }
}
template<typename T>
std::function<void()> works2() {
- return [=] { this->print<T>(); };
+ return [=] { this->print<T>(); }; // { dg-warning "implicit capture" "" { target c++2a } }
}
template<typename T>
diff --git a/gcc/testsuite/g++.dg/cpp0x/move-return2.C b/gcc/testsuite/g++.dg/cpp0x/move-return2.C
new file mode 100644
index 0000000..681e9ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/move-return2.C
@@ -0,0 +1,11 @@
+// PR c++/87150
+// { dg-do compile { target c++11 } }
+
+struct S1 { S1(S1 &&); };
+struct S2 : S1 {};
+
+S1
+f (S2 s)
+{
+ return s; // { dg-error "use of deleted function" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept30.C b/gcc/testsuite/g++.dg/cpp0x/noexcept30.C
index c51e94e..8c7ff2a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept30.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept30.C
@@ -1,5 +1,6 @@
// PR c++/69300
// { dg-do compile { target c++11 } }
+// { dg-options "-fdelete-null-pointer-checks" }
template<typename A>
struct F {
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr85070.C b/gcc/testsuite/g++.dg/cpp0x/pr85070.C
new file mode 100644
index 0000000..c1c5b23
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr85070.C
@@ -0,0 +1,13 @@
+// { dg-do compile { target c++11 } }
+
+struct A;
+
+struct B
+{
+ constexpr A & operator= (const A &); // { dg-warning "used" "" { target c++14_only } }
+};
+
+struct A : B // { dg-error "cannot be overloaded" "" { target c++14_only } }
+{
+ using B::operator=;
+} a { a = a };
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr87155.C b/gcc/testsuite/g++.dg/cpp0x/pr87155.C
new file mode 100644
index 0000000..7c7e8fb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr87155.C
@@ -0,0 +1,14 @@
+// { dg-do compile { target c++11 } }
+// PR c++/87155 confused about which anon namespace
+
+namespace {
+ void a (); // this one
+}
+
+inline namespace n2 {
+ namespace {}
+}
+
+namespace {
+ int a (); // { dg-error "ambiguating" "" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/ref-qual19.C b/gcc/testsuite/g++.dg/cpp0x/ref-qual19.C
new file mode 100644
index 0000000..50f9297
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/ref-qual19.C
@@ -0,0 +1,117 @@
+// PR c++/87109
+// { dg-do run { target c++11 } }
+
+#include <utility>
+
+struct C { int i; };
+struct D { int i; };
+
+struct A {
+ int j;
+ operator C() & { return { 1 }; }
+ operator C() && { return { 2 }; }
+};
+
+struct B : public A {
+ operator D() & { return { 3 }; }
+ operator D() && { return { 4 }; }
+};
+
+C
+f (A a)
+{
+ return a;
+}
+
+C
+f2 (A a)
+{
+ return std::move (a);
+}
+
+C
+f3 ()
+{
+ A a;
+ return a;
+}
+
+C
+f4 ()
+{
+ A a;
+ return std::move (a);
+}
+
+C
+f5 ()
+{
+ return A();
+}
+
+D
+f6 (B b)
+{
+ return b;
+}
+
+D
+f7 (B b)
+{
+ return std::move (b);
+}
+
+D
+f8 ()
+{
+ B b;
+ return b;
+}
+
+D
+f9 ()
+{
+ B b;
+ return std::move (b);
+}
+
+D
+f10 ()
+{
+ return B();
+}
+
+int
+main ()
+{
+ C c1 = f (A());
+ if (c1.i != 2)
+ __builtin_abort ();
+ C c2 = f2 (A());
+ if (c2.i != 2)
+ __builtin_abort ();
+ C c3 = f3 ();
+ if (c3.i != 2)
+ __builtin_abort ();
+ C c4 = f4 ();
+ if (c4.i != 2)
+ __builtin_abort ();
+ C c5 = f5 ();
+ if (c5.i != 2)
+ __builtin_abort ();
+ D c6 = f6 (B());
+ if (c6.i != 4)
+ __builtin_abort ();
+ D c7 = f7 (B());
+ if (c7.i != 4)
+ __builtin_abort ();
+ D c8 = f8 ();
+ if (c8.i != 4)
+ __builtin_abort ();
+ D c9 = f9 ();
+ if (c9.i != 4)
+ __builtin_abort ();
+ D c10 = f10 ();
+ if (c10.i != 4)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/ref-qual20.C b/gcc/testsuite/g++.dg/cpp0x/ref-qual20.C
new file mode 100644
index 0000000..c8bd436
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/ref-qual20.C
@@ -0,0 +1,70 @@
+// PR c++/87109
+// { dg-do run { target c++11 } }
+
+#include <utility>
+
+struct Y {
+ int y;
+ Y(int y_) : y(y_) { }
+};
+struct X : public Y {
+ int x;
+ X(int x_, int y_) : x(x_), Y(y_) { }
+};
+
+struct A {
+ operator X() & { return { 0, 2 }; }
+ operator X() && { return { 0, -1 }; }
+};
+
+Y
+f (A a)
+{
+ return a;
+}
+
+Y
+f2 (A a)
+{
+ return std::move (a);
+}
+
+Y
+f3 ()
+{
+ A a;
+ return a;
+}
+
+Y
+f4 ()
+{
+ A a;
+ return std::move (a);
+}
+
+Y
+f5 ()
+{
+ return A();
+}
+
+int
+main ()
+{
+ Y y1 = f (A());
+ if (y1.y != 2)
+ __builtin_abort ();
+ Y y2 = f2 (A());
+ if (y2.y != -1)
+ __builtin_abort ();
+ Y y3 = f3 ();
+ if (y3.y != 2)
+ __builtin_abort ();
+ Y y4 = f4 ();
+ if (y4.y != -1)
+ __builtin_abort ();
+ Y y5 = f5 ();
+ if (y5.y != -1)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-cast5.C b/gcc/testsuite/g++.dg/cpp0x/rv-cast5.C
index c2473e2..5233078 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-cast5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-cast5.C
@@ -8,5 +8,5 @@ struct hold {
int main()
{
- hold<bool&&>{42}();
+ hold<bool&&>{static_cast<bool>(42)}();
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/scoped_enum2.C b/gcc/testsuite/g++.dg/cpp0x/scoped_enum2.C
index bb8ad75..456b0da 100644
--- a/gcc/testsuite/g++.dg/cpp0x/scoped_enum2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/scoped_enum2.C
@@ -4,8 +4,8 @@ enum class E { e = 10 };
enum E2 { e2 = 10 };
struct C {
- int arr[E::e]; // { dg-error "non-integral type" }
+ int arr[E::e]; // { dg-error "could not convert|non-integral type" }
int arr2[E2::e2]; // OK
- int i: E::e; // { dg-error "non-integral type" }
+ int i: E::e; // { dg-error "could not convert|non-integral type" }
int i2: E2::e2; // OK
};
diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn52.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn52.C
new file mode 100644
index 0000000..e239bc2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn52.C
@@ -0,0 +1,4 @@
+// PR c++/67012
+// { dg-do compile { target c++14 } }
+
+decltype(auto) f() -> int; // { dg-error "function with trailing return type has" }
diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn53.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn53.C
new file mode 100644
index 0000000..720aeeb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn53.C
@@ -0,0 +1,4 @@
+// PR c++/86942
+// { dg-do compile { target c++14 } }
+
+using T = decltype(auto) () -> int; // { dg-error "invalid use of" }
diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn54.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn54.C
new file mode 100644
index 0000000..f3391dd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn54.C
@@ -0,0 +1,3 @@
+// { dg-do compile { target c++14 } }
+
+using T = int () -> decltype(auto); // { dg-error "function with trailing return type not declared with .auto." }
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-82218.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-82218.C
index 06507a9..eb8d1e0 100644
--- a/gcc/testsuite/g++.dg/cpp1y/constexpr-82218.C
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-82218.C
@@ -1,5 +1,6 @@
// PR c++/82218
// { dg-do compile { target c++14 } }
+// { dg-options "-fdelete-null-pointer-checks" }
template<typename _Tp>
struct identity
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-86767.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-86767.C
new file mode 100644
index 0000000..2ad71d5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-86767.C
@@ -0,0 +1,119 @@
+// PR c++/86767
+// { dg-do compile { target c++14 } }
+
+constexpr int
+fn0 () noexcept
+{
+ int r = 0;
+ for (int i = 0; i < 10; ++i)
+ {
+ continue;
+ r++;
+ for (int j = 0; j < 10; ++j )
+ {
+ }
+ }
+ return r;
+}
+static_assert (fn0 () == 0, "");
+
+constexpr int
+fn1 () noexcept
+{
+ int r = 0;
+ for (int i = 0; i < 10; ++i)
+ for (int j = 0; j < 10; ++j)
+ {
+ continue;
+ r++;
+ }
+ return r;
+}
+static_assert (fn1 () == 0, "");
+
+constexpr int
+fn2 () noexcept
+{
+ int r = 0;
+ for (int i = 0; i < 10; ++i)
+ {
+ continue;
+ r++;
+ }
+ return r;
+}
+static_assert (fn2 () == 0, "");
+
+constexpr int
+fn3 () noexcept
+{
+ int r = 0;
+ for (int i = 0; i < 10; ++i)
+ {
+ continue;
+ r++;
+ while (1)
+ {
+ }
+ }
+ return r;
+}
+static_assert (fn3 () == 0, "");
+
+constexpr int
+fn4 () noexcept
+{
+ for (int i = 0; i < 10; ++i)
+ {
+ switch (i)
+ {
+ case 5:
+ return i;
+ default:
+ continue;
+ }
+ while (1)
+ {
+ }
+ }
+ return 0;
+}
+static_assert (fn4 () == 5, "");
+
+constexpr int
+fn5 () noexcept
+{
+ for (int i = 0; i < 10; ++i)
+ {
+ switch (i)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ continue;
+ default:
+ return i;
+ }
+ while (1)
+ {
+ }
+ }
+ return 0;
+}
+static_assert (fn5 () == 5, "");
+
+constexpr int
+fn6 () noexcept
+{
+ int r = 0;
+ for (int i = 0; i < 10; ++i)
+ {
+ continue;
+ for (int j = 0; j < 10; ++j )
+ r++;
+ }
+ return r;
+}
+static_assert (fn6 () == 0, "");
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-array6.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-array6.C
new file mode 100644
index 0000000..1f15bef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-array6.C
@@ -0,0 +1,26 @@
+// PR c++/87075
+// { dg-do compile { target c++14 } }
+
+template <typename T>
+struct vec
+{
+ struct { T y; } n;
+ vec() = default;
+};
+
+template <typename T>
+struct S
+{
+ vec<T> value[2];
+ template<typename U>
+ constexpr S(const U&);
+};
+
+template<typename T>
+template<typename X>
+constexpr S<T>::S(const X&)
+{
+ value[0] = vec<T>();
+}
+
+S<float>m(0);
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-return4.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-return4.C
new file mode 100644
index 0000000..8f29628
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-return4.C
@@ -0,0 +1,10 @@
+// PR c++/86678
+// { dg-do compile { target c++14 } }
+
+constexpr bool always_true() { return true; }
+int f() { return 1; }
+constexpr int g() {
+ if (always_true())
+ return 0;
+ return f();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/func_constexpr2.C b/gcc/testsuite/g++.dg/cpp1y/func_constexpr2.C
new file mode 100644
index 0000000..b1576e6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/func_constexpr2.C
@@ -0,0 +1,21 @@
+// PR c++/87372
+// { dg-do compile { target c++14 } }
+
+constexpr int
+foo (char const *s)
+{
+ int i = 0;
+ while (s[i])
+ ++i;
+ return i;
+}
+
+constexpr int
+bar ()
+{
+ constexpr int l = foo (__PRETTY_FUNCTION__);
+ constexpr int l2 = foo (__FUNCTION__);
+ constexpr int l3 = foo (__func__);
+ return l + l2 + l3;
+}
+static_assert (bar () == 25, "");
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic18.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic18.C
new file mode 100644
index 0000000..1eb9cce
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic18.C
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++14 } }
+
+int main() {
+ int x = 42;
+ auto lambda2 = [x=x](int x) {}; // { dg-error "previously declared as a capture" }
+ auto lambda3 = [x](auto... x) {}; // { dg-error "previously declared as a capture" }
+ auto lambda4 = [](auto... x) {
+ auto lambda5 = [x...](auto... x) {}; // { dg-error "previously declared as a capture" }
+ auto lambda6 = [x...](int x) {}; // { dg-error "previously declared as a capture" }
+ };
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic19.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic19.C
new file mode 100644
index 0000000..e78677d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic19.C
@@ -0,0 +1,4 @@
+// PR c++/86728
+// { dg-do compile { target c++14 } }
+
+auto c = [](auto x ...) { };
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr64382.C b/gcc/testsuite/g++.dg/cpp1y/pr64382.C
index 8f2e931..0342dee 100644
--- a/gcc/testsuite/g++.dg/cpp1y/pr64382.C
+++ b/gcc/testsuite/g++.dg/cpp1y/pr64382.C
@@ -9,7 +9,7 @@ struct my_queue
}
void ice()
{
- auto L = [=](auto &&v) {
+ auto L = [=](auto &&v) { // { dg-warning "implicit capture" "" { target c++2a } }
push(v);
};
trav(L);
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr77739.C b/gcc/testsuite/g++.dg/cpp1y/pr77739.C
index 9618330..8fe76f9 100644
--- a/gcc/testsuite/g++.dg/cpp1y/pr77739.C
+++ b/gcc/testsuite/g++.dg/cpp1y/pr77739.C
@@ -8,7 +8,7 @@ struct A {
struct B {
B();
template <typename... Args> auto g(Args &&... p1) {
- return [=] { f(p1...); };
+ return [=] { f(p1...); }; // { dg-warning "implicit capture" "" { target c++2a } }
}
void f(A, const char *);
};
diff --git a/gcc/testsuite/g++.dg/cpp1z/Wpessimizing-move1.C b/gcc/testsuite/g++.dg/cpp1z/Wpessimizing-move1.C
new file mode 100644
index 0000000..5974188
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/Wpessimizing-move1.C
@@ -0,0 +1,18 @@
+// PR c++/86981
+// { dg-options "-Wpessimizing-move -std=c++17" }
+
+#include <utility>
+#include <optional>
+
+struct T {
+ T() { }
+ T(const T&) { }
+ T(T&&) { }
+};
+
+std::optional<T>
+fn ()
+{
+ T t;
+ return std::move (t);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp46.C b/gcc/testsuite/g++.dg/cpp1z/decomp46.C
new file mode 100644
index 0000000..e159b6a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp46.C
@@ -0,0 +1,25 @@
+// PR c++/86836
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+struct A {
+ int operator*();
+ void operator++();
+ bool operator!=(A);
+};
+template <typename> class map {
+public:
+ A begin();
+ A end();
+};
+
+template <typename T> void mergemap(map<T> orig, map<T> toadd) {
+ for (auto p : toadd)
+ auto [orig] = orig; // { dg-error "use of 'orig' before deduction of 'auto'" }
+} // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+
+int
+main() {
+ map<double> x, y;
+ mergemap(x, y);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp47.C b/gcc/testsuite/g++.dg/cpp1z/decomp47.C
new file mode 100644
index 0000000..f0d202d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp47.C
@@ -0,0 +1,32 @@
+// PR c++/87122
+// { dg-do run { target c++14 } }
+// { dg-options "" }
+
+extern "C" void abort ();
+struct S { int a, b; };
+int c;
+
+template <int N>
+void
+foo ()
+{
+ S x[4] = { { N, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
+ auto f = [](auto & y) {
+ for (auto & [ u, v ] : y) // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ {
+ if ((u & 1) != 1 || v != u + 1 || u < N || u > 7 || (c & (1 << u))
+ || &u != &y[v / 2 - 1].a || &v != &y[v / 2 - 1].b)
+ abort ();
+ c |= 1 << u;
+ }
+ };
+ f (x);
+}
+
+int
+main ()
+{
+ foo<1> ();
+ if (c != 0xaa)
+ abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C b/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C
index fa2934e..1850253 100644
--- a/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C
+++ b/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C
@@ -29,34 +29,34 @@ foo ()
D d6 { G }; // { dg-error "cannot convert 'A' to 'D' in initialization" "" { target c++14_down } }
E e1 { 5 }; // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
E e2 { -1 }; // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '-1' from 'int' to 'unsigned char' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '-1' from 'int' to 'unsigned char'" "" { target c++17 } .-1 }
E e3 { 5.0 }; // { dg-error "cannot convert 'double' to 'E' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char'" "" { target c++17 } .-1 }
E e4 { 5.2 }; // { dg-error "cannot convert 'double' to 'E' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '5.\[0-9]*e.0' from 'double' to 'unsigned char' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '5.\[0-9]*e.0' from 'double' to 'unsigned char'" "" { target c++17 } .-1 }
B b2 = { 7 }; // { dg-error "invalid conversion from 'int' to 'B'" }
C c2 = { C { 8 } }; // { dg-error "cannot convert 'int' to 'C' in initialization" "" { target c++14_down } }
D *d7 = new D { 9 }; // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target c++14_down } }
E *e5 = new E { -4 }; // { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '-4' from 'int' to 'unsigned char' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '-4' from 'int' to 'unsigned char'" "" { target c++17 } .-1 }
bar ({ 10 }); // { dg-error "cannot convert \[^\n\r]* to 'E'" }
bar (E { 9 }); // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
V v1 = { { 11 } }; // { dg-error "braces around scalar initializer for type 'E'" }
V v2 = { E { 12 } }; // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
V v3 = { E { 5.0 } }; // { dg-error "cannot convert 'double' to 'E' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char'" "" { target c++17 } .-1 }
V v4 = { 13 }; // { dg-error "cannot convert 'int' to 'E' in initialization" }
if (B b3 { 5 }) // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
;
if (B b4 { 4.0 }) // { dg-error "cannot convert 'double' to 'B' in initialization" "" { target c++14_down } }
- ; // { dg-error "narrowing conversion of '4.0e.0' from 'double' to 'short int' inside" "" { target c++17 } .-1 }
+ ; // { dg-error "narrowing conversion of '4.0e.0' from 'double' to 'short int'" "" { target c++17 } .-1 }
C c3 { 8L }; // { dg-error "cannot convert 'long int' to 'C' in initialization" "" { target c++14_down } }
B b4 {short (c + 5)}; // { dg-error "invalid conversion from 'short int' to 'B'" "" { target c++14_down } }
B b5 {c + 5}; // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
- // { dg-error "narrowing conversion of \[^\n\r]* from 'int' to 'short int' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of \[^\n\r]* from 'int' to 'short int'" "" { target c++17 } .-1 }
C c4 { ll }; // { dg-error "cannot convert 'long long int' to 'C' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of 'll' from 'long long int' to 'int' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of 'll' from 'long long int' to 'int'" "" { target c++17 } .-1 }
C c5 {short (c + 5)}; // { dg-error "cannot convert 'short int' to 'C' in initialization" "" { target c++14_down } }
C c6 {c + 5}; // { dg-error "cannot convert 'int' to 'C' in initialization" "" { target c++14_down } }
}
@@ -65,7 +65,7 @@ struct U
{
U () : e { 5 } {} // { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
U (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char'" "" { target c++17 } .-1 }
U (float) : e({ 6 }) {}// { dg-error "list-initializer for non-class type must not be parenthesized" }
// { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target *-*-* } .-1 }
E e;
@@ -76,7 +76,7 @@ struct W
A a { 5 }; // { dg-error "invalid conversion from 'int' to 'A'" }
B b { 6 }; // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
C c { 3.0f }; // { dg-error "cannot convert \[^\n\r]* to 'C' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int'" "" { target c++17 } .-1 }
D d = { 7 }; // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" }
};
@@ -96,33 +96,33 @@ foo2 ()
D d6 { G }; // { dg-error "cannot convert 'A' to 'D' in initialization" "" { target c++14_down } }
E e1 { 5 }; // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
E e2 { -1 }; // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '-1' from 'int' to 'unsigned char' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '-1' from 'int' to 'unsigned char'" "" { target c++17 } .-1 }
E e3 { 5.0 }; // { dg-error "cannot convert 'double' to 'E' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char'" "" { target c++17 } .-1 }
E e4 { 5.2 }; // { dg-error "cannot convert 'double' to 'E' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '5.\[0-9]*e.0' from 'double' to 'unsigned char' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '5.\[0-9]*e.0' from 'double' to 'unsigned char'" "" { target c++17 } .-1 }
B b2 = { 7 }; // { dg-error "invalid conversion from 'int' to 'B'" }
C c2 = { C { 8 } }; // { dg-error "cannot convert 'int' to 'C' in initialization" "" { target c++14_down } }
D *d7 = new D { 9 }; // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target c++14_down } }
E *e5 = new E { -4 }; // { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '-4' from 'int' to 'unsigned char' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '-4' from 'int' to 'unsigned char'" "" { target c++17 } .-1 }
bar ({ 10 }); // { dg-error "cannot convert \[^\n\r]* to 'E'" }
bar (E { 9 }); // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
V v1 = { { 11 } }; // { dg-error "braces around scalar initializer for type 'E'" }
V v2 = { E { 12 } }; // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
V v3 = { E { 5.0 } }; // { dg-error "cannot convert 'double' to 'E' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char'" "" { target c++17 } .-1 }
V v4 = { 13 }; // { dg-error "cannot convert 'int' to 'E' in initialization" }
if (B b3 { 5 }) // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
;
if (B b4 { 4.0 }) // { dg-error "cannot convert 'double' to 'B' in initialization" "" { target c++14_down } }
- ; // { dg-error "narrowing conversion of '4.0e.0' from 'double' to 'short int' inside" "" { target c++17 } .-1 }
+ ; // { dg-error "narrowing conversion of '4.0e.0' from 'double' to 'short int'" "" { target c++17 } .-1 }
C c3 { 8L }; // { dg-error "cannot convert 'long int' to 'C' in initialization" "" { target c++14_down } }
B b4 {short (c + 5)}; // { dg-error "invalid conversion from 'short int' to 'B'" "" { target c++14_down } }
B b5 {c + 5}; // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
- // { dg-error "narrowing conversion of \[^\n\r]* from 'int' to 'short int' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of \[^\n\r]* from 'int' to 'short int'" "" { target c++17 } .-1 }
C c4 { ll }; // { dg-error "cannot convert 'long long int' to 'C' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of 'll' from 'long long int' to 'int' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of 'll' from 'long long int' to 'int'" "" { target c++17 } .-1 }
C c5 {short (c + 5)}; // { dg-error "cannot convert 'short int' to 'C' in initialization" "" { target c++14_down } }
C c6 {c + 5}; // { dg-error "cannot convert 'int' to 'C' in initialization" "" { target c++14_down } }
}
@@ -132,7 +132,7 @@ struct U2
{
U2 () : e { 5 } {} // { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
U2 (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char'" "" { target c++17 } .-1 }
U2 (float) : e({ 6 }) {}
E e;
};
@@ -143,7 +143,7 @@ struct W2
A a { 5 }; // { dg-error "invalid conversion from 'int' to 'A'" "" { target *-*-* } }
B b { 6 }; // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
C c { 3.0f }; // { dg-error "cannot convert \[^\n\r]* to 'C' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int'" "" { target c++17 } .-1 }
D d = { 7 }; // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target *-*-* } }
};
@@ -164,33 +164,33 @@ foo3 ()
K d6 { G }; // { dg-error "cannot convert 'A' to 'D' in initialization" "" { target c++14_down } }
L e1 { 5 }; // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
L e2 { -1 }; // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '-1' from 'int' to 'unsigned char' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '-1' from 'int' to 'unsigned char'" "" { target c++17 } .-1 }
L e3 { 5.0 }; // { dg-error "cannot convert 'double' to 'E' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char'" "" { target c++17 } .-1 }
L e4 { 5.2 }; // { dg-error "cannot convert 'double' to 'E' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '5.\[0-9]*e.0' from 'double' to 'unsigned char' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '5.\[0-9]*e.0' from 'double' to 'unsigned char'" "" { target c++17 } .-1 }
I b2 = { 7 }; // { dg-error "invalid conversion from 'int' to 'B'" }
J c2 = { J { 8 } }; // { dg-error "cannot convert 'int' to 'C' in initialization" "" { target c++14_down } }
K *d7 = new K { 9 }; // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target c++14_down } }
L *e5 = new L { -4 }; // { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '-4' from 'int' to 'unsigned char' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '-4' from 'int' to 'unsigned char'" "" { target c++17 } .-1 }
bar3 ({ 10 }); // { dg-error "cannot convert \[^\n\r]* to 'E'" }
bar3 (E { 9 }); // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
M v1 = { { 11 } }; // { dg-error "braces around scalar initializer for type 'E'" }
M v2 = { L { 12 } }; // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
M v3 = { L { 5.0 } }; // { dg-error "cannot convert 'double' to 'E' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char'" "" { target c++17 } .-1 }
M v4 = { 13 }; // { dg-error "cannot convert 'int' to 'E' in initialization" }
if (I b3 { 5 }) // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
;
if (I b4 { 4.0 }) // { dg-error "cannot convert 'double' to 'B' in initialization" "" { target c++14_down } }
- ; // { dg-error "narrowing conversion of '4.0e.0' from 'double' to 'short int' inside" "" { target c++17 } .-1 }
+ ; // { dg-error "narrowing conversion of '4.0e.0' from 'double' to 'short int'" "" { target c++17 } .-1 }
J c3 { 8L }; // { dg-error "cannot convert 'long int' to 'C' in initialization" "" { target c++14_down } }
I b4 {short (c + 5)}; // { dg-error "invalid conversion from 'short int' to 'B'" "" { target c++14_down } }
I b5 {c + 5}; // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
- // { dg-error "narrowing conversion of \[^\n\r]* from 'int' to 'short int' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of \[^\n\r]* from 'int' to 'short int'" "" { target c++17 } .-1 }
J c4 { ll }; // { dg-error "cannot convert 'long long int' to 'C' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of 'll' from 'long long int' to 'int' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of 'll' from 'long long int' to 'int'" "" { target c++17 } .-1 }
J c5 {short (c + 5)}; // { dg-error "cannot convert 'short int' to 'C' in initialization" "" { target c++14_down } }
J c6 {c + 5}; // { dg-error "cannot convert 'int' to 'C' in initialization" "" { target c++14_down } }
}
@@ -200,7 +200,7 @@ struct U3
{
U3 () : e { 5 } {} // { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
U3 (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char'" "" { target c++17 } .-1 }
U3 (float) : e({ 6 }) {}
L e;
};
@@ -211,7 +211,7 @@ struct W3
H a { 5 }; // { dg-error "invalid conversion from 'int' to 'A'" "" { target *-*-* } }
I b { 6 }; // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
J c { 3.0f }; // { dg-error "cannot convert \[^\n\r]* to 'C' in initialization" "" { target c++14_down } }
- // { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int' inside" "" { target c++17 } .-1 }
+ // { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int'" "" { target c++17 } .-1 }
K d = { 7 }; // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target *-*-* } }
};
diff --git a/gcc/testsuite/g++.dg/cpp1z/lambda-this1.C b/gcc/testsuite/g++.dg/cpp1z/lambda-this1.C
index 2c49dd9..b13ff8b 100644
--- a/gcc/testsuite/g++.dg/cpp1z/lambda-this1.C
+++ b/gcc/testsuite/g++.dg/cpp1z/lambda-this1.C
@@ -15,7 +15,7 @@ struct A {
auto g = [*this] { a++; }; // { dg-error "in read-only object" }
// { dg-error "'*this' capture only available with" "" { target c++14_down } .-1 }
auto h = [*this] () mutable { a++; };// { dg-error "'*this' capture only available with" "" { target c++14_down } }
- auto i = [=] { return a; };
+ auto i = [=] { return a; }; // { dg-warning "implicit capture" "" { target c++2a } }
auto j = [&] { return a; };
// P0409R2 - C++2A lambda capture [=, this]
auto k = [=, this] { return a; };// { dg-error "explicit by-copy capture of 'this' redundant with by-copy capture default" "" { target c++17_down } }
@@ -62,7 +62,7 @@ struct C {
auto d = [this] { return c; };
auto e = [*this] { return c; }; // { dg-error "use of deleted function" }
// { dg-error "'*this' capture only available with" "" { target c++14_down } .-1 }
- auto f = [=] { return c; };
+ auto f = [=] { return c; }; // { dg-warning "implicit capture" "" { target c++2a } }
auto g = [&] { return c; };
auto h = [this] { bar (); };
auto i = [*this] { bar (); }; // { dg-error "use of deleted function" }
@@ -77,7 +77,7 @@ struct D {
auto e = [this] { return d; };
auto f = [*this] { return d; }; // { dg-error "use of deleted function" }
// { dg-error "'*this' capture only available with" "" { target c++14_down } .-1 }
- auto g = [=] { return d; };
+ auto g = [=] { return d; }; // { dg-warning "implicit capture" "" { target c++2a } }
auto h = [&] { return d; };
auto i = [this] { bar (); };
auto j = [*this] { bar (); }; // { dg-error "use of deleted function" }
diff --git a/gcc/testsuite/g++.dg/cpp1z/lambda-this2.C b/gcc/testsuite/g++.dg/cpp1z/lambda-this2.C
index 5a0066d..f3ef8e3 100644
--- a/gcc/testsuite/g++.dg/cpp1z/lambda-this2.C
+++ b/gcc/testsuite/g++.dg/cpp1z/lambda-this2.C
@@ -12,7 +12,7 @@ struct A {
if (z != 0) abort ();
auto b = [this] { return &a; };
auto c = [*this] { return &a; }; // { dg-warning "'*this' capture only available with" "" { target c++14_down } }
- auto d = [=] { return &a; };
+ auto d = [=] { return &a; }; // { dg-warning "implicit capture" "" { target c++2a } }
auto e = [&] { return &a; };
if (b () != &a) abort ();
if (*b () != 4) abort ();
@@ -24,7 +24,7 @@ struct A {
if (e () != &a) abort ();
auto g = [this] { return a + z; };
auto h = [*this] { return a + z; }; // { dg-warning "'*this' capture only available with" "" { target c++14_down } }
- auto i = [=] { return a + z; };
+ auto i = [=] { return a + z; }; // { dg-warning "implicit capture" "" { target c++2a } }
auto j = [&] { return a + z; };
if (g () != 4 || h () != 5 || i () != 4 || j () != 4) abort ();
}
@@ -39,7 +39,7 @@ struct B {
if (z != 0) abort ();
auto b = [this] { return &a; };
auto c = [*this] { return &a; }; // { dg-warning "'*this' capture only available with" "" { target c++14_down } }
- auto d = [=] { return &a; };
+ auto d = [=] { return &a; }; // { dg-warning "implicit capture" "" { target c++2a } }
auto e = [&] { return &a; };
if (b () != &a) abort ();
if (*b () != 9) abort ();
@@ -51,7 +51,7 @@ struct B {
if (e () != &a) abort ();
auto g = [this] { return a + z; };
auto h = [*this] { return a + z; }; // { dg-warning "'*this' capture only available with" "" { target c++14_down } }
- auto i = [=] { return a + z; };
+ auto i = [=] { return a + z; }; // { dg-warning "implicit capture" "" { target c++2a } }
auto j = [&] { return a + z; };
if (g () != 9 || h () != 10 || i () != 9 || j () != 9) abort ();
}
diff --git a/gcc/testsuite/g++.dg/cpp2a/aggr1.C b/gcc/testsuite/g++.dg/cpp2a/aggr1.C
new file mode 100644
index 0000000..73a257c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/aggr1.C
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++11 } }
+struct A {
+ A () = delete; // { dg-message "declared here" "" { target c++2a } }
+};
+struct B {
+ B () = default;
+ int b = 0;
+};
+struct C {
+ C (C&&) = default; // { dg-message "candidate" "" { target c++2a } }
+ int c, d;
+};
+A a {}; // { dg-error "use of deleted function" "" { target c++2a } }
+B b = {1}; // { dg-error "could not convert" "" { target { c++11_only || c++2a } } }
+C *c = new C {2, 3}; // { dg-error "no matching function for call to" "" { target c++2a } }
diff --git a/gcc/testsuite/g++.dg/cpp2a/aggr2.C b/gcc/testsuite/g++.dg/cpp2a/aggr2.C
new file mode 100644
index 0000000..e774be7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/aggr2.C
@@ -0,0 +1,25 @@
+// { dg-do run { target c++11 } }
+
+struct A;
+struct B { operator A (); };
+struct A { A (const A &) = default; A () = default; B a; };
+A a {B {}};
+bool seen;
+
+B::operator A ()
+{
+ seen = true;
+ return A ();
+}
+
+int
+main ()
+{
+#if __cplusplus > 201703L
+ if (!seen)
+ __builtin_abort ();
+#else
+ if (seen)
+ __builtin_abort ();
+#endif
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual1.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual1.C
new file mode 100644
index 0000000..fcf8cac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual1.C
@@ -0,0 +1,8 @@
+// P1064R0
+// { dg-do compile { target c++11 } }
+// { dg-options "-pedantic-errors" }
+
+struct X
+{
+ constexpr virtual int f() { return 0; } // { dg-error "member .f. can be declared both .virtual. and .constexpr. only" "" { target c++17_down } }
+};
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual2.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual2.C
new file mode 100644
index 0000000..9d82c5c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual2.C
@@ -0,0 +1,49 @@
+// P1064R0
+// { dg-do compile }
+// { dg-options "-std=c++2a" }
+
+struct X1
+{
+ virtual int f() const = 0;
+};
+
+struct X2: public X1
+{
+ constexpr virtual int f() const { return 2; }
+};
+
+struct X3: public X2
+{
+ virtual int f() const { return 3; }
+};
+
+struct X4: public X3
+{
+ constexpr virtual int f() const { return 4; }
+};
+
+constexpr int (X1::*pf)() const = &X1::f;
+
+constexpr X2 x2;
+static_assert(x2.f() == 2);
+static_assert((x2.*pf)() == 2);
+
+constexpr X1 const& r2 = x2;
+static_assert(r2.f() == 2);
+static_assert((r2.*pf)() == 2);
+
+constexpr X1 const* p2 = &x2;
+static_assert(p2->f() == 2);
+static_assert((p2->*pf)() == 2);
+
+constexpr X4 x4;
+static_assert(x4.f() == 4);
+static_assert((x4.*pf)() == 4);
+
+constexpr X1 const& r4 = x4;
+static_assert(r4.f() == 4);
+static_assert((r4.*pf)() == 4);
+
+constexpr X1 const* p4 = &x4;
+static_assert(p4->f() == 4);
+static_assert((p4->*pf)() == 4);
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual3.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual3.C
new file mode 100644
index 0000000..d71422f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual3.C
@@ -0,0 +1,52 @@
+// P1064R0
+// { dg-do compile }
+// { dg-options "-std=c++2a" }
+
+struct X1
+{
+ virtual int f() const = 0;
+};
+
+struct X2: public X1
+{
+ int i2 = 42;
+ constexpr virtual int f() const { return 2; }
+};
+
+struct X3: public X2
+{
+ int i3 = 42;
+ virtual int f() const { return 3; }
+};
+
+struct X4: public X3
+{
+ int i4 = 42;
+ constexpr virtual int f() const { return 4; }
+};
+
+constexpr int (X1::*pf)() const = &X1::f;
+
+constexpr X2 x2;
+static_assert(x2.f() == 2);
+static_assert((x2.*pf)() == 2);
+
+constexpr X1 const& r2 = x2;
+static_assert(r2.f() == 2);
+static_assert((r2.*pf)() == 2);
+
+constexpr X1 const* p2 = &x2;
+static_assert(p2->f() == 2);
+static_assert((p2->*pf)() == 2);
+
+constexpr X4 x4;
+static_assert(x4.f() == 4);
+static_assert((x4.*pf)() == 4);
+
+constexpr X1 const& r4 = x4;
+static_assert(r4.f() == 4);
+static_assert((r4.*pf)() == 4);
+
+constexpr X1 const* p4 = &x4;
+static_assert(p4->f() == 4);
+static_assert((p4->*pf)() == 4);
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual4.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual4.C
new file mode 100644
index 0000000..2038beb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual4.C
@@ -0,0 +1,57 @@
+// P1064R0
+// { dg-do compile }
+// { dg-options "-std=c++2a" }
+
+struct X1
+{
+ virtual int f1() const = 0;
+ virtual int f2() const = 0;
+ virtual int f3() const = 0;
+};
+
+struct X2: public X1
+{
+ constexpr virtual int f1() const { return 21; }
+ constexpr virtual int f2() const { return 22; }
+ constexpr virtual int f3() const { return 23; }
+};
+
+struct X3: public X2
+{
+ virtual int f1() const { return 31; }
+ virtual int f2() const { return 32; }
+ virtual int f3() const { return 33; }
+};
+
+struct X4: public X3
+{
+ constexpr virtual int f1() const { return 41; }
+ constexpr virtual int f2() const { return 42; }
+ constexpr virtual int f3() const { return 43; }
+};
+
+constexpr int (X1::*pf)() const = &X1::f2;
+
+constexpr X2 x2;
+static_assert(x2.f2() == 22);
+static_assert((x2.*pf)() == 22);
+
+constexpr X1 const& r2 = x2;
+static_assert(r2.f2() == 22);
+static_assert((r2.*pf)() == 22);
+
+constexpr X1 const* p2 = &x2;
+static_assert(p2->f2() == 22);
+static_assert((p2->*pf)() == 22);
+
+constexpr X4 x4;
+static_assert(x4.f2() == 42);
+static_assert((x4.*pf)() == 42);
+
+constexpr X1 const& r4 = x4;
+static_assert(r4.f2() == 42);
+static_assert((r4.*pf)() == 42);
+
+constexpr X1 const* p4 = &x4;
+static_assert(p4->f2() == 42);
+static_assert((p4->*pf)() == 42);
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual5.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual5.C
new file mode 100644
index 0000000..6d27990
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual5.C
@@ -0,0 +1,60 @@
+// P1064R0
+// { dg-do compile }
+// { dg-options "-std=c++2a" }
+
+struct X1
+{
+ virtual int f1() const = 0;
+ virtual int f2() const = 0;
+ virtual int f3() const = 0;
+};
+
+struct X2: public X1
+{
+ int i2 = 42;
+ constexpr virtual int f1() const { return 21; }
+ constexpr virtual int f2() const { return 22; }
+ constexpr virtual int f3() const { return 23; }
+};
+
+struct X3: public X2
+{
+ int i3 = 42;
+ virtual int f1() const { return 31; }
+ virtual int f2() const { return 32; }
+ virtual int f3() const { return 33; }
+};
+
+struct X4: public X3
+{
+ int i4 = 42;
+ constexpr virtual int f1() const { return 41; }
+ constexpr virtual int f2() const { return 42; }
+ constexpr virtual int f3() const { return 43; }
+};
+
+constexpr int (X1::*pf)() const = &X1::f2;
+
+constexpr X2 x2;
+static_assert(x2.f2() == 22);
+static_assert((x2.*pf)() == 22);
+
+constexpr X1 const& r2 = x2;
+static_assert(r2.f2() == 22);
+static_assert((r2.*pf)() == 22);
+
+constexpr X1 const* p2 = &x2;
+static_assert(p2->f2() == 22);
+static_assert((p2->*pf)() == 22);
+
+constexpr X4 x4;
+static_assert(x4.f2() == 42);
+static_assert((x4.*pf)() == 42);
+
+constexpr X1 const& r4 = x4;
+static_assert(r4.f2() == 42);
+static_assert((r4.*pf)() == 42);
+
+constexpr X1 const* p4 = &x4;
+static_assert(p4->f2() == 42);
+static_assert((p4->*pf)() == 42);
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual6.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual6.C
new file mode 100644
index 0000000..ece5e70
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual6.C
@@ -0,0 +1,25 @@
+// P1064R0
+// { dg-do compile }
+// { dg-options "-std=c++2a" }
+
+struct X1
+{
+ constexpr virtual X1 const *f() const { return this; }
+};
+
+struct Y
+{
+ int m = 0;
+};
+
+struct X2: public Y, public X1
+{
+ constexpr virtual X2 const *f() const { return this; }
+};
+
+constexpr X1 x1;
+static_assert(x1.f() == &x1);
+
+constexpr X2 x2;
+constexpr X1 const& r2 = x2;
+static_assert(r2.f() == &r2);
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual7.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual7.C
new file mode 100644
index 0000000..b0f4996
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual7.C
@@ -0,0 +1,87 @@
+// P1064R0
+// { dg-do compile }
+// { dg-options "-std=c++2a" }
+
+struct X1
+{
+ virtual int f() const = 0;
+};
+
+struct X2: public X1
+{
+ constexpr virtual int f() const { return 2; }
+};
+
+struct X3: public X2
+{
+ virtual int f() const { return 3; }
+};
+
+struct X4: public X3
+{
+ constexpr virtual int f() const { return 4; }
+};
+
+constexpr int (X1::*pf)() const = &X1::f;
+
+constexpr X2 x2;
+
+struct S
+{
+ int i, j;
+ constexpr S() : i(x2.f()), j((x2.*pf)()) { }
+};
+
+static_assert(S().i == 2);
+static_assert(S().j == 2);
+
+constexpr X1 const& r2 = x2;
+
+struct S2
+{
+ int i, j;
+ constexpr S2() : i(r2.f()), j((r2.*pf)()) { }
+};
+
+static_assert(S2().i == 2);
+static_assert(S2().j == 2);
+
+constexpr X1 const* p2 = &x2;
+struct S3
+{
+ int i, j;
+ constexpr S3() : i(p2->f()), j((p2->*pf)()) { }
+};
+
+static_assert(S3().i == 2);
+static_assert(S3().j == 2);
+
+constexpr X4 x4;
+struct S4
+{
+ int i, j;
+ constexpr S4() : i(x4.f()), j((x4.*pf)()) { }
+};
+
+static_assert(S4().i == 4);
+static_assert(S4().j == 4);
+
+constexpr X1 const& r4 = x4;
+struct S5
+{
+ int i, j;
+ constexpr S5() : i(r4.f()), j((r4.*pf)()) { }
+};
+
+static_assert(S5().i == 4);
+static_assert(S5().j == 4);
+
+constexpr X1 const* p4 = &x4;
+struct S6
+{
+ int i, j;
+ constexpr S6() : i(p4->f()), j((p4->*pf)()) { }
+};
+
+static_assert(S6().i == 4);
+static_assert(S6().j == 4);
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual8.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual8.C
new file mode 100644
index 0000000..4a7cc97
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual8.C
@@ -0,0 +1,50 @@
+// P1064R0
+// { dg-do compile }
+// { dg-options "-std=c++2a" }
+
+template<typename T>
+struct X1
+{
+ virtual T f() const = 0;
+};
+
+struct X2: public X1<int>
+{
+ constexpr virtual int f() const { return 2; }
+};
+
+struct X3: public X2
+{
+ virtual int f() const { return 3; }
+};
+
+struct X4: public X3
+{
+ constexpr virtual int f() const { return 4; }
+};
+
+constexpr int (X1<int>::*pf)() const = &X1<int>::f;
+
+constexpr X2 x2;
+static_assert(x2.f() == 2);
+static_assert((x2.*pf)() == 2);
+
+constexpr X1<int> const& r2 = x2;
+static_assert(r2.f() == 2);
+static_assert((r2.*pf)() == 2);
+
+constexpr X1<int> const* p2 = &x2;
+static_assert(p2->f() == 2);
+static_assert((p2->*pf)() == 2);
+
+constexpr X4 x4;
+static_assert(x4.f() == 4);
+static_assert((x4.*pf)() == 4);
+
+constexpr X1<int> const& r4 = x4;
+static_assert(r4.f() == 4);
+static_assert((r4.*pf)() == 4);
+
+constexpr X1<int> const* p4 = &x4;
+static_assert(p4->f() == 4);
+static_assert((p4->*pf)() == 4);
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual9.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual9.C
new file mode 100644
index 0000000..3a12adc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual9.C
@@ -0,0 +1,83 @@
+// P1064R0
+// { dg-do compile }
+// { dg-options "-std=c++2a" }
+
+struct X1
+{
+ virtual int f() const = 0;
+ virtual int f(int) const = 0;
+ virtual int f(int, int) const = 0;
+};
+
+struct X2: public X1
+{
+ constexpr virtual int f() const { return 2; }
+ constexpr virtual int f(int) const { return 12; }
+ constexpr virtual int f(int, int) const { return 22; }
+};
+
+struct X3: public X2
+{
+ virtual int f() const { return 3; }
+ virtual int f(int) const { return 13; }
+ virtual int f(int, int) const { return 23; }
+};
+
+struct X4: public X3
+{
+ constexpr virtual int f() const { return 4; }
+ constexpr virtual int f(int) const { return 14; }
+ constexpr virtual int f(int, int) const { return 24; }
+};
+
+constexpr int (X1::*pf)() const = &X1::f;
+constexpr int (X1::*pf1)(int) const = &X1::f;
+constexpr int (X1::*pf2)(int, int) const = &X1::f;
+
+constexpr X2 x2;
+static_assert(x2.f() == 2);
+static_assert((x2.*pf)() == 2);
+static_assert(x2.f(1) == 12);
+static_assert((x2.*pf1)(1) == 12);
+static_assert(x2.f(1, 2) == 22);
+static_assert((x2.*pf2)(1, 2) == 22);
+
+constexpr X1 const& r2 = x2;
+static_assert(r2.f() == 2);
+static_assert((r2.*pf)() == 2);
+static_assert(r2.f(1) == 12);
+static_assert((r2.*pf1)(1) == 12);
+static_assert(r2.f(1, 2) == 22);
+static_assert((r2.*pf2)(1, 2) == 22);
+
+constexpr X1 const* p2 = &x2;
+static_assert(p2->f() == 2);
+static_assert((p2->*pf)() == 2);
+static_assert(p2->f(1) == 12);
+static_assert((p2->*pf1)(1) == 12);
+static_assert(p2->f(1, 2) == 22);
+static_assert((p2->*pf2)(1, 2) == 22);
+
+constexpr X4 x4;
+static_assert(x4.f() == 4);
+static_assert((x4.*pf)() == 4);
+static_assert(x4.f(1) == 14);
+static_assert((x4.*pf1)(1) == 14);
+static_assert(x4.f(1, 2) == 24);
+static_assert((x4.*pf2)(1, 2) == 24);
+
+constexpr X1 const& r4 = x4;
+static_assert(r4.f() == 4);
+static_assert((r4.*pf)() == 4);
+static_assert(r4.f(1) == 14);
+static_assert((r4.*pf1)(1) == 14);
+static_assert(r4.f(1, 2) == 24);
+static_assert((r4.*pf2)(1, 2) == 24);
+
+constexpr X1 const* p4 = &x4;
+static_assert(p4->f() == 4);
+static_assert((p4->*pf)() == 4);
+static_assert(p4->f(1) == 14);
+static_assert((p4->*pf1)(1) == 14);
+static_assert(p4->f(1, 2) == 24);
+static_assert((p4->*pf2)(1, 2) == 24);
diff --git a/gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated1.C b/gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated1.C
new file mode 100644
index 0000000..3b98884
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated1.C
@@ -0,0 +1,66 @@
+// P0595R1
+// { dg-do compile { target c++14 } }
+
+template<int N> struct X { int v = N; };
+X<__builtin_is_constant_evaluated ()> x; // type X<true>
+int y = 4;
+int a = __builtin_is_constant_evaluated () ? y : 1; // initializes a to 1
+int b = __builtin_is_constant_evaluated () ? 2 : y; // initializes b to 2
+int c = y + (__builtin_is_constant_evaluated () ? 2 : y); // initializes c to 2*y
+int d = __builtin_is_constant_evaluated (); // initializes d to 1
+int e = d + __builtin_is_constant_evaluated (); // initializes e to 0
+
+struct false_type { static constexpr bool value = false; };
+struct true_type { static constexpr bool value = true; };
+template<class T, class U>
+struct is_same : false_type {};
+template<class T>
+struct is_same<T, T> : true_type {};
+
+constexpr int
+foo (int x)
+{
+ const int n = __builtin_is_constant_evaluated () ? 13 : 17; // n == 13
+ int m = __builtin_is_constant_evaluated () ? 13 : 17; // m might be 13 or 17 (see below)
+ char arr[n] = {}; // char[13]
+ return m + sizeof (arr) + x;
+}
+
+constexpr int
+bar ()
+{
+ const int n = __builtin_is_constant_evaluated() ? 13 : 17;
+ X<n> x1;
+ X<__builtin_is_constant_evaluated() ? 13 : 17> x2;
+ static_assert (is_same<decltype (x1), decltype (x2)>::value, "x1/x2's type");
+ return x1.v + x2.v;
+}
+
+int p = foo (0); // m == 13; initialized to 26
+int q = p + foo (0); // m == 17 for this call; initialized to 56
+static_assert (bar () == 26, "bar");
+
+struct S { int a, b; };
+
+S s = { __builtin_is_constant_evaluated () ? 2 : 3, y };
+S t = { __builtin_is_constant_evaluated () ? 2 : 3, 4 };
+
+static_assert (is_same<decltype (x), X<true> >::value, "x's type");
+
+int
+main ()
+{
+ if (a != 1 || b != 2 || c != 8 || d != 1 || e != 0 || p != 26 || q != 56)
+ __builtin_abort ();
+ if (s.a != 3 || s.b != 4 || t.a != 2 || t.b != 4)
+ __builtin_abort ();
+ if (foo (y) != 34)
+ __builtin_abort ();
+#if __cplusplus >= 201703L
+ if constexpr (foo (0) != 26)
+ __builtin_abort ();
+#endif
+ constexpr int w = foo (0);
+ if (w != 26)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-this1.C b/gcc/testsuite/g++.dg/cpp2a/lambda-this1.C
new file mode 100644
index 0000000..a31b968
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-this1.C
@@ -0,0 +1,51 @@
+// P0806R2
+// { dg-do compile }
+// { dg-options "-std=c++2a" }
+
+struct X {
+ int x;
+ void foo (int n) {
+ auto a1 = [=] { x = n; }; // { dg-warning "implicit capture" }
+ auto a2 = [=, this] { x = n; };
+ auto a3 = [=, *this]() mutable { x = n; };
+ auto a4 = [&] { x = n; };
+ auto a5 = [&, this] { x = n; };
+ auto a6 = [&, *this]() mutable { x = n; };
+
+ auto a7 = [=] { // { dg-warning "implicit capture" }
+ auto a = [=] { // { dg-warning "implicit capture" }
+ auto a2 = [=] { x = n; }; // { dg-warning "implicit capture" }
+ };
+ };
+
+ auto a8 = [=, this] {
+ auto a = [=, this] {
+ auto a2 = [=, this] { x = n; };
+ };
+ };
+
+ auto a9 = [=, *this]() mutable {
+ auto a = [=, *this]() mutable {
+ auto a2 = [=, *this]() mutable { x = n; };
+ };
+ };
+
+ auto a10 = [&] {
+ auto a = [&] {
+ auto a2 = [&] { x = n; };
+ };
+ };
+
+ auto a11 = [&, this] {
+ auto a = [&, this] {
+ auto a2 = [&, this] { x = n; };
+ };
+ };
+
+ auto a12 = [&, *this]() mutable {
+ auto a = [&, *this]() mutable {
+ auto a2 = [&, *this]() mutable { x = n; };
+ };
+ };
+ }
+};
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-this2.C b/gcc/testsuite/g++.dg/cpp2a/lambda-this2.C
new file mode 100644
index 0000000..307fb4c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-this2.C
@@ -0,0 +1,51 @@
+// P0806R2
+// { dg-do compile }
+// { dg-options "-std=c++2a -Wno-deprecated" }
+
+struct X {
+ int x;
+ void foo (int n) {
+ auto a1 = [=] { x = n; }; // { dg-bogus "implicit capture" }
+ auto a2 = [=, this] { x = n; };
+ auto a3 = [=, *this]() mutable { x = n; };
+ auto a4 = [&] { x = n; };
+ auto a5 = [&, this] { x = n; };
+ auto a6 = [&, *this]() mutable { x = n; };
+
+ auto a7 = [=] { // { dg-bogus "implicit capture" }
+ auto a = [=] { // { dg-bogus "implicit capture" }
+ auto a2 = [=] { x = n; }; // { dg-bogus "implicit capture" }
+ };
+ };
+
+ auto a8 = [=, this] {
+ auto a = [=, this] {
+ auto a2 = [=, this] { x = n; };
+ };
+ };
+
+ auto a9 = [=, *this]() mutable {
+ auto a = [=, *this]() mutable {
+ auto a2 = [=, *this]() mutable { x = n; };
+ };
+ };
+
+ auto a10 = [&] {
+ auto a = [&] {
+ auto a2 = [&] { x = n; };
+ };
+ };
+
+ auto a11 = [&, this] {
+ auto a = [&, this] {
+ auto a2 = [&, this] { x = n; };
+ };
+ };
+
+ auto a12 = [&, *this]() mutable {
+ auto a = [&, *this]() mutable {
+ auto a2 = [&, *this]() mutable { x = n; };
+ };
+ };
+ }
+};
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-this3.C b/gcc/testsuite/g++.dg/cpp2a/lambda-this3.C
new file mode 100644
index 0000000..5e5c8b3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-this3.C
@@ -0,0 +1,55 @@
+// P0806R2
+// { dg-do compile }
+// { dg-options "-std=c++17" }
+
+struct X {
+ int x;
+ void foo (int n) {
+ auto a1 = [=] { x = n; }; // { dg-bogus "implicit capture" }
+ auto a2 = [=, this] { x = n; };
+ // { dg-warning "explicit by-copy capture" "" { target c++17_down } .-1 }
+ auto a3 = [=, *this]() mutable { x = n; };
+ auto a4 = [&] { x = n; };
+ auto a5 = [&, this] { x = n; };
+ auto a6 = [&, *this]() mutable { x = n; };
+
+ auto a7 = [=] { // { dg-bogus "implicit capture" }
+ auto a = [=] { // { dg-bogus "implicit capture" }
+ auto a2 = [=] { x = n; }; // { dg-bogus "implicit capture" }
+ };
+ };
+
+ auto a8 = [=, this] {
+ // { dg-warning "explicit by-copy capture" "" { target c++17_down } .-1 }
+ auto a = [=, this] {
+ // { dg-warning "explicit by-copy capture" "" { target c++17_down } .-1 }
+ auto a2 = [=, this] { x = n; };
+ // { dg-warning "explicit by-copy capture" "" { target c++17_down } .-1 }
+ };
+ };
+
+ auto a9 = [=, *this]() mutable {
+ auto a = [=, *this]() mutable {
+ auto a2 = [=, *this]() mutable { x = n; };
+ };
+ };
+
+ auto a10 = [&] {
+ auto a = [&] {
+ auto a2 = [&] { x = n; };
+ };
+ };
+
+ auto a11 = [&, this] {
+ auto a = [&, this] {
+ auto a2 = [&, this] { x = n; };
+ };
+ };
+
+ auto a12 = [&, *this]() mutable {
+ auto a = [&, *this]() mutable {
+ auto a2 = [&, *this]() mutable { x = n; };
+ };
+ };
+ }
+};
diff --git a/gcc/testsuite/g++.dg/cpp2a/range-for11.C b/gcc/testsuite/g++.dg/cpp2a/range-for11.C
new file mode 100644
index 0000000..5f0a803
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/range-for11.C
@@ -0,0 +1,22 @@
+// PR c++/87152
+// { dg-do run }
+// { dg-options "-std=c++2a" }
+
+template<typename>
+int foo ()
+{
+ int a[] = { 1, 2, 3, 4, 5 };
+ int j = 0;
+ for (int i = 0; auto x : a)
+ j += i++;
+
+ return j;
+}
+
+int
+main ()
+{
+ int j = foo<int>();
+ if (j != 10)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/range-for12.C b/gcc/testsuite/g++.dg/cpp2a/range-for12.C
new file mode 100644
index 0000000..0955834
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/range-for12.C
@@ -0,0 +1,33 @@
+// PR c++/87152
+// { dg-do compile }
+// { dg-options "-std=c++2a" }
+
+static const int a[] = { 1, 2, 3, 4, 5 };
+extern void foo (int);
+extern void bar (int, int);
+
+constexpr int
+baz ()
+{
+ return 6;
+}
+
+template<typename T>
+void
+fn1 (T i)
+{
+ for ((i += 2); auto x : a)
+ foo (i);
+
+ for (auto j = 0, k = 0; auto x : a)
+ bar (j + k, x);
+
+ for (constexpr int j = baz (); auto x : a)
+ bar (x, j);
+}
+
+void
+do_fn1 ()
+{
+ fn1<int>(10);
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/range-for13.C b/gcc/testsuite/g++.dg/cpp2a/range-for13.C
new file mode 100644
index 0000000..fb1ff28
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/range-for13.C
@@ -0,0 +1,33 @@
+// PR c++/87152
+// { dg-do run }
+// { dg-options "-std=c++2a" }
+
+template<typename T>
+void foo ()
+{
+ int a[] = { 1, 2, 3, 4, 5 };
+
+ for (T i = 1; auto x : a)
+ if (i++ != x)
+ __builtin_abort ();
+
+ T i;
+ for (i = 1; auto x : a)
+ if (i++ != x)
+ __builtin_abort ();
+
+ i = 0;
+ for (i++; auto x : a)
+ if (i != 1)
+ __builtin_abort ();
+
+ for (T s[] = { 1, 1, 1 }; auto x : s)
+ if (x != 1)
+ __builtin_abort ();
+}
+
+int
+main ()
+{
+ foo<int>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/range-for14.C b/gcc/testsuite/g++.dg/cpp2a/range-for14.C
new file mode 100644
index 0000000..94ff3c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/range-for14.C
@@ -0,0 +1,24 @@
+// PR c++/87152
+// { dg-do run }
+// { dg-options "-std=c++2a" }
+
+template<typename T>
+void
+fn ()
+{
+ T a[] = { 1, 2, 3, 4, 5 };
+
+ for (T i = []{ return 3; }(); auto x : a)
+ if (i != 3)
+ __builtin_abort ();
+
+ for (T i = ({ 3; }); auto x : a)
+ if (i != 3)
+ __builtin_abort ();
+}
+
+int
+main ()
+{
+ fn<int>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/range-for15.C b/gcc/testsuite/g++.dg/cpp2a/range-for15.C
new file mode 100644
index 0000000..532b768
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/range-for15.C
@@ -0,0 +1,43 @@
+// PR c++/87152
+// { dg-do run }
+// { dg-options "-std=c++2a" }
+
+struct A { int i; long long j; } a[64];
+
+template<typename T>
+void foo ()
+{
+ for (T i = 0; auto &x : a)
+ {
+ x.i = i;
+ x.j = 2 * i++;
+ }
+ for (auto & [ x, y ] : a)
+ {
+ x += 2;
+ y += 3;
+ }
+ for (T i = 0; const auto [ u, v ] : a)
+ {
+ if (u != i + 2 || v != 2 * i++ + 3)
+ __builtin_abort ();
+ }
+ for (T i = 0; auto [ x, y ] : a)
+ {
+ x += 4;
+ y += 5;
+ if (x != i + 6 || y != 2 * i++ + 8)
+ __builtin_abort ();
+ }
+ for (T i = 0; const auto x : a)
+ {
+ if (x.i != i + 2 || x.j != 2 * i++ + 3)
+ __builtin_abort ();
+ }
+}
+
+int
+main ()
+{
+ foo<int>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/range-for16.C b/gcc/testsuite/g++.dg/cpp2a/range-for16.C
new file mode 100644
index 0000000..cbfd987
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/range-for16.C
@@ -0,0 +1,36 @@
+// PR c++/87152
+// { dg-do run }
+// { dg-options "-std=c++2a" }
+
+struct A { int i, j; };
+
+template<typename T>
+void foo ()
+{
+ A a = { .i = 2, .j = 3 };
+ T arr[] = { 1, 1, 1 };
+
+ for (auto & [ x, y ] = a; auto z : arr)
+ if (x + z != 3 || y + z != 4)
+ __builtin_abort ();
+
+ for (T d = 1; auto &z : arr)
+ z += d;
+
+ for (const auto [ x, y ] = a; auto z : arr)
+ if (x + z != 4 || y + z != 5)
+ __builtin_abort ();
+
+ for (T d = 1; auto &z : arr)
+ z += d;
+
+ for (auto [ x, y ] = a; auto z : arr)
+ if (x + z != 5 || y + z != 6)
+ __builtin_abort ();
+}
+
+int
+main ()
+{
+ foo<int>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/range-for17.C b/gcc/testsuite/g++.dg/cpp2a/range-for17.C
new file mode 100644
index 0000000..2e8734b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/range-for17.C
@@ -0,0 +1,30 @@
+// PR c++/87152
+// { dg-do run }
+// { dg-options "-std=c++2a" }
+
+struct A { int i; long long j; } a[64];
+
+template<typename>
+void foo ()
+{
+ A b = { 1, 2 };
+ for (auto & [ u, v ] : a)
+ {
+ u = 2;
+ v = 3;
+ }
+
+ for (auto [x, y] = b; auto [ u, v ] : a)
+ if (y + u != x + v)
+ __builtin_abort ();
+
+ for (auto [x, y] = b; auto & [ u, v ] : a)
+ if (y + u != x + v)
+ __builtin_abort ();
+}
+
+int
+main ()
+{
+ foo<int>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/range-for18.C b/gcc/testsuite/g++.dg/cpp2a/range-for18.C
new file mode 100644
index 0000000..e38b41c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/range-for18.C
@@ -0,0 +1,16 @@
+// PR c++/87152
+// { dg-do compile }
+// { dg-options "-std=c++2a" }
+
+template<int> void foo()
+{
+ int a[] = { 1, 1, 1 };
+ for (int i = 0; auto x : a);
+ int i;
+}
+
+void
+bar ()
+{
+ foo<0>();
+}
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/pr85302.C b/gcc/testsuite/g++.dg/debug/dwarf2/pr85302.C
index 97ac302..457508d 100644
--- a/gcc/testsuite/g++.dg/debug/dwarf2/pr85302.C
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/pr85302.C
@@ -1,5 +1,6 @@
// PR debug/85302
// { dg-do compile }
+// { dg-skip-if "split DWARF unsupported" { *-*-darwin* } }
// { dg-options "-std=c++11 -gsplit-dwarf -O1" }
// { dg-additional-options "-fPIE" { target pie } }
diff --git a/gcc/testsuite/g++.dg/diagnostic/aka3.C b/gcc/testsuite/g++.dg/diagnostic/aka3.C
new file mode 100644
index 0000000..1eb4fb2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/aka3.C
@@ -0,0 +1,25 @@
+/* Verify the "aka" descriptions for typedefs are correctly
+ quoted and shown within labels. */
+
+/* { dg-options "-fdiagnostics-show-caret" } */
+
+typedef struct s1 t1;
+typedef struct s2 {int i;} t2;
+
+int foo(t1 *);
+
+void test_1 () {
+ t2 pos;
+
+ foo (&pos); // { dg-error "cannot convert 't2\\*' {aka 's2\\*'} to 't1\\*' {aka 's1\\*'}" }
+ /* { dg-begin-multiline-output "" }
+ foo (&pos);
+ ^~~~
+ |
+ t2* {aka s2*}
+ { dg-end-multiline-output "" } */
+ /* { dg-begin-multiline-output "" }
+ int foo(t1 *);
+ ^~~~
+ { dg-end-multiline-output "" } */
+}
diff --git a/gcc/testsuite/g++.dg/diagnostic/auto1.C b/gcc/testsuite/g++.dg/diagnostic/auto1.C
new file mode 100644
index 0000000..ee2eefd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/auto1.C
@@ -0,0 +1,4 @@
+// PR c++/86915
+// { dg-do compile { target c++17 } }
+
+template<auto [1]> struct S; // { dg-error "creating array of .auto." }
diff --git a/gcc/testsuite/g++.dg/diagnostic/missing-typename.C b/gcc/testsuite/g++.dg/diagnostic/missing-typename.C
new file mode 100644
index 0000000..21d1ed1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/missing-typename.C
@@ -0,0 +1,12 @@
+// fix-it hint for missing "typename" (PR c++/63392)
+// { dg-options "-fdiagnostics-show-caret" }
+
+template<typename T>
+class test_1 {
+ T::type x; // { dg-error "need 'typename' before 'T::type' because 'T' is a dependent scope" }
+ /* { dg-begin-multiline-output "" }
+ T::type x;
+ ^
+ typename
+ { dg-end-multiline-output "" } */
+};
diff --git a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C
index c3b6f00..f74f8d3 100644
--- a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C
+++ b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C
@@ -12,6 +12,8 @@ int test_1 (int first, const char *second, float third)
/* { dg-begin-multiline-output "" }
return callee_1 (first, second, third);
^~~~~~
+ |
+ const char*
{ dg-end-multiline-output "" } */
// { dg-message "initializing argument 2 of 'int callee_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } callee_1 }
/* { dg-begin-multiline-output "" }
@@ -30,6 +32,8 @@ int test_2 (int first, const char *second, float third)
/* { dg-begin-multiline-output "" }
return callee_2 (first, second, third);
^~~~~~
+ |
+ const char*
{ dg-end-multiline-output "" } */
// { dg-message "initializing argument 2 of 'int callee_2\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } callee_2 }
/* { dg-begin-multiline-output "" }
@@ -51,6 +55,8 @@ int test_3 (int first, const char *second, float third)
/* { dg-begin-multiline-output "" }
return callee_3 (first, second, third);
^~~~~~
+ |
+ const char*
{ dg-end-multiline-output "" } */
// { dg-message "initializing argument 2 of 'int callee_3\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } callee_3 }
/* { dg-begin-multiline-output "" }
@@ -65,18 +71,18 @@ struct s4 { static int member_1 (int one, const char **two, float three); }; //
int test_4 (int first, const char *second, float third)
{
- return s4::member_1 (first, second, third); // { dg-error "no matching function for call to 's4::member_1\\(int&, const char\\*&, float&\\)'" }
+ return s4::member_1 (first, second, third); // { dg-error "31: cannot convert 'const char\\*' to 'const char\\*\\*'" }
/* { dg-begin-multiline-output "" }
return s4::member_1 (first, second, third);
- ^
+ ^~~~~~
+ |
+ const char*
{ dg-end-multiline-output "" } */
- // { dg-message "candidate: 'static int s4::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s4_member_1 }
- /* { dg-begin-multiline-output "" }
+ // { dg-message "initializing argument 2 of 'static int s4::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s4_member_1 }
+ /* { dg-begin-multiline-output "" }
struct s4 { static int member_1 (int one, const char **two, float three); };
- ^~~~~~~~
+ ~~~~~~~~~~~~~^~~
{ dg-end-multiline-output "" } */
- // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s4_member_1 }
- // TODO: underline the pertinent param
}
/* non-static member, with argname. */
@@ -86,18 +92,18 @@ struct s5 { int member_1 (int one, const char **two, float three); }; // { dg-li
int test_5 (int first, const char *second, float third)
{
s5 inst;
- return inst.member_1 (first, second, third); // { dg-error "no matching function for call to 's5::member_1\\(int&, const char\\*&, float&\\)'" }
+ return inst.member_1 (first, second, third); // { dg-error "32: cannot convert 'const char\\*' to 'const char\\*\\*'" }
/* { dg-begin-multiline-output "" }
return inst.member_1 (first, second, third);
- ^
+ ^~~~~~
+ |
+ const char*
{ dg-end-multiline-output "" } */
- // { dg-message "candidate: 'int s5::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s5_member_1 }
+ // { dg-message "initializing argument 2 of 'int s5::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s5_member_1 }
/* { dg-begin-multiline-output "" }
struct s5 { int member_1 (int one, const char **two, float three); };
- ^~~~~~~~
+ ~~~~~~~~~~~~~^~~
{ dg-end-multiline-output "" } */
- // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s5_member_1 }
- // TODO: underline the pertinent param
}
/* non-static member, with argname, via a ptr. */
@@ -106,18 +112,18 @@ struct s6 { int member_1 (int one, const char **two, float three); }; // { dg-li
int test_6 (int first, const char *second, float third, s6 *ptr)
{
- return ptr->member_1 (first, second, third); // { dg-error "no matching function for call to 's6::member_1\\(int&, const char\\*&, float&\\)'" }
+ return ptr->member_1 (first, second, third); // { dg-error "32: cannot convert 'const char\\*' to 'const char\\*\\*'" }
/* { dg-begin-multiline-output "" }
return ptr->member_1 (first, second, third);
- ^
+ ^~~~~~
+ |
+ const char*
{ dg-end-multiline-output "" } */
- // { dg-message "candidate: 'int s6::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s6_member_1 }
- /* { dg-begin-multiline-output "" }
+ // { dg-message "initializing argument 2 of 'int s6::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s6_member_1 }
+ /* { dg-begin-multiline-output "" }
struct s6 { int member_1 (int one, const char **two, float three); };
- ^~~~~~~~
+ ~~~~~~~~~~~~~^~~
{ dg-end-multiline-output "" } */
- // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s6_member_1 }
- // TODO: underline the pertinent param
}
/* Template function. */
@@ -153,18 +159,18 @@ struct s8 { static int member_1 (int one, T two, float three); }; // { dg-line s
int test_8 (int first, const char *second, float third)
{
- return s8 <const char **>::member_1 (first, second, third); // { dg-error "no matching function for call to 's8<const char\\*\\*>::member_1\\(int&, const char\\*&, float&\\)'" }
+ return s8 <const char **>::member_1 (first, second, third); // { dg-error "47: cannot convert 'const char\\*' to 'const char\\*\\*'" }
/* { dg-begin-multiline-output "" }
return s8 <const char **>::member_1 (first, second, third);
- ^
+ ^~~~~~
+ |
+ const char*
{ dg-end-multiline-output "" } */
- // { dg-message "candidate: 'static int s8<T>::member_1\\(int, T, float\\)" "" { target *-*-* } s8_member_1 }
+ // { dg-message "initializing argument 2 of 'static int s8<T>::member_1\\(int, T, float\\) .with T = const char\\*\\*.'" "" { target *-*-* } s8_member_1 }
/* { dg-begin-multiline-output "" }
struct s8 { static int member_1 (int one, T two, float three); };
- ^~~~~~~~
+ ~~^~~
{ dg-end-multiline-output "" } */
- // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s8_member_1 }
- // TODO: underline the pertinent param
}
/* Template class, non-static function. */
@@ -175,16 +181,43 @@ struct s9 { int member_1 (int one, T two, float three); }; // { dg-line s9_membe
int test_9 (int first, const char *second, float third)
{
s9 <const char **> inst;
- return inst.member_1 (first, second, third); // { dg-error "no matching function for call to 's9<const char\\*\\*>::member_1\\(int&, const char\\*&, float&\\)'" }
+ return inst.member_1 (first, second, third); // { dg-error "32: cannot convert 'const char\\*' to 'const char\\*\\*'" }
/* { dg-begin-multiline-output "" }
return inst.member_1 (first, second, third);
- ^
+ ^~~~~~
+ |
+ const char*
{ dg-end-multiline-output "" } */
- // { dg-message "candidate: 'int s9<T>::member_1\\(int, T, float\\)" "" { target *-*-* } s9_member_1 }
+ // { dg-message "initializing argument 2 of 'int s9<T>::member_1\\(int, T, float\\) .with T = const char\\*\\*.'" "" { target *-*-* } s9_member_1 }
/* { dg-begin-multiline-output "" }
struct s9 { int member_1 (int one, T two, float three); };
- ^~~~~~~~
+ ~~^~~
+ { dg-end-multiline-output "" } */
+}
+
+/* Overloaded operator (with one candidate). */
+
+struct s10 {};
+
+extern int operator- (const s10&, int); // { dg-line s10_operator }
+
+int test_10 ()
+{
+ s10 v10_a, v10_b;
+
+ return v10_a - v10_b; // { dg-error "no match for" }
+ /* { dg-begin-multiline-output "" }
+ return v10_a - v10_b;
+ ~~~~~~^~~~~~~
+ { dg-end-multiline-output "" } */
+ // { dg-message "candidate" "" { target *-*-* } s10_operator }
+ /* { dg-begin-multiline-output "" }
+ extern int operator- (const s10&, int);
+ ^~~~~~~~
+ { dg-end-multiline-output "" } */
+ // { dg-message "no known conversion for argument 2 from" "" { target *-*-* } s10_operator }
+ /* { dg-begin-multiline-output "" }
+ extern int operator- (const s10&, int);
+ ^~~
{ dg-end-multiline-output "" } */
- // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s9_member_1 }
- // TODO: underline the pertinent param
}
diff --git a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
index 5fcde0b..50bbd4a 100644
--- a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
+++ b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
@@ -12,6 +12,8 @@ int test_1 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_1 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
// { dg-message "initializing argument 2 of 'int callee_1\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_1 }
/* { dg-begin-multiline-output "" }
@@ -30,6 +32,8 @@ int test_2 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_2 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
// { dg-message "initializing argument 2 of 'int callee_2\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_2 }
/* { dg-begin-multiline-output "" }
@@ -51,6 +55,8 @@ int test_3 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_3 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
// { dg-message "initializing argument 2 of 'int callee_3\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_3 }
/* { dg-begin-multiline-output "" }
@@ -69,6 +75,8 @@ int test_4 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return s4::member_1 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
struct s4 { static int member_1 (int one, const char *two, float three); };
@@ -87,6 +95,8 @@ int test_5 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return inst.member_1 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
struct s5 { int member_1 (int one, const char *two, float three); };
@@ -104,6 +114,8 @@ int test_6 (int first, int second, float third, s6 *ptr)
/* { dg-begin-multiline-output "" }
return ptr->member_1 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
struct s6 { int member_1 (int one, const char *two, float three); };
@@ -144,6 +156,8 @@ int test_8 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return s8 <const char *>::member_1 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
struct s8 { static int member_1 (int one, T two, float three); };
@@ -163,6 +177,8 @@ int test_9 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return inst.member_1 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
struct s9 { int member_1 (int one, T two, float three); };
@@ -180,6 +196,8 @@ int test_10 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_10 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
// { dg-message "initializing argument 2 of 'int callee_10\\(int, int \\(\\*\\)\\(int, int\\), float\\)'" "" { target *-*-* } callee_10 }
/* { dg-begin-multiline-output "" }
@@ -198,6 +216,8 @@ int test_11 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_11 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
// { dg-message "initializing argument 2 of 'int callee_11\\(int, int \\(\\*\\)\\(int, int\\), float\\)'" "" { target *-*-* } callee_11 }
/* { dg-begin-multiline-output "" }
diff --git a/gcc/testsuite/g++.dg/diagnostic/pr86993.C b/gcc/testsuite/g++.dg/diagnostic/pr86993.C
new file mode 100644
index 0000000..313a489
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/pr86993.C
@@ -0,0 +1,13 @@
+// PR c++/86993
+// { dg-options "-fdiagnostics-show-caret" }
+
+int
+main ()
+{
+ const int i = 5; // { dg-error "assignment of read-only variable 'i'" "" { target *-*-* } .+1 }
+ i = 5 + 6;
+/* { dg-begin-multiline-output "" }
+ i = 5 + 6;
+ ~~^~~~~~~
+ { dg-end-multiline-output "" } */
+}
diff --git a/gcc/testsuite/g++.dg/diagnostic/virtual-constexpr.C b/gcc/testsuite/g++.dg/diagnostic/virtual-constexpr.C
index 2c83236..9223c69 100644
--- a/gcc/testsuite/g++.dg/diagnostic/virtual-constexpr.C
+++ b/gcc/testsuite/g++.dg/diagnostic/virtual-constexpr.C
@@ -1,14 +1,15 @@
-// { dg-options "-fdiagnostics-show-caret" }
+// { dg-options "-fdiagnostics-show-caret -pedantic-errors" }
// { dg-do compile { target c++11 } }
+// { dg-skip-if "virtual constexpr" { *-*-* } { "-std=gnu++2a" } { "" } }
struct S
{
- virtual constexpr void foo(); // { dg-error "3:member .foo. cannot be declared both .virtual. and .constexpr." }
+ virtual constexpr void foo(); // { dg-error "3:member .foo. can be declared both .virtual. and .constexpr." }
/* { dg-begin-multiline-output "" }
virtual constexpr void foo();
^~~~~~~ ~~~~~~~~~
{ dg-end-multiline-output "" } */
- constexpr virtual void bar(); // { dg-error "13:member .bar. cannot be declared both .virtual. and .constexpr." }
+ constexpr virtual void bar(); // { dg-error "13:member .bar. can be declared both .virtual. and .constexpr." }
/* { dg-begin-multiline-output "" }
constexpr virtual void bar();
~~~~~~~~~ ^~~~~~~
diff --git a/gcc/testsuite/g++.dg/expr/pmf-1.C b/gcc/testsuite/g++.dg/expr/pmf-1.C
index e6b7219..35ebe529 100644
--- a/gcc/testsuite/g++.dg/expr/pmf-1.C
+++ b/gcc/testsuite/g++.dg/expr/pmf-1.C
@@ -14,6 +14,6 @@ struct A
{
void (A::*p)() = &A::f;
void (A::*q)() = &(A::f); // { dg-error "parenthesized" }
- foo(&g<int>); // { dg-error "no matching" }
+ foo(&g<int>); // { dg-error "cannot convert" }
}
};
diff --git a/gcc/testsuite/g++.dg/expr/pmf-3.C b/gcc/testsuite/g++.dg/expr/pmf-3.C
index fac42fc..b94cd8e 100644
--- a/gcc/testsuite/g++.dg/expr/pmf-3.C
+++ b/gcc/testsuite/g++.dg/expr/pmf-3.C
@@ -1,5 +1,6 @@
// PR c++/80485
// { dg-do compile { target c++11 } }
+// { dg-options "-fdelete-null-pointer-checks" }
struct dummy {
void nonnull() {};
diff --git a/gcc/testsuite/g++.dg/ext/attr-returns-nonnull.C b/gcc/testsuite/g++.dg/ext/attr-returns-nonnull.C
index f75f32e..46d1fa0 100644
--- a/gcc/testsuite/g++.dg/ext/attr-returns-nonnull.C
+++ b/gcc/testsuite/g++.dg/ext/attr-returns-nonnull.C
@@ -4,7 +4,7 @@
// does not "inherit" attribute nonnull from an argument declared with
// one in the primary template.
// { dg-do compile }
-// { dg-options "-O -Wall -fdump-tree-optimized" }
+// { dg-options "-O -Wall -fdump-tree-optimized -fdelete-null-pointer-checks" }
template <class T>
void* __attribute__ ((returns_nonnull))
diff --git a/gcc/testsuite/g++.dg/ext/is_aggregate.C b/gcc/testsuite/g++.dg/ext/is_aggregate.C
index 8adc6c4..bdcc70f 100644
--- a/gcc/testsuite/g++.dg/ext/is_aggregate.C
+++ b/gcc/testsuite/g++.dg/ext/is_aggregate.C
@@ -61,6 +61,8 @@ struct K { int a, b; virtual void foo (); };
struct L : virtual public A { int d, e; };
struct M : protected A { int d, e; };
struct N : private A { int d, e; };
+struct O { O () = delete; int a, b, c; };
+struct P { P () = default; int a, b, c; };
typedef int T;
typedef float U;
typedef int V __attribute__((vector_size (4 * sizeof (int))));
@@ -94,6 +96,13 @@ main ()
assert (NTEST (L));
assert (NTEST (M));
assert (NTEST (N));
+#if __cplusplus > 201703L
+ assert (NTEST (O));
+ assert (NTEST (P));
+#else
+ assert (PTEST (O));
+ assert (PTEST (P));
+#endif
assert (PTEST (int[]));
assert (PTEST (double[]));
assert (PTEST (T[2]));
@@ -114,4 +123,6 @@ main ()
assert (PTEST (L[]));
assert (PTEST (M[6]));
assert (PTEST (N[]));
+ assert (PTEST (O[]));
+ assert (PTEST (P[]));
}
diff --git a/gcc/testsuite/g++.dg/ext/is_constructible2.C b/gcc/testsuite/g++.dg/ext/is_constructible2.C
new file mode 100644
index 0000000..8f25e7e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_constructible2.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++11 } }
+
+#include <type_traits>
+
+template <typename T> struct x {
+ operator bool() {
+ static_assert(!std::is_same<T, T>::value, "");
+ return false;
+ }
+};
+
+static constexpr auto a = __is_constructible(bool, x<int>);
diff --git a/gcc/testsuite/g++.dg/ext/stmtexpr15.C b/gcc/testsuite/g++.dg/ext/stmtexpr15.C
index 83a831c..1a60a0d 100644
--- a/gcc/testsuite/g++.dg/ext/stmtexpr15.C
+++ b/gcc/testsuite/g++.dg/ext/stmtexpr15.C
@@ -3,5 +3,5 @@
void foo()
{
- int x[({ return; })]; // { dg-error "non-integral" }
+ int x[({ return; })]; // { dg-error "could not convert|non-integral" }
}
diff --git a/gcc/testsuite/g++.dg/gcov/loop.C b/gcc/testsuite/g++.dg/gcov/loop.C
index 7f3be55..24f5806 100644
--- a/gcc/testsuite/g++.dg/gcov/loop.C
+++ b/gcc/testsuite/g++.dg/gcov/loop.C
@@ -2,11 +2,11 @@
/* { dg-do run { target native } } */
unsigned
-loop (unsigned n, int value) /* count(14k) */
+loop (unsigned n, int value) /* count(14.0k) */
{
for (unsigned i = 0; i < n - 1; i++)
{
- value += i; /* count(21M) */
+ value += i; /* count(21.0M) */
}
return value;
@@ -18,7 +18,7 @@ int main(int argc, char **argv)
for (unsigned i = 0; i < 7 * 1000; i++)
{
sum += loop (1000, sum);
- sum += loop (2000, sum); /* count(7k) */
+ sum += loop (2000, sum); /* count(7.0k) */
}
return 0; /* count(1) */
diff --git a/gcc/testsuite/g++.dg/gomp/pr47963.C b/gcc/testsuite/g++.dg/gomp/pr47963.C
index 5b0c60b..6be4c0e 100644
--- a/gcc/testsuite/g++.dg/gomp/pr47963.C
+++ b/gcc/testsuite/g++.dg/gomp/pr47963.C
@@ -5,7 +5,7 @@
void
foo (float n)
{
- int A[n][n]; // { dg-error "has non-integral type|converted constant expression" }
+ int A[n][n]; // { dg-error "could not convert|has non-integral type|converted constant expression" }
#pragma omp parallel private(A)
;
}
diff --git a/gcc/testsuite/g++.dg/guality/pr86687.C b/gcc/testsuite/g++.dg/guality/pr86687.C
new file mode 100644
index 0000000..140a6fc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/guality/pr86687.C
@@ -0,0 +1,28 @@
+// PR debug/86687
+// { dg-do run }
+// { dg-options "-g" }
+
+class string {
+public:
+ string (int p) { this->p = p ; }
+ string (const string &s) { this->p = s.p; }
+
+ int p;
+};
+
+class foo {
+public:
+ foo (string dir_hint) {
+ p = dir_hint.p; // { dg-final { gdb-test . "dir_hint.p" 3 } }
+ }
+
+ int p;
+};
+
+int
+main (void)
+{
+ string s = 3;
+ foo bar(s);
+ return !(bar.p == 3);
+}
diff --git a/gcc/testsuite/g++.dg/init/goto3.C b/gcc/testsuite/g++.dg/init/goto3.C
index 4c5ceab..72ca9b9 100644
--- a/gcc/testsuite/g++.dg/init/goto3.C
+++ b/gcc/testsuite/g++.dg/init/goto3.C
@@ -15,11 +15,11 @@ adapt_parameters_next_iteration(void)
case VAR_NONE: break;
case VAR_DELTA:
- int trunc_n_ants = 0;
+ int trunc_n_ants = 0; // { dg-message "initialization" }
n_ants += trunc_n_ants;
break;
- case VAR_SWITCH:
+ case VAR_SWITCH: // { dg-error "jump" }
break;
- default: break;
+ default: break; // { dg-error "jump" }
}
}
diff --git a/gcc/testsuite/g++.dg/init/new37.C b/gcc/testsuite/g++.dg/init/new37.C
index 9ecbfd7..2a42fda 100644
--- a/gcc/testsuite/g++.dg/init/new37.C
+++ b/gcc/testsuite/g++.dg/init/new37.C
@@ -32,7 +32,7 @@ template <typename T>
void *
callnew_fail_3()
{
- return new T[2][T::n]; // { dg-error "size of array has non-integral type|converted constant expression" }
+ return new T[2][T::n]; // { dg-error "could not convert|size of array has non-integral type|converted constant expression" }
}
struct T1 {
diff --git a/gcc/testsuite/g++.dg/init/new43.C b/gcc/testsuite/g++.dg/init/new43.C
index 9b08667..aa40b42 100644
--- a/gcc/testsuite/g++.dg/init/new43.C
+++ b/gcc/testsuite/g++.dg/init/new43.C
@@ -31,35 +31,35 @@ void test_literal ()
// Verify integer literal.
p = new char [-1]; // { dg-error "size of array is negative" }
- p = new char [2][-3]; // { dg-error "size of array is negative" }
+ p = new char [2][-3]; // { dg-error "size of array|narrowing conversion" }
p = new char [-4][5]; // { dg-error "size of array is negative" }
- p = new char [-6][-7]; // { dg-error "size of array is negative" }
+ p = new char [-6][-7]; // { dg-error "size of array|narrowing conversion" }
p = new (p) char [-1]; // { dg-error "size of array is negative" }
- p = new (p) char [2][-3]; // { dg-error "size of array is negative" }
+ p = new (p) char [2][-3]; // { dg-error "size of array|narrowing conversion" }
p = new (p) char [-4][5]; // { dg-error "size of array is negative" }
- p = new (p) char [-6][-7]; // { dg-error "size of array is negative" }
+ p = new (p) char [-6][-7]; // { dg-error "size of array|narrowing conversion" }
p = new (p) A [-1]; // { dg-error "size of array is negative" }
- p = new (p) A [2][-3]; // { dg-error "size of array is negative" }
+ p = new (p) A [2][-3]; // { dg-error "size of array|narrowing conversion" }
p = new (p) A [-4][5]; // { dg-error "size of array is negative" }
- p = new (p) A [-6][-7]; // { dg-error "size of array is negative" }
+ p = new (p) A [-6][-7]; // { dg-error "size of array|narrowing conversion" }
p = new (p) B [-1]; // { dg-error "size of array is negative" }
- p = new (p) B [2][-3]; // { dg-error "size of array is negative" }
+ p = new (p) B [2][-3]; // { dg-error "size of array|narrowing conversion" }
p = new (p) B [-4][5]; // { dg-error "size of array is negative" }
- p = new (p) B [-6][-7]; // { dg-error "size of array is negative" }
+ p = new (p) B [-6][-7]; // { dg-error "size of array|narrowing conversion" }
p = new (&b) B [-1]; // { dg-error "size of array is negative" }
- p = new (&b) B [2][-3]; // { dg-error "size of array is negative" }
+ p = new (&b) B [2][-3]; // { dg-error "size of array|narrowing conversion" }
p = new (&b) B [-4][5]; // { dg-error "size of array is negative" }
- p = new (&b) B [-6][-7]; // { dg-error "size of array is negative" }
+ p = new (&b) B [-6][-7]; // { dg-error "size of array|narrowing conversion" }
p = new char [1 - 2]; // { dg-error "size of array is negative" }
p = new (p) char [2 - 3]; // { dg-error "size of array is negative" }
p = new A [2 < 1 ? -1 : -2]; // { dg-error "size of array is negative" }
p = new (p) B [2 - 3 * 2]; // { dg-error "size of array is negative" }
- p = new (&b) B [1][2 - 3 * 2];// { dg-error "size of array is negative" }
+ p = new (&b) B [1][2 - 3 * 2];// { dg-error "size of array|narrowing conversion" }
}
void test_constant_expression ()
@@ -79,35 +79,35 @@ void test_constant_expression ()
// Verify constant expression.
p = new char [i1]; // { dg-error "size of array is negative" }
- p = new char [2][i3]; // { dg-error "size of array is negative" }
+ p = new char [2][i3]; // { dg-error "size of array|narrowing conversion" }
p = new char [i4][5]; // { dg-error "size of array is negative" }
- p = new char [i6][i7]; // { dg-error "size of array is negative" }
+ p = new char [i6][i7]; // { dg-error "size of array|narrowing conversion" }
p = new (p) char [i1]; // { dg-error "size of array is negative" }
- p = new (p) char [2][i3]; // { dg-error "size of array is negative" }
+ p = new (p) char [2][i3]; // { dg-error "size of array|narrowing conversion" }
p = new (p) char [i4][5]; // { dg-error "size of array is negative" }
- p = new (p) char [i6][i7]; // { dg-error "size of array is negative" }
+ p = new (p) char [i6][i7]; // { dg-error "size of array|narrowing conversion" }
p = new (p) A [i1]; // { dg-error "size of array is negative" }
- p = new (p) A [2][i3]; // { dg-error "size of array is negative" }
+ p = new (p) A [2][i3]; // { dg-error "size of array|narrowing conversion" }
p = new (p) A [i4][5]; // { dg-error "size of array is negative" }
- p = new (p) A [i6][i7]; // { dg-error "size of array is negative" }
+ p = new (p) A [i6][i7]; // { dg-error "size of array|narrowing conversion" }
p = new (p) B [i1]; // { dg-error "size of array is negative" }
- p = new (p) B [2][i3]; // { dg-error "size of array is negative" }
+ p = new (p) B [2][i3]; // { dg-error "size of array|narrowing conversion" }
p = new (p) B [i4][5]; // { dg-error "size of array is negative" }
- p = new (p) B [i6][i7]; // { dg-error "size of array is negative" }
+ p = new (p) B [i6][i7]; // { dg-error "size of array|narrowing conversion" }
p = new (&b) B [i1]; // { dg-error "size of array is negative" }
- p = new (&b) B [2][i3]; // { dg-error "size of array is negative" }
+ p = new (&b) B [2][i3]; // { dg-error "size of array|narrowing conversion" }
p = new (&b) B [i4][5]; // { dg-error "size of array is negative" }
- p = new (&b) B [i6][i7]; // { dg-error "size of array is negative" }
+ p = new (&b) B [i6][i7]; // { dg-error "size of array|narrowing conversion" }
p = new short [i1 - 2]; // { dg-error "size of array is negative" }
p = new (p) bool [i2 - 3]; // { dg-error "size of array is negative" }
p = new A [2 < 1 ? i1 : i2]; // { dg-error "size of array is negative" }
p = new (p) B [2 + i3 * 2]; // { dg-error "size of array is negative" }
- p = new (&b) B [1][i1 - 3 * 2];// { dg-error "size of array is negative" }
+ p = new (&b) B [1][i1 - 3 * 2];// { dg-error "size of array|narrowing conversion" }
}
void test_constexpr ()
@@ -132,33 +132,33 @@ void test_constexpr ()
// Verify constant expression.
p = new char [s1]; // { dg-error "size of array is negative" }
- p = new char [2][s3]; // { dg-error "size of array is negative" }
+ p = new char [2][s3]; // { dg-error "size of array|narrowing conversion" }
p = new char [s4][5]; // { dg-error "size of array is negative" }
- p = new char [s6][s7]; // { dg-error "size of array is negative" }
+ p = new char [s6][s7]; // { dg-error "size of array|narrowing conversion" }
p = new (p) char [s1]; // { dg-error "size of array is negative" }
- p = new (p) char [2][s3]; // { dg-error "size of array is negative" }
+ p = new (p) char [2][s3]; // { dg-error "size of array|narrowing conversion" }
p = new (p) char [s4][5]; // { dg-error "size of array is negative" }
- p = new (p) char [s6][s7]; // { dg-error "size of array is negative" }
+ p = new (p) char [s6][s7]; // { dg-error "size of array|narrowing conversion" }
p = new (p) A [s1]; // { dg-error "size of array is negative" }
- p = new (p) A [2][s3]; // { dg-error "size of array is negative" }
+ p = new (p) A [2][s3]; // { dg-error "size of array|narrowing conversion" }
p = new (p) A [s4][5]; // { dg-error "size of array is negative" }
- p = new (p) A [s6][s7]; // { dg-error "size of array is negative" }
+ p = new (p) A [s6][s7]; // { dg-error "size of array|narrowing conversion" }
p = new (p) B [s1]; // { dg-error "size of array is negative" }
- p = new (p) B [2][s3]; // { dg-error "size of array is negative" }
+ p = new (p) B [2][s3]; // { dg-error "size of array|narrowing conversion" }
p = new (p) B [s4][5]; // { dg-error "size of array is negative" }
- p = new (p) B [s6][s7]; // { dg-error "size of array is negative" }
+ p = new (p) B [s6][s7]; // { dg-error "size of array|narrowing conversion" }
p = new (&b) B [s1]; // { dg-error "size of array is negative" }
- p = new (&b) B [2][s3]; // { dg-error "size of array is negative" }
+ p = new (&b) B [2][s3]; // { dg-error "size of array|narrowing conversion" }
p = new (&b) B [s4][5]; // { dg-error "size of array is negative" }
- p = new (&b) B [s6][s7]; // { dg-error "size of array is negative" }
+ p = new (&b) B [s6][s7]; // { dg-error "size of array|narrowing conversion" }
p = new int [s1 + s2]; // { dg-error "size of array is negative" }
p = new (p) long [2 * s3]; // { dg-error "size of array is negative" }
p = new A [s2 < s1 ? s1 : s2]; // { dg-error "size of array is negative" }
p = new (p) B [s7 - s2 * 2]; // { dg-error "size of array is negative" }
- p = new (&b) B [9][s4 - s1 * 2]; // { dg-error "size of array is negative" }
+ p = new (&b) B [9][s4 - s1 * 2]; // { dg-error "size of array|narrowing conversion" }
}
diff --git a/gcc/testsuite/g++.dg/init/string2.C b/gcc/testsuite/g++.dg/init/string2.C
new file mode 100644
index 0000000..19ae6b4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/string2.C
@@ -0,0 +1,104 @@
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+//
+// Verify that strlen() calls with constant character array arguments
+// initialized with string constants are folded. (This is a small
+// subset of pr71625).
+// { dg-do compile }
+// { dg-options "-O0 -Wno-error=narrowing -fdump-tree-gimple" }
+
+#define A(expr) do { typedef char A[-1 + 2 * !!(expr)]; } while (0)
+
+/* This is undefined but accepted without -Wpedantic. Verify that
+ the size is zero. */
+const char ax[] = { };
+
+void size0 ()
+{
+ A (sizeof ax == 0);
+}
+
+const char a0[] = { 'a', 'b', 'c', '\0' };
+
+int len0 ()
+{
+ return __builtin_strlen (a0);
+}
+
+// Verify that narrowing warnings are preserved.
+const signed char
+sa0[] = { 'a', 'b', 255, '\0' }; // { dg-warning "\\\[\(-Wnarrowing|-Woverflow\)" "" { target { ! c++98_only } } }
+
+int lens0 ()
+{
+ return __builtin_strlen ((const char*)sa0);
+}
+
+const unsigned char
+ua0[] = { 'a', 'b', -1, '\0' }; // { dg-warning "\\\[\(-Wnarrowing|-Woverflow\)" "" { target { ! c++98_only } } }
+
+int lenu0 ()
+{
+ return __builtin_strlen ((const char*)ua0);
+}
+
+const char c = 0;
+const char a1[] = { 'a', 'b', 'c', c };
+
+int len1 ()
+{
+ return __builtin_strlen (a1);
+}
+
+template <class T>
+int tmplen ()
+{
+ static const T
+ a[] = { 1, 2, 333, 0 }; // { dg-warning "\\\[\(-Wnarrowing|-Woverflow\)" }
+ return __builtin_strlen (a);
+}
+
+template int tmplen<char>();
+
+const wchar_t ws4[] = { 1, 2, 3, 4 };
+const wchar_t ws7[] = { 1, 2, 3, 4, 0, 0, 0 };
+const wchar_t ws9[9] = { 1, 2, 3, 4, 0 };
+
+void wsize ()
+{
+ A (sizeof ws4 == 4 * sizeof *ws4);
+ A (ws4[0] == 1 && ws4[1] == 2 && ws4[2] == 3 && ws4[3] == 4);
+
+ A (sizeof ws7 == 7 * sizeof *ws7);
+ A (ws7[0] == 1 && ws7[1] == 2 && ws7[2] == 3 && ws7[4] == 4
+ && !ws7[5] && !ws7[6]);
+
+ A (sizeof ws9 == 9 * sizeof *ws9);
+ A (ws9[0] == 1 && ws9[1] == 2 && ws9[2] == 3 && ws9[4] == 4
+ && !ws9[5] && !ws9[6] && !ws9[7] && !ws9[8]);
+}
+
+#if 0
+
+// The following aren't handled.
+
+const char &cref = c;
+const char a2[] = { 'a', 'b', 'c', cref };
+
+int len2 ()
+{
+ return __builtin_strlen (a2);
+}
+
+
+const char* const cptr = &cref;
+const char a3[] = { 'a', 'b', 'c', *cptr };
+
+int len3 ()
+{
+ return __builtin_strlen (a3);
+}
+
+#endif
+
+// { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
diff --git a/gcc/testsuite/g++.dg/init/string3.C b/gcc/testsuite/g++.dg/init/string3.C
new file mode 100644
index 0000000..8212e81
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/string3.C
@@ -0,0 +1,35 @@
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+//
+// Verify that strlen() call with a constant character array argument
+// initialized with non-constant elements isn't folded.
+//
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-optimized" }
+
+
+extern const char c;
+const char a0[] = { 'a', 'b', 'c', c };
+
+int len0 ()
+{
+ return __builtin_strlen (a0);
+}
+
+const char &ref = c;
+const char a1[] = { 'a', 'b', 'c', ref };
+
+int len1 ()
+{
+ return __builtin_strlen (a1);
+}
+
+const char* const ptr = &c;
+const char a2[] = { 'a', 'b', 'c', *ptr };
+
+int len2 ()
+{
+ return __builtin_strlen (a2);
+}
+
+// { dg-final { scan-tree-dump-times "strlen" 3 "optimized" } }
diff --git a/gcc/testsuite/g++.dg/init/string4.C b/gcc/testsuite/g++.dg/init/string4.C
new file mode 100644
index 0000000..5df4176
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/string4.C
@@ -0,0 +1,60 @@
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+
+// Verify that zero-length array initialization results in the expected
+// array sizes and in the expected diagnostics. See init-string-3.c
+// for the corresponding C test.
+
+// { dg-do compile }
+// { dg-options "-Wall -Wno-unused-local-typedefs -fpermissive" }
+
+#define A(expr) typedef char A[-1 + 2 * !!(expr)];
+
+const char a[] = { };
+
+A (sizeof a == 0);
+
+
+const char b[0] = { };
+
+A (sizeof b == 0);
+
+// Also verify that the error is "too many initializers for
+// 'const char [0]'" and not "initializer-string is too long."
+const char c[0] = { 1 }; // { dg-error "too many initializers for .const char \\\[0]" }
+
+A (sizeof c == 0);
+
+
+void test_auto_empty (void)
+{
+ const char a[] = { };
+
+ A (sizeof a == 0);
+}
+
+void test_auto_zero_length (void)
+{
+ const char a[0] = { };
+
+ A (sizeof a == 0);
+
+ const char b[0] = { 0 }; // { dg-error "too many initializers" }
+
+ A (sizeof b == 0);
+
+ const char c[0] = ""; // { dg-warning "too long" }
+
+ A (sizeof c == 0);
+}
+
+
+void test_compound_zero_length (void)
+{
+ A (sizeof (const char[]){ } == 0);
+ A (sizeof (const char[0]){ } == 0);
+ A (sizeof (const char[0]){ 0 } == 0); // { dg-error "too many" }
+ A (sizeof (const char[0]){ 1 } == 0); // { dg-error "too many" }
+ A (sizeof (const char[0]){ "" } == 0); // { dg-warning "too long" }
+ A (sizeof (const char[0]){ "1" } == 0); // { dg-warning "too long" }
+}
diff --git a/gcc/testsuite/g++.dg/ipa/pr64059.C b/gcc/testsuite/g++.dg/ipa/pr64059.C
index 0269b45..5701132 100644
--- a/gcc/testsuite/g++.dg/ipa/pr64059.C
+++ b/gcc/testsuite/g++.dg/ipa/pr64059.C
@@ -1,4 +1,4 @@
-// { dg-options "-r -nostdlib -O2 -flto -fno-devirtualize" }
+// { dg-options "-r -O2 -flto -fno-devirtualize" }
// { dg-require-effective-target lto }
class A;
diff --git a/gcc/testsuite/g++.dg/lookup/name-clash12.C b/gcc/testsuite/g++.dg/lookup/name-clash12.C
new file mode 100644
index 0000000..07ed8c3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/name-clash12.C
@@ -0,0 +1,9 @@
+// PR c++/86661
+
+typedef int a; // { dg-message "declared here" }
+namespace {
+class b {
+ a c;
+ template <typename> void a(); // { dg-error "changes meaning" }
+};
+}
diff --git a/gcc/testsuite/g++.dg/lto/20081109-1_0.C b/gcc/testsuite/g++.dg/lto/20081109-1_0.C
index 3b58600..db0ba36 100644
--- a/gcc/testsuite/g++.dg/lto/20081109-1_0.C
+++ b/gcc/testsuite/g++.dg/lto/20081109-1_0.C
@@ -1,6 +1,6 @@
// { dg-lto-do link }
// { dg-require-effective-target fpic }
// { dg-lto-options {{-fPIC -flto -flto-partition=1to1}} }
-// { dg-extra-ld-options "-fPIC -flto -flto-partition=1to1 -r -nostdlib -fno-exceptions -flinker-output=nolto-rel" }
+// { dg-extra-ld-options "-fPIC -flto -flto-partition=1to1 -r -fno-exceptions -flinker-output=nolto-rel" }
void func(); class Foo { };
void bar() { try { func(); } catch (Foo) { } };
diff --git a/gcc/testsuite/g++.dg/lto/20090302_0.C b/gcc/testsuite/g++.dg/lto/20090302_0.C
index 3a61787..23e0127 100644
--- a/gcc/testsuite/g++.dg/lto/20090302_0.C
+++ b/gcc/testsuite/g++.dg/lto/20090302_0.C
@@ -1,6 +1,6 @@
/* { dg-lto-do link } */
/* { dg-require-effective-target fpic } */
-/* { dg-lto-options {{-fPIC -flto -flto-partition=1to1 -r -nostdlib}} } */
+/* { dg-lto-options {{-fPIC -flto -flto-partition=1to1 -r}} } */
/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
struct Foo {
bool Mumble();
diff --git a/gcc/testsuite/g++.dg/lto/pr45621_0.C b/gcc/testsuite/g++.dg/lto/pr45621_0.C
index f34b3b7..2055ebf 100644
--- a/gcc/testsuite/g++.dg/lto/pr45621_0.C
+++ b/gcc/testsuite/g++.dg/lto/pr45621_0.C
@@ -1,5 +1,5 @@
// { dg-lto-do assemble }
-// { dg-extra-ld-options "-O2 -fipa-cp-clone -flto -nostdlib -r -flinker-output=nolto-rel" }
+// { dg-extra-ld-options "-O2 -fipa-cp-clone -flto -r -flinker-output=nolto-rel" }
#include "pr45621.h"
void
diff --git a/gcc/testsuite/g++.dg/lto/pr60567_0.C b/gcc/testsuite/g++.dg/lto/pr60567_0.C
index 966a3c3..175b3aa 100644
--- a/gcc/testsuite/g++.dg/lto/pr60567_0.C
+++ b/gcc/testsuite/g++.dg/lto/pr60567_0.C
@@ -1,7 +1,7 @@
// PR lto/60567
// { dg-lto-do link }
// { dg-lto-options { { -flto -fno-use-linker-plugin } } }
-// { dg-extra-ld-options "-r -nostdlib" }
+// { dg-extra-ld-options "-r" }
#pragma implementation
struct S {};
diff --git a/gcc/testsuite/g++.dg/lto/pr62026.C b/gcc/testsuite/g++.dg/lto/pr62026.C
index 63766a8..0432e90 100644
--- a/gcc/testsuite/g++.dg/lto/pr62026.C
+++ b/gcc/testsuite/g++.dg/lto/pr62026.C
@@ -1,5 +1,5 @@
// { dg-lto-do link }
-// { dg-lto-options {{-flto -O3 -r -nostdlib}} }
+// { dg-lto-options {{-flto -O3 -r}} }
class C;
class F {
virtual C m_fn1();
diff --git a/gcc/testsuite/g++.dg/opt/eh1.C b/gcc/testsuite/g++.dg/opt/eh1.C
index 63a4d2e..0c3e679 100644
--- a/gcc/testsuite/g++.dg/opt/eh1.C
+++ b/gcc/testsuite/g++.dg/opt/eh1.C
@@ -1,6 +1,6 @@
// PR middle-end/14477
// { dg-do compile }
-// { dg-options "-O2 -fno-default-inline" }
+// { dg-options "-O2" }
struct A
{
diff --git a/gcc/testsuite/g++.dg/opt/mpx.C b/gcc/testsuite/g++.dg/opt/mpx.C
index 6ae0cef..201ee1b 100644
--- a/gcc/testsuite/g++.dg/opt/mpx.C
+++ b/gcc/testsuite/g++.dg/opt/mpx.C
@@ -1,5 +1,5 @@
// { dg-do compile }
// { dg-options "-fcheck-pointer-bounds -fchkp-first-field-has-own-bounds" }
-// { dg-warning "deprecated command line option .-fcheck-pointer-bounds." "" { target *-*-* } 0 }
-// { dg-warning "deprecated command line option .-fchkp-first-field-has-own-bounds." "" { target *-*-* } 0 }
+// { dg-warning ".-fcheck-pointer-bounds. is no longer supported" "" { target *-*-* } 0 }
+// { dg-warning ".-fchkp-first-field-has-own-bounds. is no longer supported" "" { target *-*-* } 0 }
diff --git a/gcc/testsuite/g++.dg/opt/pr86738.C b/gcc/testsuite/g++.dg/opt/pr86738.C
new file mode 100644
index 0000000..f5079ff
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr86738.C
@@ -0,0 +1,12 @@
+// PR c++/86738
+// { dg-do compile }
+
+struct S { int s; };
+unsigned char a[20];
+unsigned char *p = &a[(__UINTPTR_TYPE__) &((S *) 0)->s];
+
+void
+foo ()
+{
+ __builtin_memcpy (&a[15], &a[(__UINTPTR_TYPE__) &((S *) 0)->s], 2);
+}
diff --git a/gcc/testsuite/g++.dg/other/fold1.C b/gcc/testsuite/g++.dg/other/fold1.C
index 23d3454..bf07403 100644
--- a/gcc/testsuite/g++.dg/other/fold1.C
+++ b/gcc/testsuite/g++.dg/other/fold1.C
@@ -4,5 +4,5 @@
struct A
{
static const int i = i; // { dg-error "not declared" }
- int x[i]; // { dg-error "constant-expression" }
+ int x[i]; // { dg-error "constant-expression|narrowing conversion" }
};
diff --git a/gcc/testsuite/g++.dg/other/friend10.C b/gcc/testsuite/g++.dg/other/friend10.C
new file mode 100644
index 0000000..c162395
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/friend10.C
@@ -0,0 +1,9 @@
+// PR c++/59480
+
+class test {
+ friend int foo(bool = true) { return 1; } // { dg-message "14:previous" }
+ template<typename> friend int bar(bool = true) { return 1; } // { dg-message "33:previous" }
+};
+
+int foo(bool); // { dg-error "5:friend declaration" }
+template<typename> int bar(bool); // { dg-error "24:friend declaration" }
diff --git a/gcc/testsuite/g++.dg/other/friend11.C b/gcc/testsuite/g++.dg/other/friend11.C
new file mode 100644
index 0000000..b82b39d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/friend11.C
@@ -0,0 +1,8 @@
+// PR c++/59480
+
+class test {
+ friend int foo(bool = true) { return 1; } // { dg-message "14:previous" }
+ friend int foo(bool); // { dg-error "14:friend declaration" }
+ template<typename> friend int bar(bool = true) { return 1; } // { dg-message "33:previous" }
+ template<typename> friend int bar(bool); // { dg-error "33:friend declaration" }
+};
diff --git a/gcc/testsuite/g++.dg/other/friend12.C b/gcc/testsuite/g++.dg/other/friend12.C
new file mode 100644
index 0000000..b78ce4b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/friend12.C
@@ -0,0 +1,11 @@
+// PR c++/59480
+
+template<typename>
+class test {
+ friend int foo(bool = true) { return 1; } // { dg-message "14:previous" }
+ friend int foo(bool); // { dg-error "14:friend declaration" }
+ template<typename> friend int bar(bool = true) { return 1; } // { dg-message "33:previous" }
+ template<typename> friend int bar(bool); // { dg-error "33:friend declaration" }
+};
+
+template class test<bool>;
diff --git a/gcc/testsuite/g++.dg/other/friend13.C b/gcc/testsuite/g++.dg/other/friend13.C
new file mode 100644
index 0000000..6cdb322
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/friend13.C
@@ -0,0 +1,6 @@
+// PR c++/59480
+
+void f(int, int, int=0); // { dg-message "6:previous" }
+class C {
+ friend void f(int, int=0, int) {} // { dg-error "15:friend declaration" }
+};
diff --git a/gcc/testsuite/g++.dg/other/friend14.C b/gcc/testsuite/g++.dg/other/friend14.C
new file mode 100644
index 0000000..0f955a0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/friend14.C
@@ -0,0 +1,14 @@
+// PR c++/59480
+
+class Matrix;
+
+Matrix rot90 (const Matrix& a, int k = 1);
+template<typename> Matrix rot90_ (const Matrix& a, int k = 1);
+
+class Matrix {
+ friend Matrix rot90 (const Matrix&, int);
+ template<typename> friend Matrix rot90_ (const Matrix&, int);
+};
+
+Matrix rot90 (const Matrix& a, int k) { return Matrix(); }
+template<typename> Matrix rot90_ (const Matrix& a, int k) { return Matrix(); }
diff --git a/gcc/testsuite/g++.dg/other/friend15.C b/gcc/testsuite/g++.dg/other/friend15.C
new file mode 100644
index 0000000..7f31811
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/friend15.C
@@ -0,0 +1,14 @@
+// PR c++/59480
+
+class Matrix;
+
+void rot90 (const Matrix& a, int k = 1) { }
+template<typename> void rot90_ (const Matrix& a, int k = 1) { }
+
+class Matrix {
+ friend void rot90 (const Matrix&, int);
+ template<typename> friend void rot90_ (const Matrix&, int);
+};
+
+void rot90 (const Matrix& a, int k);
+template<typename> void rot90_ (const Matrix& a, int k);
diff --git a/gcc/testsuite/g++.dg/other/friend8.C b/gcc/testsuite/g++.dg/other/friend8.C
new file mode 100644
index 0000000..6b5df88
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/friend8.C
@@ -0,0 +1,6 @@
+// PR c++/59480
+
+class test {
+ friend int foo(bool = true); // { dg-error "14:friend declaration" }
+ template<typename> friend int bar(bool = true); // { dg-error "33:friend declaration" }
+};
diff --git a/gcc/testsuite/g++.dg/other/friend9.C b/gcc/testsuite/g++.dg/other/friend9.C
new file mode 100644
index 0000000..16b4f57
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/friend9.C
@@ -0,0 +1,9 @@
+// PR c++/59480
+
+template<typename>
+class test {
+ friend int foo(bool = true); // { dg-error "14:friend declaration" }
+ template<typename> friend int bar(bool = true); // { dg-error "33:friend declaration" }
+};
+
+template class test<bool>;
diff --git a/gcc/testsuite/g++.dg/other/switch4.C b/gcc/testsuite/g++.dg/other/switch4.C
new file mode 100644
index 0000000..42acb1b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/switch4.C
@@ -0,0 +1,6 @@
+// PR c++/86546
+
+class a b; // { dg-error "aggregate" }
+void c() {
+ switch () // { dg-error "expected" }
+ case b // { dg-error "expected" }
diff --git a/gcc/testsuite/g++.dg/other/vrp1.C b/gcc/testsuite/g++.dg/other/vrp1.C
index 0a798c9..466a15b 100644
--- a/gcc/testsuite/g++.dg/other/vrp1.C
+++ b/gcc/testsuite/g++.dg/other/vrp1.C
@@ -9,4 +9,4 @@ long long mod (long long l, long long r)
return 0LL;
return l % r;
}
-template long long mod<-0x8000000000000000LL> (long long, long long);
+template long long mod<-0x8000000000000000LL> (long long, long long); // { dg-error "template-id" "" { target { c++11 } } }
diff --git a/gcc/testsuite/g++.dg/parse/array-size2.C b/gcc/testsuite/g++.dg/parse/array-size2.C
index d0bc47f..997b95e 100644
--- a/gcc/testsuite/g++.dg/parse/array-size2.C
+++ b/gcc/testsuite/g++.dg/parse/array-size2.C
@@ -14,7 +14,7 @@ extern void bar (char *, char *);
void
foo (void)
{
- char g[(char *) &((struct S *) 0)->b - (char *) 0]; // { dg-error "constant" }
+ char g[(char *) &((struct S *) 0)->b - (char *) 0]; // { dg-error "constant|narrowing conversion" }
char h[(__SIZE_TYPE__) &((struct S *) 8)->b]; // { dg-error "constant" }
bar (g, h);
}
diff --git a/gcc/testsuite/g++.dg/parse/defarg4.C b/gcc/testsuite/g++.dg/parse/defarg4.C
index 151f6c5..ad8a1ed 100644
--- a/gcc/testsuite/g++.dg/parse/defarg4.C
+++ b/gcc/testsuite/g++.dg/parse/defarg4.C
@@ -1,4 +1,4 @@
-// { dg-do compile }
+// { dg-options "-fpermissive -w" }
// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 3 Jul 2003 <nathan@codesourcery.com>
diff --git a/gcc/testsuite/g++.dg/parse/defarg8.C b/gcc/testsuite/g++.dg/parse/defarg8.C
index 1f1f078..3310006 100644
--- a/gcc/testsuite/g++.dg/parse/defarg8.C
+++ b/gcc/testsuite/g++.dg/parse/defarg8.C
@@ -1,3 +1,5 @@
+// { dg-options "-fpermissive -w" }
+
struct A {
static void g(int);
};
diff --git a/gcc/testsuite/g++.dg/parse/error61.C b/gcc/testsuite/g++.dg/parse/error61.C
index 199e1aa..272626b 100644
--- a/gcc/testsuite/g++.dg/parse/error61.C
+++ b/gcc/testsuite/g++.dg/parse/error61.C
@@ -4,8 +4,8 @@
template<int> void foo()
{
int x[8];
- for (int& i, j : x) // { dg-error "multiple" }
- i = 0; // { dg-error "local variable" }
+ for (int& i, j : x) // { dg-error "multiple|reference" }
+ i = 0;
}
void bar()
diff --git a/gcc/testsuite/g++.dg/plugin/plugin.exp b/gcc/testsuite/g++.dg/plugin/plugin.exp
index 451c4a9..d9f54ab 100644
--- a/gcc/testsuite/g++.dg/plugin/plugin.exp
+++ b/gcc/testsuite/g++.dg/plugin/plugin.exp
@@ -69,6 +69,7 @@ set plugin_test_list [list \
diagnostic-test-inlining-1.C } \
{ show_template_tree_color_plugin.c \
show-template-tree-color.C \
+ show-template-tree-color-labels.C \
show-template-tree-color-no-elide-type.C } \
{ comment_plugin.c comments-1.C } \
]
diff --git a/gcc/testsuite/g++.dg/plugin/show-template-tree-color-labels.C b/gcc/testsuite/g++.dg/plugin/show-template-tree-color-labels.C
new file mode 100644
index 0000000..462e1bd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/plugin/show-template-tree-color-labels.C
@@ -0,0 +1,38 @@
+/* Verify colorization of the labels in diagnostic-show-locus.c
+ for template comparisons.
+ Doing so requires a plugin; see the comments in the plugin for the
+ rationale. */
+
+// { dg-options "-fdiagnostics-color=always -fdiagnostics-show-caret" }
+
+template<typename> struct vector {};
+template<typename, typename> struct map {};
+
+void fn_1(vector<int>);
+void fn_2(map<int, int>);
+
+void test_1 (vector<double> vec)
+{
+ fn_1 (vec);
+ /* { dg-begin-multiline-output "" }
+could not convert 'vec' from 'vector<double>' to 'vector<int>'
+ fn_1 (vec);
+ ^~~
+ |
+ vector<double>
+ { dg-end-multiline-output "" } */
+ // TODO: we don't yet highlight the mismatching part with color
+}
+
+void test_2 (const map<int, double> &m)
+{
+ fn_2 (m);
+ /* { dg-begin-multiline-output "" }
+could not convert 'm' from 'map<[...],double>' to 'map<[...],int>'
+ fn_2 (m);
+ ^
+ |
+ map<[...],double>
+ { dg-end-multiline-output "" } */
+ // TODO: we don't yet highlight the mismatching part with color
+}
diff --git a/gcc/testsuite/g++.dg/pr61941.C b/gcc/testsuite/g++.dg/pr61941.C
new file mode 100644
index 0000000..5485b98
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr61941.C
@@ -0,0 +1,12 @@
+// PR c++/61941 - Misparsing of warn_unused_result function with ref-qualifiers
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wall" }
+
+class S
+{
+public:
+ S x() const __attribute__ ((__warn_unused_result__));
+
+ S y() const & __attribute__ ((__warn_unused_result__));
+ S y() && __attribute__ ((__warn_unused_result__));
+};
diff --git a/gcc/testsuite/g++.dg/pr83239.C b/gcc/testsuite/g++.dg/pr83239.C
index b0f31be..bf6be7a 100644
--- a/gcc/testsuite/g++.dg/pr83239.C
+++ b/gcc/testsuite/g++.dg/pr83239.C
@@ -1,7 +1,7 @@
// PR tree-optimization/83239 - False positive from -Wstringop-overflow
// on simple std::vector code
// { dg-do compile }
-// { dg-options "-O3 -Wall -fdump-tree-optimized" }
+// { dg-options "-O3 -finline-limit=500 -Wall -fdump-tree-optimized" }
#include <vector>
diff --git a/gcc/testsuite/g++.dg/pr85523.C b/gcc/testsuite/g++.dg/pr85523.C
new file mode 100644
index 0000000..0ed16ff
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr85523.C
@@ -0,0 +1,91 @@
+/* { dg-options "-fdiagnostics-show-caret" } */
+
+/* Verify that we emit a "return *this;" fix-it hint for
+ a missing return in an assignment operator. */
+
+struct s1 {
+ s1& operator=(const s1&) { } // { dg-warning "no return statement in function returning non-void" }
+ /* { dg-begin-multiline-output "" }
+ s1& operator=(const s1&) { }
+ ^
+ return *this;
+ { dg-end-multiline-output "" } */
+};
+
+/* Likewise for +=. */
+
+struct s2 {
+ s2& operator+=(const s2&) {} // { dg-warning "no return statement in function returning non-void" }
+ /* { dg-begin-multiline-output "" }
+ s2& operator+=(const s2&) {}
+ ^
+ return *this;
+ { dg-end-multiline-output "" } */
+};
+
+/* No warning for "void" return. */
+
+struct s3 {
+ void operator=(const s3&) { }
+};
+
+/* We shouldn't issue the fix-it hint if the return type isn't right. */
+
+struct s4 {
+ int operator=(int) { } // { dg-warning "no return statement in function returning non-void" }
+ /* { dg-begin-multiline-output "" }
+ int operator=(int) { }
+ ^
+ { dg-end-multiline-output "" } */
+};
+
+/* Example of a multi-line fix-it hint. */
+
+struct s5 {
+ int i;
+ s5& operator=(const s5& z) {
+ i = z.i;
+ } // { dg-warning "no return statement in function returning non-void" }
+ /* { dg-begin-multiline-output "" }
+ i = z.i;
++ return *this;
+ }
+ ^
+ { dg-end-multiline-output "" } */
+};
+
+/* Example of a multi-line fix-it hint with other statements. */
+
+extern void log (const char *);
+struct s6 {
+ int i;
+ s6& operator=(const s6& z) {
+ log ("operator=\n");
+ i = z.i;
+ } // { dg-warning "no return statement in function returning non-void" }
+ /* { dg-begin-multiline-output "" }
+ i = z.i;
++ return *this;
+ }
+ ^
+ { dg-end-multiline-output "" } */
+};
+
+/* Another example of a multi-line fix-it hint with other statements. */
+
+struct s7 {
+ int i;
+ s7& operator=(const s6& z) {
+ if (z.i)
+ log ("operator=\n");
+ else
+ log ("operator=\n");
+ i = z.i;
+ } // { dg-warning "no return statement in function returning non-void" }
+ /* { dg-begin-multiline-output "" }
+ i = z.i;
++ return *this;
+ }
+ ^
+ { dg-end-multiline-output "" } */
+};
diff --git a/gcc/testsuite/g++.dg/pr86593.C b/gcc/testsuite/g++.dg/pr86593.C
new file mode 100644
index 0000000..feed8c3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr86593.C
@@ -0,0 +1,11 @@
+// { dg-options "-O -g -fno-omit-frame-pointer" }
+
+struct Foo
+{
+ int bar(int a, int b, int c, int i1, int i2, int i3, int d);
+};
+
+int Foo::bar(int a, int b, int c, int i1, int i2, int i3, int d)
+{
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/pr86988.C b/gcc/testsuite/g++.dg/pr86988.C
new file mode 100644
index 0000000..62fb0f3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr86988.C
@@ -0,0 +1,16 @@
+// { dg-do compile }
+// { dg-options "-O2 -Warray-bounds" }
+
+struct R { int r; };
+void baz (char *, char *, char *, char *);
+
+void
+foo ()
+{
+ const R a = { 12 };
+ char b[1][a.r] = { { "12345678901" } };
+ char c[a.r] = { "12345678901" };
+ char d[1][a.r] = { { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '\0' } };
+ char e[a.r] = { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '\0' };
+ baz (b[0], c, d[0], e);
+}
diff --git a/gcc/testsuite/g++.dg/pr87185.C b/gcc/testsuite/g++.dg/pr87185.C
new file mode 100644
index 0000000..46dae0e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr87185.C
@@ -0,0 +1,4 @@
+// PR c++/87185
+// { dg-do compile { target c++11 } }
+
+void f() { const int i=0; [&]() noexcept {i;}; }
diff --git a/gcc/testsuite/g++.dg/predict-1.C b/gcc/testsuite/g++.dg/predict-1.C
new file mode 100644
index 0000000..8e2032f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/predict-1.C
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-profile_estimate" } */
+
+#include <new>
+
+int *r;
+
+void test()
+{
+ r = new(std::nothrow) int;
+ if (r)
+ __builtin_memset (r, 0, sizeof(int));
+}
+
+/* { dg-final { scan-tree-dump "malloc returned non-NULL heuristics of edge\[^:\]*: 99.96%" "profile_estimate"} } */
diff --git a/gcc/testsuite/g++.dg/recip_sqrt_mult_1.C b/gcc/testsuite/g++.dg/recip_sqrt_mult_1.C
new file mode 100644
index 0000000..11d9c6f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/recip_sqrt_mult_1.C
@@ -0,0 +1,49 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fnon-call-exceptions -fdump-tree-recip" } */
+
+double res, res2, tmp;
+void
+foo1 (double a, double b)
+{
+ try {
+ tmp = 1.0 / __builtin_sqrt (a);
+ res = tmp * tmp;
+ res2 = a * tmp;
+ }
+ catch (...)
+ { ; }
+}
+
+void
+foo4 (double a, double b, int c, int d)
+{
+ try {
+ tmp = 1.0 / __builtin_sqrt (a);
+ }
+ catch (...)
+ {
+ if (c)
+ res = tmp * tmp;
+
+ if (d)
+ res2 = a * tmp;
+ }
+}
+
+void
+foo5 (double a, double b, int c, int d)
+{
+ try {
+ tmp = 1.0 / __builtin_sqrt (a);
+ res = tmp * tmp;
+
+ if (d)
+ res2 = a * tmp;
+ }
+ catch (...)
+ { ; }
+}
+
+/* { dg-final { scan-tree-dump-times "Optimizing reciprocal sqrt multiplications" 2 "recip" } } */
+/* { dg-final { scan-tree-dump-times "Replacing squaring multiplication" 2 "recip" } } */
+/* { dg-final { scan-tree-dump-times "Replacing original division" 2 "recip" } } */
diff --git a/gcc/testsuite/g++.dg/recip_sqrt_mult_2.C b/gcc/testsuite/g++.dg/recip_sqrt_mult_2.C
new file mode 100644
index 0000000..cca12ca
--- /dev/null
+++ b/gcc/testsuite/g++.dg/recip_sqrt_mult_2.C
@@ -0,0 +1,49 @@
+/* { dg-do compile } */
+/* { dg-options "-w -Ofast -fnon-call-exceptions -ftrapping-math -fdump-tree-recip" } */
+
+/* Check that the recip_sqrt optimization does not trigger here, causing an
+ ICE due to EH info. */
+
+
+double res, res2, tmp;
+void
+foo1 (double a, double b)
+{
+ try {
+ tmp = 1.0 / __builtin_sqrt (a);
+ res = tmp * tmp;
+ res2 = a * tmp;
+ }
+ catch (...)
+ { ; }
+}
+
+void
+foo4 (double a, double b, int c, int d)
+{
+ try {
+ tmp = 1.0 / __builtin_sqrt (a);
+ }
+ catch (...)
+ {
+ if (c)
+ res = tmp * tmp;
+
+ if (d)
+ res2 = a * tmp;
+ }
+}
+
+void
+foo5 (double a, double b, int c, int d)
+{
+ try {
+ tmp = 1.0 / __builtin_sqrt (a);
+ res = tmp * tmp;
+
+ if (d)
+ res2 = a * tmp;
+ }
+ catch (...)
+ { ; }
+}
diff --git a/gcc/testsuite/g++.dg/template/char1.C b/gcc/testsuite/g++.dg/template/char1.C
index 51e72e7..a6cffaa 100644
--- a/gcc/testsuite/g++.dg/template/char1.C
+++ b/gcc/testsuite/g++.dg/template/char1.C
@@ -1,4 +1,5 @@
template <class CharType, CharType line_terminator = 0>
class String {};
-String<signed char, 255> s; // { dg-warning "overflow" }
+String<signed char, 255> s; // { dg-error "narrowing conversion" "" { target c++11 } }
+// { dg-warning "overflow" "" { target c++98_only } .-1 }
diff --git a/gcc/testsuite/g++.dg/template/crash84.C b/gcc/testsuite/g++.dg/template/crash84.C
index b3099d9..f90cf5c 100644
--- a/gcc/testsuite/g++.dg/template/crash84.C
+++ b/gcc/testsuite/g++.dg/template/crash84.C
@@ -14,7 +14,7 @@ void
foo ()
{
a<int> a1; // OK
- a<int>::b<a,int> b1; // { dg-error "template argument|converted constant" }
+ a<int>::b<a,int> b1; // { dg-error "template argument|convert" }
}
// { dg-prune-output "invalid type in declaration" }
diff --git a/gcc/testsuite/g++.dg/template/dependent-name3.C b/gcc/testsuite/g++.dg/template/dependent-name3.C
index bbe6fb6..f9d1405 100644
--- a/gcc/testsuite/g++.dg/template/dependent-name3.C
+++ b/gcc/testsuite/g++.dg/template/dependent-name3.C
@@ -11,7 +11,7 @@ template<int I> struct A
template<int N> struct B
{
int x[A<N>::zero]; // { dg-error "zero" }
- int y[A<N>::minus_one]; // { dg-error "negative" }
+ int y[A<N>::minus_one]; // { dg-error "size of array|narrowing conversion" }
};
B<0> b;
diff --git a/gcc/testsuite/g++.dg/template/inline1.C b/gcc/testsuite/g++.dg/template/inline1.C
index c7ae1f5..f941e6c 100644
--- a/gcc/testsuite/g++.dg/template/inline1.C
+++ b/gcc/testsuite/g++.dg/template/inline1.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-fno-default-inline -O0" }
+// { dg-options "-O0" }
// { dg-final { scan-assembler-not "\n_?_ZN1X3FooIiEEvT_\[: \t\n\]" } }
// Copyright (C) 2003 Free Software Foundation, Inc.
diff --git a/gcc/testsuite/g++.dg/template/pr86706.C b/gcc/testsuite/g++.dg/template/pr86706.C
new file mode 100644
index 0000000..86af18a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr86706.C
@@ -0,0 +1,16 @@
+// PR c++/86706
+// { dg-do compile }
+
+class A { int b; };
+
+template <class, typename>
+class C : A { C (); static C *f; };
+
+template <class T, typename U>
+C<T, U> *C<T, U>::f;
+
+template <class T, typename U>
+C<T, U>::C ()
+{
+ f->b;
+}
diff --git a/gcc/testsuite/g++.dg/template/ptrmem20.C b/gcc/testsuite/g++.dg/template/ptrmem20.C
index e17ed84..74713a7 100644
--- a/gcc/testsuite/g++.dg/template/ptrmem20.C
+++ b/gcc/testsuite/g++.dg/template/ptrmem20.C
@@ -12,5 +12,5 @@ template<void (A::*)()> void bar(); // { dg-message "note" }
void baz()
{
- bar<&B::foo>(); // { dg-error "template argument|no match" }
+ bar<&B::foo>(); // { dg-error "template argument|no match|convert" }
}
diff --git a/gcc/testsuite/g++.dg/template/ptrmem8.C b/gcc/testsuite/g++.dg/template/ptrmem8.C
index b759b70..4e9fab0 100644
--- a/gcc/testsuite/g++.dg/template/ptrmem8.C
+++ b/gcc/testsuite/g++.dg/template/ptrmem8.C
@@ -15,8 +15,8 @@ template <int (D::*fun)() const> int Get(); // { dg-message "note" }
int main ()
{
- Get<&B::I>(); // { dg-error "template argument|converted constant" "not valid" }
+ Get<&B::I>(); // { dg-error "template argument|convert" "not valid" }
// { dg-error "no match" "no match" { target *-*-* } .-1 }
- Get<&D::I>(); // { dg-error "template argument|converted constant" "not valid" }
+ Get<&D::I>(); // { dg-error "template argument|convert" "not valid" }
// { dg-error "no match" "no match" { target *-*-* } .-1 }
}
diff --git a/gcc/testsuite/g++.dg/torture/20180705-1.C b/gcc/testsuite/g++.dg/torture/20180705-1.C
new file mode 100644
index 0000000..8460473
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/20180705-1.C
@@ -0,0 +1,30 @@
+// { dg-do compile }
+
+typedef long unsigned int size_t;
+extern void fancy_abort () __attribute__ ((__noreturn__));
+class cpp_string_location_reader { };
+class cpp_substring_ranges {
+public:
+ void add_range ();
+};
+typedef unsigned char uchar;
+void
+cpp_interpret_string_1 (size_t count, cpp_string_location_reader *loc_readers, cpp_substring_ranges *ranges, uchar c, const uchar *p)
+{
+ size_t i;
+ ((void)(!((loc_readers != __null ) == (ranges != __null )) ? fancy_abort (), 0 : 0));
+ cpp_string_location_reader *loc_reader = __null;
+ for (i = 0; i < count; i++)
+ {
+ if (loc_readers) loc_reader = &loc_readers[i];
+ if (*p == 'R') continue;
+ for (;;)
+ {
+ switch (c) {
+ case 'x': if (ranges) ranges->add_range (); break;
+ case '7': ((void)(!((loc_reader != __null ) == (ranges != __null )) ? fancy_abort (), 0 : 0)); break;
+ }
+ p = 0;
+ }
+ }
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr44295.C b/gcc/testsuite/g++.dg/torture/pr44295.C
index 7525dc4..a2edf63 100644
--- a/gcc/testsuite/g++.dg/torture/pr44295.C
+++ b/gcc/testsuite/g++.dg/torture/pr44295.C
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-additional-options "-Wno-return-type" } */
+/* { dg-skip-if "no pthread_barrier" { *-*-darwin* } } */
extern "C" {
typedef __SIZE_TYPE__ size_t;
diff --git a/gcc/testsuite/g++.dg/torture/pr86763.C b/gcc/testsuite/g++.dg/torture/pr86763.C
new file mode 100644
index 0000000..8455ac9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr86763.C
@@ -0,0 +1,37 @@
+// { dg-do run { target { *-*-linux* } } }
+// { dg-additional-options "-fschedule-insns2 -fstrict-aliasing" }
+// { dg-additional-options "-lrt" }
+
+#include <cstdint>
+#include <cassert>
+#include <time.h>
+struct ID {
+ uint64_t value;
+};
+uint64_t value(ID id) { return id.value; }
+uint64_t gen { 1000 };
+struct Msg {
+ uint64_t time;
+ ID id;
+};
+struct V {
+ V() { }
+ V(Msg const & msg) : msg(msg) { }
+ Msg & get() { return msg; }
+ Msg msg;
+ char pad[237 - sizeof(Msg)];
+};
+struct T : V { using V::V; };
+Msg init_msg() {
+ Msg msg;
+ timespec t;
+ clock_gettime(CLOCK_REALTIME, &t);
+ msg.time = t.tv_sec + t.tv_nsec;
+ msg.id.value = ++gen;
+ return msg;
+}
+int main() {
+ T t;
+ t = init_msg();
+ assert(value(t.get().id) == 1001);
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr86816.C b/gcc/testsuite/g++.dg/torture/pr86816.C
new file mode 100644
index 0000000..604a7d4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr86816.C
@@ -0,0 +1,42 @@
+// { dg-do compile }
+
+class Signal
+{
+public:
+ int m_Mode;
+};
+
+class Ctx
+{
+public:
+ bool m_Invert;
+
+ void DoSomething();
+};
+
+class Test
+{
+ void TestIce( Ctx& ctx, Signal* sig);
+};
+
+void Test::TestIce( Ctx& ctx, Signal* sig)
+{
+ int invert = false;
+
+ if( ! ctx.m_Invert)
+ invert = ! invert;
+
+ switch( sig->m_Mode)
+ {
+ case 1:
+ invert = ! invert;
+ break;
+
+ case 2:
+ invert = true;
+ break;
+ }
+
+ if( invert)
+ ctx.DoSomething();
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr87014.C b/gcc/testsuite/g++.dg/torture/pr87014.C
new file mode 100644
index 0000000..614954e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr87014.C
@@ -0,0 +1,37 @@
+// { dg-do run }
+
+void
+fillstack ()
+{
+ long long foo[] =
+ {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ };
+}
+
+void
+f (long long=-1,long long=-1,long long=-1,long long=-1,
+ long long=-1,long long=-1,long long arg7_on_stack=-1)
+{
+ throw 0;
+}
+
+void
+g()
+{
+ try
+ {
+ f ();
+ }
+ catch (int)
+ {
+ }
+}
+
+int
+main()
+{
+ fillstack ();
+ g ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr87124.C b/gcc/testsuite/g++.dg/torture/pr87124.C
new file mode 100644
index 0000000..3e7d480
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr87124.C
@@ -0,0 +1,12 @@
+// { dg-do compile }
+
+class A {
+ void m_fn1();
+};
+
+void A::m_fn1()
+{
+ A *a = this;
+ for (int i; i && a;)
+ a = 0;
+}
diff --git a/gcc/testsuite/g++.dg/torture/type-generic-1.C b/gcc/testsuite/g++.dg/torture/type-generic-1.C
index 4d82592..7708724 100644
--- a/gcc/testsuite/g++.dg/torture/type-generic-1.C
+++ b/gcc/testsuite/g++.dg/torture/type-generic-1.C
@@ -4,6 +4,7 @@
/* { dg-do run } */
/* { dg-add-options ieee } */
/* { dg-skip-if "No Inf/NaN support" { spu-*-* } } */
+/* { dg-skip-if "No subnormal support" { csky-*-* } { "-mhard-float" } } */
#include "../../gcc.dg/tg-tests.h"
diff --git a/gcc/testsuite/g++.dg/tree-ssa/lifetime-dse1.C b/gcc/testsuite/g++.dg/tree-ssa/lifetime-dse1.C
index 90c90f2..0b7451d 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/lifetime-dse1.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/lifetime-dse1.C
@@ -1,5 +1,5 @@
// PR c++/61982
-// { dg-additional-options "-O2 -fdump-tree-optimized" }
+// { dg-additional-options "-O2 -fdump-tree-optimized -fdelete-null-pointer-checks" }
// { dg-final { scan-tree-dump-not "= 0" "optimized" } }
struct X {
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr61034.C b/gcc/testsuite/g++.dg/tree-ssa/pr61034.C
index 023655b..870b237 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr61034.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr61034.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-O2 -fdump-tree-fre3 -fdump-tree-optimized" }
+// { dg-options "-O2 -fdump-tree-fre3 -fdump-tree-optimized -fdelete-null-pointer-checks" }
#define assume(x) if(!(x))__builtin_unreachable()
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr81408.C b/gcc/testsuite/g++.dg/tree-ssa/pr81408.C
index 60e6e52..89d6e55 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr81408.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr81408.C
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -std=gnu++11 -fopt-info-loop-missed -Wunsafe-loop-optimizations" } */
+/* { dg-options "-O2 -std=gnu++11 -fopt-info-loop-missed" } */
struct p
{
char *ay;
diff --git a/gcc/testsuite/g++.dg/ubsan/vptr-13.C b/gcc/testsuite/g++.dg/ubsan/vptr-13.C
new file mode 100644
index 0000000..345581f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/vptr-13.C
@@ -0,0 +1,19 @@
+// PR c++/87095
+// { dg-do run }
+// { dg-options "-fsanitize=vptr -fno-sanitize-recover=vptr" }
+
+struct A
+{
+ virtual ~A () {}
+};
+
+struct B : virtual A {};
+
+struct C : B {};
+
+int
+main ()
+{
+ C c;
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wclass-conversion1.C b/gcc/testsuite/g++.dg/warn/Wclass-conversion1.C
new file mode 100644
index 0000000..2599a53
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wclass-conversion1.C
@@ -0,0 +1,19 @@
+// PR c++/87357
+// { dg-do compile }
+
+struct B { };
+
+struct X : public B {
+ operator X(); // { dg-warning "3:converting .X. to the same type will never use a type conversion operator" }
+ operator X&(); // { dg-warning "3:converting .X. to a reference to the same type will never use a type conversion operator" }
+ operator X() const; // { dg-warning "3:converting .X. to the same type will never use a type conversion operator" }
+ operator const X(); // { dg-warning "3:converting .X. to the same type will never use a type conversion operator" }
+
+ operator B(); // { dg-warning "3:converting .X. to a base class .B. will never use a type conversion operator" }
+ operator B&(); // { dg-warning "3:converting .X. to a reference to a base class .B. will never use a type conversion operator" }
+ operator B() const; // { dg-warning "3:converting .X. to a base class .B. will never use a type conversion operator" }
+ operator const B(); // { dg-warning "3:converting .X. to a base class .const B. will never use a type conversion operator" }
+
+ operator void(); // { dg-warning "3:converting .X. to .void. will never use a type conversion operator" }
+ operator void() const; // { dg-warning "3:converting .X. to .void. will never use a type conversion operator" }
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wclass-conversion2.C b/gcc/testsuite/g++.dg/warn/Wclass-conversion2.C
new file mode 100644
index 0000000..b6919f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wclass-conversion2.C
@@ -0,0 +1,20 @@
+// PR c++/87357
+// { dg-do compile }
+// { dg-options "-Wno-class-conversion" }
+
+struct B { };
+
+struct X : public B {
+ operator X(); // { dg-bogus "3:converting .X. to the same type will never use a type conversion operator" }
+ operator X&(); // { dg-bogus "3:converting .X. to a reference to the same type will never use a type conversion operator" }
+ operator X() const; // { dg-bogus "3:converting .X. to the same type will never use a type conversion operator" }
+ operator const X(); // { dg-bogus "3:converting .X. to the same type will never use a type conversion operator" }
+
+ operator B(); // { dg-bogus "3:converting .X. to a base class .B. will never use a type conversion operator" }
+ operator B&(); // { dg-bogus "3:converting .X. to a reference to a base class .B. will never use a type conversion operator" }
+ operator B() const; // { dg-bogus "3:converting .X. to a base class .B. will never use a type conversion operator" }
+ operator const B(); // { dg-bogus "3:converting .X. to a base class .const B. will never use a type conversion operator" }
+
+ operator void(); // { dg-bogus "3:converting .X. to .void. will never use a type conversion operator" }
+ operator void() const; // { dg-bogus "3:converting .X. to .void. will never use a type conversion operator" }
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-5.C b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-5.C
new file mode 100644
index 0000000..7609627
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-5.C
@@ -0,0 +1,8 @@
+// PR c++/86982
+// { dg-do compile { target c++11 } }
+
+#include <utility>
+
+int&& f() { int i = 0; return std::move(i); } // { dg-warning "reference to local variable" }
+int&& g() { int i = 0; return std::forward<int>(i); } // { dg-warning "reference to local variable" }
+int&& h() { long l = 0; return std::forward<int>(l); } // { dg-warning "reference to temporary" }
diff --git a/gcc/testsuite/g++.dg/warn/Wunreachable-code-1.C b/gcc/testsuite/g++.dg/warn/Wunreachable-code-1.C
deleted file mode 100644
index 23fc86d..0000000
--- a/gcc/testsuite/g++.dg/warn/Wunreachable-code-1.C
+++ /dev/null
@@ -1,22 +0,0 @@
-/* PR17544 Incorrect -Wunreachable-code warning
- Origin: sebor@roguewave.com
-
- G++ appends a "return 0;" when finishing a function, but it was not
- given a source location. The gimplifier thinks a return statement
- needs a locus so it would add one, making the compiler generated code
- visible to the unreachable code warning. */
-
-/* { dg-do compile } */
-/* { dg-options "-O -Wunreachable-code" } */
-
-int
-main (int argc, char *argv[])
-{
- const char* const s = argc < 2 ? "" : argv [1];
- int i = 0;
- do {
- ++i;
- } while (i < s [0]);
- return i;
-}
-
diff --git a/gcc/testsuite/g++.dg/warn/Wunreachable-code-2.C b/gcc/testsuite/g++.dg/warn/Wunreachable-code-2.C
deleted file mode 100644
index d50f7fe..0000000
--- a/gcc/testsuite/g++.dg/warn/Wunreachable-code-2.C
+++ /dev/null
@@ -1,23 +0,0 @@
-// PR c++/21228
-/* { dg-options "-Wunreachable-code" } */
-
-class testStringBase
-{
-public:
- char *stringPtr;
-};
-
-class testString : public testStringBase
-{
-public:
- testString();
-};
-
-testString::testString()
-{
- stringPtr = (char *) 9;
-}
-
-int main(int argc, char **argv) {
- testString s;
-}
diff --git a/gcc/testsuite/g++.dg/warn/conversion-function-1.C b/gcc/testsuite/g++.dg/warn/conversion-function-1.C
index 878011c..890719b 100644
--- a/gcc/testsuite/g++.dg/warn/conversion-function-1.C
+++ b/gcc/testsuite/g++.dg/warn/conversion-function-1.C
@@ -1,6 +1,6 @@
// Copyright (C) 2003 Free Software Foundation
// Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
-// { dg-options "-Wno-conversion" }
+// { dg-options "-Wno-class-conversion" }
struct A {
operator A&();
diff --git a/gcc/testsuite/g++.dg/warn/pr31246-2.C b/gcc/testsuite/g++.dg/warn/pr31246-2.C
deleted file mode 100644
index c9a4cae..0000000
--- a/gcc/testsuite/g++.dg/warn/pr31246-2.C
+++ /dev/null
@@ -1,9 +0,0 @@
-// PR 31246
-// { dg-do compile }
-// { dg-options "-Wunreachable-code" }
-#include <new>
-
-int* get_ptr(void* ptr)
-{
- return new(ptr) int();
-}
diff --git a/gcc/testsuite/g++.dg/warn/pr31246.C b/gcc/testsuite/g++.dg/warn/pr31246.C
deleted file mode 100644
index f3603af..0000000
--- a/gcc/testsuite/g++.dg/warn/pr31246.C
+++ /dev/null
@@ -1,9 +0,0 @@
-// PR 31246
-// { dg-do compile }
-// { dg-options "-Wunreachable-code -D_GLIBCXX_DEBUG" }
-#include <vector>
-
-int main()
-{
- std::vector<int>::iterator a;
-}
diff --git a/gcc/testsuite/g++.dg/warn/pr86881.C b/gcc/testsuite/g++.dg/warn/pr86881.C
new file mode 100644
index 0000000..6ce17e8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/pr86881.C
@@ -0,0 +1,20 @@
+// PR c++/86881 ICE with shadow warning
+// { dg-do compile { target c++11 } }
+// { dg-additional-options { -Wshadow-compatible-local } }}
+
+void a() {
+ auto b([] {});
+ {
+ auto b = 0;
+ }
+}
+
+struct Proxy { };
+
+void Two ()
+{
+ auto my = Proxy ();
+ {
+ auto my = Proxy (); // { dg-warning "shadows" "" { xfail *-*-* } }
+ };
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900215_01.C b/gcc/testsuite/g++.old-deja/g++.bugs/900215_01.C
index 0cd9b32..fd07568 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900215_01.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900215_01.C
@@ -24,7 +24,7 @@
struct struct0 {
- operator void (); // { dg-warning "3:conversion to void will never use a type conversion operator" }
+ operator void (); // { dg-warning "3:converting .struct0. to .void. will never use a type conversion operator" }
};
int exit_status = 1;
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900330_02.C b/gcc/testsuite/g++.old-deja/g++.bugs/900330_02.C
index 588251d..f1591b2 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900330_02.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900330_02.C
@@ -24,7 +24,7 @@ struct D : public B {
void h(D* pd)
{
- pd->f(1); // { dg-error "no matching" } D::f(struct B) hides B::f(int)
+ pd->f(1); // { dg-error "cannot convert" } D::f(struct B) hides B::f(int)
}
int main () { return 0; }
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/conversion11.C b/gcc/testsuite/g++.old-deja/g++.jason/conversion11.C
index a7c0fbe..ccbd1f5 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/conversion11.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/conversion11.C
@@ -22,6 +22,6 @@ void DoSomething(Ding A);
void foo(Something* pX)
{
DoSomething(1); // { dg-error "could not convert" }
- pX->DoSomething(1); // { dg-error "no matching" }
- (*pX).DoSomething(1); // { dg-error "no matching" }
+ pX->DoSomething(1); // { dg-error "cannot convert" }
+ (*pX).DoSomething(1); // { dg-error "cannot convert" }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/conversion5.C b/gcc/testsuite/g++.old-deja/g++.jason/conversion5.C
index a9531a6..7f04de4 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/conversion5.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/conversion5.C
@@ -3,7 +3,7 @@
struct A { };
struct B: public A {
A a;
- operator A () { return a; } // { dg-warning "3:conversion to a base class will never use a type conversion operator" }
+ operator A () { return a; } // { dg-warning "3:converting .B. to a base class .A. will never use a type conversion operator" }
};
void f (const A&);
void g()
diff --git a/gcc/testsuite/g++.old-deja/g++.law/arg11.C b/gcc/testsuite/g++.old-deja/g++.law/arg11.C
index bd88844..d68f184 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/arg11.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/arg11.C
@@ -17,6 +17,6 @@ int
foo(S *o)
{ // Neither call has a usable constructor for conversions of char[5] to Ack.
function("adsf");// { dg-error "could not convert" }
- o->method("adsf");// { dg-error "no matching" }
+ o->method("adsf");// { dg-error "cannot convert" }
return 0;
}
diff --git a/gcc/testsuite/g++.old-deja/g++.law/arm9.C b/gcc/testsuite/g++.old-deja/g++.law/arm9.C
index c603aab..ab18189 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/arm9.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/arm9.C
@@ -23,7 +23,7 @@ void B::set (f2 f) { std::cout << "called B\n|no known conversion";} // { dg-mes
int main() {
B b;
- b.set(F1); // ARM page 309: should call A.set(f1) and that what g++ does,// { dg-error "match" }
+ b.set(F1); // ARM page 309: should call A.set(f1) and that what g++ does,// { dg-error "cannot convert" }
// but 13.1 of ARM clearly states that it should call B::set()
// or generate an error because overloading works only for
// functions within the same scope (first page of chapter 13)
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p784.C b/gcc/testsuite/g++.old-deja/g++.mike/p784.C
index 04a70c2..44d03f1 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/p784.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/p784.C
@@ -1,6 +1,6 @@
// { dg-do assemble }
// { dg-require-effective-target ilp32 } */
-// { dg-options "-w" }
+// { dg-options "-w -fpermissive" }
// prms-id: 784
//# 1 "GctSymbol.GctSymbol.CHMap.cc"
diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb131.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb131.C
index 6a0f1c3..c2377fb 100644
--- a/gcc/testsuite/g++.old-deja/g++.robertl/eb131.C
+++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb131.C
@@ -15,6 +15,6 @@ struct a {
a::a()
{
- foo( &junk ); // { dg-error "match" } junk is an unqualified-id.
- foo( &bar ); // { dg-error "match" } bar is an unqualified-id.
+ foo( &junk ); // { dg-error "cannot convert" } junk is an unqualified-id.
+ foo( &bar ); // { dg-error "cannot convert" } bar is an unqualified-id.
}
diff --git a/gcc/testsuite/gcc.c-torture/compile/20000804-1.c b/gcc/testsuite/gcc.c-torture/compile/20000804-1.c
index 5c6b731..35464c2 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20000804-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20000804-1.c
@@ -4,6 +4,7 @@
/* { dg-skip-if "" { { i?86-*-* x86_64-*-* } && { ia32 && { ! nonpic } } } } */
/* { dg-skip-if "No 64-bit registers" { m32c-*-* } } */
/* { dg-skip-if "Not enough 64-bit registers" { pdp11-*-* } { "-O0" } { "" } } */
+/* { dg-xfail-if "Inconsistent constraint on asm" { csky-*-* } { "-O0" } { "" } } */
/* { dg-xfail-if "" { h8300-*-* } } */
/* Copyright (C) 2000, 2003 Free Software Foundation */
diff --git a/gcc/testsuite/gcc.c-torture/compile/20180915-1.c b/gcc/testsuite/gcc.c-torture/compile/20180915-1.c
new file mode 100644
index 0000000..be5c4f0
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20180915-1.c
@@ -0,0 +1,27 @@
+/* PR middle-end/86864 */
+/* Testcase by Serge Belyshev <belyshev@depni.sinp.msu.ru> */
+
+long a;
+void f ();
+void g (int b, int c, int d)
+{
+ switch (b)
+ {
+ case 42:
+ case 29:
+ case 48:
+ case 40:
+ case 32:
+ c = 2;
+ break;
+ case 0:
+ c = 1;
+ break;
+ default:
+ __builtin_unreachable ();
+ }
+ if (d || a)
+ f ();
+ if (c == 1)
+ f ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/dse.c b/gcc/testsuite/gcc.c-torture/compile/dse.c
new file mode 100644
index 0000000..908e650
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/dse.c
@@ -0,0 +1,19 @@
+typedef unsigned long microblaze_reg_t;
+struct pt_regs
+{
+ microblaze_reg_t msr;
+ int pt_mode;
+};
+struct task_struct
+{
+ void *stack;
+};
+int
+copy_thread (struct task_struct *p)
+{
+ struct pt_regs *childregs =
+ (((struct pt_regs *) ((1 << 13) + ((void *) (p)->stack))) - 1);
+ memset (childregs, 0, sizeof (struct pt_regs));
+ childregs->pt_mode = 1;
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr85704.c b/gcc/testsuite/gcc.c-torture/compile/pr85704.c
new file mode 100644
index 0000000..52dd504
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr85704.c
@@ -0,0 +1,10 @@
+/* PR c/85704 */
+
+struct C { struct {} c; };
+struct D { int d; struct C e; int f; };
+
+void
+foo (struct D *x)
+{
+ *x = (struct D) { .e = (struct C) { .c = {} } };
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr87110.c b/gcc/testsuite/gcc.c-torture/compile/pr87110.c
new file mode 100644
index 0000000..8428d3d
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr87110.c
@@ -0,0 +1,13 @@
+enum a { b, c };
+struct d {
+ _Bool e;
+ enum a f
+};
+g, h;
+i() {
+ struct d j[h];
+ j[0] = (struct d){.f = c};
+ for (; g;)
+ (struct d){};
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/execute/20101011-1.c b/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
index dda49a5..f95d900 100644
--- a/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
+++ b/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
@@ -93,6 +93,10 @@ __aeabi_idiv0 (int return_value)
#elif defined (__nvptx__)
/* There isn't even a signal function. */
# define DO_TEST 0
+#elif defined (__csky__)
+ /* This presently doesn't raise SIGFPE even on csky-linux-gnu, much
+ less bare metal. See the implementation of __divsi3 in libgcc. */
+# define DO_TEST 0
#else
# define DO_TEST 1
#endif
diff --git a/gcc/testsuite/gcc.c-torture/execute/20180921-1.c b/gcc/testsuite/gcc.c-torture/execute/20180921-1.c
new file mode 100644
index 0000000..50d4faa
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20180921-1.c
@@ -0,0 +1,161 @@
+/* PR tree-optimization/86990 */
+/* Testcase by Zhendong Su <su@cs.ucdavis.edu> */
+
+const char *ss;
+
+int __attribute__((noipa)) dummy (const char *s, ...)
+{
+ ss = s;
+}
+
+int i[6];
+static int j, v, e, f, h = 5, k, l, n, o, p, q, r, s, u, w, x, y, z, aa, ab, ac,
+ ad, ae, af, ag = 8, ah, ai, aj, ak, al;
+char c;
+struct a {
+ unsigned b;
+ int c : 9;
+ int d;
+} static g = {9, 5};
+static short m[1], t = 95, am;
+int an, ao, ap;
+void aq(int ar) {
+ j = j & 5 ^ i[j ^ v & 5];
+ j = j & 5 ^ i[(j ^ v) & 5];
+ j = j & 4095 ^ (j ^ v) & 5;
+}
+void as(int ar) {
+ if (n)
+ s = 0;
+}
+static unsigned at() {
+ int au[] = {2080555007, 0};
+ for (; al; al--) {
+ if (r)
+ --x;
+ if (g.d)
+ l++;
+ dummy("", j);
+ if (u)
+ ae = n = au[al];
+ }
+ r = 0;
+ return 0;
+}
+int aw(int ar) {
+ int ax[] = {9, 5, 5, 9, 5}, ay = 3;
+ struct a az = {1, 3};
+av:
+ an = (as((at(), ax)[2]), ax[4]);
+ {
+ int ba[] = {5, 5, 9, 8, 1, 0, 5, 5, 9, 8, 1, 0,
+ 5, 5, 9, 8, 1, 0, 5, 5, 9, 8, 1};
+ int a[] = {8, 2, 8, 2, 8, 2, 8};
+ int b[] = {1027239, 8, 1, 7, 9, 2, 9, 4, 4, 2, 8, 1, 0, 4, 4, 2,
+ 4, 4, 2, 9, 2, 9, 8, 1, 7, 9, 2, 9, 4, 4, 2};
+ if (z) {
+ struct a bc;
+ bb:
+ for (; e; e++)
+ for (; q;)
+ return ax[e];
+ if (bc.c < g.d <= a[7])
+ aa--;
+ }
+ {
+ struct a bd = {5};
+ int d[20] = {1, 9, 7, 7, 8, 4, 4, 4, 4, 8, 1, 9, 7, 7, 8, 4, 4, 4, 4};
+ c = h | r % g.c ^ x;
+ dummy("", g);
+ am -= t | x;
+ if (h)
+ while (1) {
+ if (a[o]) {
+ struct a be;
+ if (ar) {
+ struct a bf = {908, 5, 3};
+ int bg[3], bh = k, bj = ag | ae, bk = aj + 3, bl = u << e;
+ if (f)
+ if (ac)
+ ak = w;
+ ag = -(ag & t);
+ af = ag ^ af;
+ if (8 < af)
+ break;
+ if (bj)
+ goto bi;
+ if (s)
+ dummy("", 6);
+ be.d = k;
+ w = f - bh;
+ dummy("", be);
+ if (w)
+ goto bb;
+ ao = r - aa && g.b;
+ if (y)
+ k++;
+ goto av;
+ bi:
+ if (aa)
+ continue;
+ if (f)
+ if (k)
+ dummy("", g);
+ aj = ac + k ^ g.c;
+ g.c = bk;
+ ah = 0;
+ for (; ah < 3; ah++)
+ if (s)
+ bg[ah] = 8;
+ if (!ay)
+ dummy("", ai);
+ u = bl;
+ g = bf;
+ } else
+ for (;; o += a[ap])
+ ;
+ int bm[] = {0};
+ for (; p; p++)
+ c = ad;
+ ad = l;
+ if (bd.c) {
+ dummy(" ");
+ goto bi;
+ }
+ }
+ int bn[] = {5, 2, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 5,
+ 2, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 5, 2,
+ 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 5, 2, 2, 5, 2};
+ struct a a[] = {3440025416, 2, 8, 4, 2, 8, 4, 4, 2, 8, 4};
+ struct a b = {3075920};
+ if (f) {
+ aq(m[am + e]);
+ dummy("", j);
+ dummy("", e);
+ ab--;
+ }
+ if (ax[4]) {
+ if (l)
+ goto av;
+ ++f;
+ } else
+ ay = az.c && a;
+ for (; ac; ac++)
+ m[f] = 0;
+ }
+ h = 9;
+ for (; y; y = 1)
+ if (f)
+ goto av;
+ }
+ }
+ return 0;
+}
+
+int main (void)
+{
+ aw(1);
+ if (g.c!= 5)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/mul-subnormal-single-1.x b/gcc/testsuite/gcc.c-torture/execute/ieee/mul-subnormal-single-1.x
index 16df951..ee40863 100644
--- a/gcc/testsuite/gcc.c-torture/execute/ieee/mul-subnormal-single-1.x
+++ b/gcc/testsuite/gcc.c-torture/execute/ieee/mul-subnormal-single-1.x
@@ -1,3 +1,8 @@
+if {[istarget "csky-*-*"] && [check_effective_target_hard_float]} {
+ # The C-SKY hardware FPU only supports flush-to-zero mode.
+ set torture_execute_xfail "csky-*-*"
+ return 1
+}
if [istarget "epiphany-*-*"] {
# The Epiphany single-precision floating point format does not
# support subnormals.
diff --git a/gcc/testsuite/gcc.c-torture/execute/memchr-1.c b/gcc/testsuite/gcc.c-torture/execute/memchr-1.c
new file mode 100644
index 0000000..54fae16
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/memchr-1.c
@@ -0,0 +1,153 @@
+/* PR tree-optimization/86711 - wrong folding of memchr
+
+ Verify that memchr() of arrays initialized with string literals
+ where the nul doesn't fit in the array doesn't find the nul. */
+typedef __SIZE_TYPE__ size_t;
+typedef __WCHAR_TYPE__ wchar_t;
+
+extern void* memchr (const void*, int, size_t);
+
+#define A(expr) \
+ ((expr) \
+ ? (void)0 \
+ : (__builtin_printf ("assertion failed on line %i: %s\n", \
+ __LINE__, #expr), \
+ __builtin_abort ()))
+
+static const char c = '1';
+static const char s1[1] = "1";
+static const char s4[4] = "1234";
+
+static const char s4_2[2][4] = { "1234", "5678" };
+static const char s5_3[3][5] = { "12345", "6789", "01234" };
+
+volatile int v0 = 0;
+volatile int v1 = 1;
+volatile int v2 = 2;
+volatile int v3 = 3;
+volatile int v4 = 3;
+
+void test_narrow (void)
+{
+ int i0 = 0;
+ int i1 = i0 + 1;
+ int i2 = i1 + 1;
+ int i3 = i2 + 1;
+ int i4 = i3 + 1;
+
+ A (memchr ("" + 1, 0, 0) == 0);
+
+ A (memchr (&c, 0, sizeof c) == 0);
+ A (memchr (&c + 1, 0, sizeof c - 1) == 0);
+ A (memchr (&c + i1, 0, sizeof c - i1) == 0);
+ A (memchr (&c + v1, 0, sizeof c - v1) == 0);
+
+ A (memchr (s1, 0, sizeof s1) == 0);
+ A (memchr (s1 + 1, 0, sizeof s1 - 1) == 0);
+ A (memchr (s1 + i1, 0, sizeof s1 - i1) == 0);
+ A (memchr (s1 + v1, 0, sizeof s1 - v1) == 0);
+
+ A (memchr (&s1, 0, sizeof s1) == 0);
+ A (memchr (&s1 + 1, 0, sizeof s1 - 1) == 0);
+ A (memchr (&s1 + i1, 0, sizeof s1 - i1) == 0);
+ A (memchr (&s1 + v1, 0, sizeof s1 - v1) == 0);
+
+ A (memchr (&s1[0], 0, sizeof s1) == 0);
+ A (memchr (&s1[0] + 1, 0, sizeof s1 - 1) == 0);
+ A (memchr (&s1[0] + i1, 0, sizeof s1 - i1) == 0);
+ A (memchr (&s1[0] + v1, 0, sizeof s1 - v1) == 0);
+
+ A (memchr (&s1[i0], 0, sizeof s1) == 0);
+ A (memchr (&s1[i0] + 1, 0, sizeof s1 - 1) == 0);
+ A (memchr (&s1[i0] + i1, 0, sizeof s1 - i1) == 0);
+ A (memchr (&s1[i0] + v1, 0, sizeof s1 - v1) == 0);
+
+ A (memchr (&s1[v0], 0, sizeof s1) == 0);
+ A (memchr (&s1[v0] + 1, 0, sizeof s1 - 1) == 0);
+ A (memchr (&s1[v0] + i1, 0, sizeof s1 - i1) == 0);
+ A (memchr (&s1[v0] + v1, 0, sizeof s1 - v1) == 0);
+
+
+ A (memchr (s4 + i0, 0, sizeof s4 - i0) == 0);
+ A (memchr (s4 + i1, 0, sizeof s4 - i1) == 0);
+ A (memchr (s4 + i2, 0, sizeof s4 - i2) == 0);
+ A (memchr (s4 + i3, 0, sizeof s4 - i3) == 0);
+ A (memchr (s4 + i4, 0, sizeof s4 - i4) == 0);
+
+ A (memchr (s4 + v0, 0, sizeof s4 - v0) == 0);
+ A (memchr (s4 + v1, 0, sizeof s4 - v1) == 0);
+ A (memchr (s4 + v2, 0, sizeof s4 - v2) == 0);
+ A (memchr (s4 + v3, 0, sizeof s4 - v3) == 0);
+ A (memchr (s4 + v4, 0, sizeof s4 - v4) == 0);
+
+
+ A (memchr (s4_2, 0, sizeof s4_2) == 0);
+
+ A (memchr (s4_2[0], 0, sizeof s4_2[0]) == 0);
+ A (memchr (s4_2[1], 0, sizeof s4_2[1]) == 0);
+
+ A (memchr (s4_2[0] + 1, 0, sizeof s4_2[0] - 1) == 0);
+ A (memchr (s4_2[1] + 2, 0, sizeof s4_2[1] - 2) == 0);
+ A (memchr (s4_2[1] + 3, 0, sizeof s4_2[1] - 3) == 0);
+
+ A (memchr (s4_2[v0], 0, sizeof s4_2[v0]) == 0);
+ A (memchr (s4_2[v0] + 1, 0, sizeof s4_2[v0] - 1) == 0);
+
+
+ /* The following calls must find the nul. */
+ A (memchr ("", 0, 1) != 0);
+ A (memchr (s5_3, 0, sizeof s5_3) == &s5_3[1][4]);
+
+ A (memchr (&s5_3[0][0] + i0, 0, sizeof s5_3 - i0) == &s5_3[1][4]);
+ A (memchr (&s5_3[0][0] + i1, 0, sizeof s5_3 - i1) == &s5_3[1][4]);
+ A (memchr (&s5_3[0][0] + i2, 0, sizeof s5_3 - i2) == &s5_3[1][4]);
+ A (memchr (&s5_3[0][0] + i4, 0, sizeof s5_3 - i4) == &s5_3[1][4]);
+
+ A (memchr (&s5_3[1][i0], 0, sizeof s5_3[1] - i0) == &s5_3[1][4]);
+}
+
+static const wchar_t wc = L'1';
+static const wchar_t ws1[] = L"1";
+static const wchar_t ws4[] = L"\x00123456\x12005678\x12340078\x12345600";
+
+void test_wide (void)
+{
+ int i0 = 0;
+ int i1 = i0 + 1;
+ int i2 = i1 + 1;
+ int i3 = i2 + 1;
+ int i4 = i3 + 1;
+
+ A (memchr (L"" + 1, 0, 0) == 0);
+ A (memchr (&wc + 1, 0, 0) == 0);
+ A (memchr (L"\x12345678", 0, sizeof (wchar_t)) == 0);
+
+ const size_t nb = sizeof ws4;
+ const size_t nwb = sizeof (wchar_t);
+
+ const char *pws1 = (const char*)ws1;
+ const char *pws4 = (const char*)ws4;
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ A (memchr (ws1, 0, sizeof ws1) == pws1 + 1);
+
+ A (memchr (&ws4[0], 0, nb) == pws4 + 3);
+ A (memchr (&ws4[1], 0, nb - 1 * nwb) == pws4 + 1 * nwb + 2);
+ A (memchr (&ws4[2], 0, nb - 2 * nwb) == pws4 + 2 * nwb + 1);
+ A (memchr (&ws4[3], 0, nb - 3 * nwb) == pws4 + 3 * nwb + 0);
+#else
+ A (memchr (ws1, 0, sizeof ws1) == pws1 + 0);
+
+ A (memchr (&ws4[0], 0, nb) == pws4 + 0);
+ A (memchr (&ws4[1], 0, nb - 1 * nwb) == pws4 + 1 * nwb + 1);
+ A (memchr (&ws4[2], 0, nb - 2 * nwb) == pws4 + 2 * nwb + 2);
+ A (memchr (&ws4[3], 0, nb - 3 * nwb) == pws4 + 3 * nwb + 3);
+#endif
+}
+
+
+int main ()
+{
+ test_narrow ();
+ test_wide ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr86714.c b/gcc/testsuite/gcc.c-torture/execute/pr86714.c
new file mode 100644
index 0000000..3ad6852
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr86714.c
@@ -0,0 +1,26 @@
+/* PR tree-optimization/86714 - tree-ssa-forwprop.c confused by too
+ long initializer
+
+ The excessively long initializer for a[0] is undefined but this
+ test verifies that the excess elements are not considered a part
+ of the value of the array as a matter of QoI. */
+
+const char a[2][3] = { "1234", "xyz" };
+char b[6];
+
+void *pb = b;
+
+int main ()
+{
+ __builtin_memcpy (b, a, 4);
+ __builtin_memset (b + 4, 'a', 2);
+
+ if (b[0] != '1' || b[1] != '2' || b[2] != '3'
+ || b[3] != 'x' || b[4] != 'a' || b[5] != 'a')
+ __builtin_abort ();
+
+ if (__builtin_memcmp (pb, "123xaa", 6))
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr86844.c b/gcc/testsuite/gcc.c-torture/execute/pr86844.c
new file mode 100644
index 0000000..ead8922
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr86844.c
@@ -0,0 +1,24 @@
+/* PR tree-optimization/86844 */
+
+__attribute__((noipa)) void
+foo (int *p)
+{
+ *p = 0;
+ *((char *)p + 3) = 1;
+ *((char *)p + 1) = 2;
+ *((char *)p + 2) = *((char *)p + 6);
+}
+
+int
+main ()
+{
+ int a[2] = { -1, 0 };
+ if (sizeof (int) != 4)
+ return 0;
+ ((char *)a)[6] = 3;
+ foo (a);
+ if (((char *)a)[0] != 0 || ((char *)a)[1] != 2
+ || ((char *)a)[2] != 3 || ((char *)a)[3] != 1)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr87053.c b/gcc/testsuite/gcc.c-torture/execute/pr87053.c
new file mode 100644
index 0000000..0170731
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr87053.c
@@ -0,0 +1,17 @@
+/* PR middle-end/87053 */
+
+const union
+{ struct {
+ char x[4];
+ char y[4];
+ };
+ struct {
+ char z[8];
+ };
+} u = {{"1234", "567"}};
+
+int main ()
+{
+ if (__builtin_strlen (u.z) != 7)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr87290.c b/gcc/testsuite/gcc.c-torture/execute/pr87290.c
new file mode 100644
index 0000000..31bbdd6
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr87290.c
@@ -0,0 +1,63 @@
+/* PR middle-end/87290 */
+
+int c;
+
+__attribute__((noipa)) void
+f0 (void)
+{
+ c++;
+}
+
+__attribute__((noipa)) int
+f1 (int x)
+{
+ return x % 16 == 13;
+}
+
+__attribute__((noipa)) int
+f2 (int x)
+{
+ return x % 16 == -13;
+}
+
+__attribute__((noipa)) void
+f3 (int x)
+{
+ if (x % 16 == 13)
+ f0 ();
+}
+
+__attribute__((noipa)) void
+f4 (int x)
+{
+ if (x % 16 == -13)
+ f0 ();
+}
+
+int
+main ()
+{
+ int i, j;
+ for (i = -30; i < 30; i++)
+ {
+ if (f1 (13 + i * 16) != (i >= 0) || f2 (-13 + i * 16) != (i <= 0))
+ __builtin_abort ();
+ f3 (13 + i * 16);
+ if (c != (i >= 0))
+ __builtin_abort ();
+ f4 (-13 + i * 16);
+ if (c != 1 + (i == 0))
+ __builtin_abort ();
+ for (j = 1; j < 16; j++)
+ {
+ if (f1 (13 + i * 16 + j) || f2 (-13 + i * 16 + j))
+ __builtin_abort ();
+ f3 (13 + i * 16 + j);
+ f4 (-13 + i * 16 + j);
+ }
+ if (c != 1 + (i == 0))
+ __builtin_abort ();
+ c = 0;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/widechar-3.c b/gcc/testsuite/gcc.c-torture/execute/widechar-3.c
new file mode 100644
index 0000000..0810c7d
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/widechar-3.c
@@ -0,0 +1,26 @@
+extern void abort (void);
+extern void exit (int);
+
+static int f(char *x)
+{
+ return __builtin_strlen(x);
+}
+
+int foo ()
+{
+ return f((char*)&L"abcdef"[0]);
+}
+
+
+int
+main()
+{
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ if (foo () != 0)
+ abort ();
+#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ if (foo () != 1)
+ abort ();
+#endif
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.c-torture/unsorted/dump-noaddr.x b/gcc/testsuite/gcc.c-torture/unsorted/dump-noaddr.x
index e86f36a..0e4298a 100644
--- a/gcc/testsuite/gcc.c-torture/unsorted/dump-noaddr.x
+++ b/gcc/testsuite/gcc.c-torture/unsorted/dump-noaddr.x
@@ -11,10 +11,10 @@ proc dump_compare { src options } {
foreach option $option_list {
file delete -force $tmpdir/dump1
file mkdir $tmpdir/dump1
- c-torture-compile $src "$option $options -dumpbase dump1/$dumpbase -DMASK=1 -x c --param ggc-min-heapsize=1 -fdump-ipa-all -fdump-rtl-all -fdump-tree-all -fdump-noaddr"
+ c-torture-compile $src "$option $options -dumpbase dump1/$dumpbase -DMASK=1 -x c --param ggc-min-heapsize=1 -fdump-ipa-all -fdump-rtl-all -fdump-tree-all -fdump-noaddr -gno-record-gcc-switches"
file delete -force $tmpdir/dump2
file mkdir $tmpdir/dump2
- c-torture-compile $src "$option $options -dumpbase dump2/$dumpbase -DMASK=2 -x c -fdump-ipa-all -fdump-rtl-all -fdump-tree-all -fdump-noaddr"
+ c-torture-compile $src "$option $options -dumpbase dump2/$dumpbase -DMASK=2 -x c -fdump-ipa-all -fdump-rtl-all -fdump-tree-all -fdump-noaddr -gno-record-gcc-switches"
foreach dump1 [lsort [glob -nocomplain $tmpdir/dump1/*]] {
set dump2 "$tmpdir/dump2/[file tail $dump1]"
set dumptail "gcc.c-torture/unsorted/[file tail $dump1]"
diff --git a/gcc/testsuite/gcc.dg/20020312-2.c b/gcc/testsuite/gcc.dg/20020312-2.c
index f5929e0..f8be3ce 100644
--- a/gcc/testsuite/gcc.dg/20020312-2.c
+++ b/gcc/testsuite/gcc.dg/20020312-2.c
@@ -111,6 +111,11 @@ extern void abort (void);
/* No pic register. */
#elif defined (__nvptx__)
/* No pic register. */
+#elif defined (__csky__)
+/* Pic register is r28, but some cores only have r0-r15. */
+# if defined (__CK807__) || defined (__CK810__)
+# define PIC_REG "r28"
+# endif
#else
# error "Modify the test for your target."
#endif
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-33.c b/gcc/testsuite/gcc.dg/Warray-bounds-33.c
new file mode 100644
index 0000000..28f14b4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-33.c
@@ -0,0 +1,36 @@
+/* PR tree-optimization/86741 - ICE in -Warray-bounds indexing into
+ an object of incomplete type
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+struct S
+{
+ int s;
+};
+
+void f (void);
+
+void test_void (void)
+{
+ extern void v;
+ struct S *b = (struct S*)&v;
+ if (b->s)
+ f ();
+}
+
+void test_incomplete_enum (void)
+{
+ extern enum E e;
+ struct S *b = (struct S*)&e;
+ if (b->s)
+ f ();
+}
+
+void test_func (void)
+{
+ struct S *b = (struct S*)&f;
+ if (b->s)
+ f ();
+}
+
+/* { dg-prune-output "taking address of expression of type .void." } */
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-34.c b/gcc/testsuite/gcc.dg/Warray-bounds-34.c
new file mode 100644
index 0000000..cea7c4b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-34.c
@@ -0,0 +1,18 @@
+/* PR tree-optimization/86650 - -Warray-bounds missing inlining context
+ { dg-do compile }
+ { dg-options "-O2 -Warray-bounds" } */
+
+int a[3]; /* { dg-message "while referencing .a." } */
+int x;
+
+inline void foo (int i)
+{
+ a[i + 1] = 123; /* { dg-warning "\\\[-Warray-bounds]" } */
+}
+
+int bar (void)
+{
+ foo (3);
+
+ return x;
+}
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-35.c b/gcc/testsuite/gcc.dg/Warray-bounds-35.c
new file mode 100644
index 0000000..b3ad362
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-35.c
@@ -0,0 +1,15 @@
+/* PR tree-optimization/87072 - g++6.2.0 false warning: array subscript
+ is above array bounds, with misleading line number
+ { dg-do compile }
+ { dg-options "-O3 -Wall" } */
+
+int a[10];
+
+void f (unsigned n)
+{
+ for (unsigned j = 0; j < n; j++) {
+ for (unsigned k = 0; k < j; k++)
+ a[j] += k; /* { dg-bogus "\\\[-Warray-bounds]" } */
+ a[j] += j;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/Wno-frame-address.c b/gcc/testsuite/gcc.dg/Wno-frame-address.c
index e6dfe52..9fe4d07 100644
--- a/gcc/testsuite/gcc.dg/Wno-frame-address.c
+++ b/gcc/testsuite/gcc.dg/Wno-frame-address.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-skip-if "Cannot access arbitrary stack frames" { arm*-*-* avr-*-* hppa*-*-* ia64-*-* visium-*-* } } */
+/* { dg-skip-if "Cannot access arbitrary stack frames" { arm*-*-* avr-*-* hppa*-*-* ia64-*-* visium-*-* csky-*-* } } */
/* { dg-options "-Werror" } */
/* { dg-additional-options "-mbackchain" { target { s390*-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-6.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-6.c
index 9284a87..acb0fcb 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-6.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-6.c
@@ -25,7 +25,7 @@ void test_strcpy_strcat_1 (void)
void test_strcpy_strcat_2 (void)
{
- strcpy (a2, "12"), strcat (a2, "3"); /* { dg-warning "\\\[-Wstringop-overflow=]" "bug 86121" { xfail *-*-* } } */
+ strcpy (a2, "12"), strcat (a2, "3"); /* { dg-warning "\\\[-Wstringop-overflow=]" } */
}
void test_strcpy_strcat_3 (void)
diff --git a/gcc/testsuite/gcc.dg/addr_equal-1.c b/gcc/testsuite/gcc.dg/addr_equal-1.c
index dd237a7..70fa354 100644
--- a/gcc/testsuite/gcc.dg/addr_equal-1.c
+++ b/gcc/testsuite/gcc.dg/addr_equal-1.c
@@ -2,7 +2,7 @@
/* { dg-require-effective-target nonpic } */
/* { dg-require-weak "" } */
/* { dg-require-alias "" } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -fdelete-null-pointer-checks" } */
/* { dg-skip-if "" { powerpc-ibm-aix* } } */
void abort (void);
extern int undef_var0, undef_var1;
diff --git a/gcc/testsuite/gcc.dg/asan/pr81923.c b/gcc/testsuite/gcc.dg/asan/pr81923.c
index f81d512..dd9db72 100644
--- a/gcc/testsuite/gcc.dg/asan/pr81923.c
+++ b/gcc/testsuite/gcc.dg/asan/pr81923.c
@@ -1,7 +1,10 @@
/* PR sanitizer/81923 */
/* { dg-do link } */
-int foobar __asm (__USER_LABEL_PREFIX__ "barbaz") = 34;
+#define STR1(X) #X
+#define STR2(X) STR1(X)
+
+int foobar __asm (STR2(__USER_LABEL_PREFIX__) "barbaz") = 34;
int
main ()
diff --git a/gcc/testsuite/gcc.dg/asan/pr86962.c b/gcc/testsuite/gcc.dg/asan/pr86962.c
new file mode 100644
index 0000000..7a8cfa9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/pr86962.c
@@ -0,0 +1,13 @@
+/* PR sanitizer/86962 */
+/* { dg-do compile } */
+
+extern int dummy (int *);
+
+void foo(int i)
+{
+ int j=i;
+
+ void bar() { int x=j, y=i; }
+
+ dummy(&i);
+}
diff --git a/gcc/testsuite/gcc.dg/bad-binary-ops.c b/gcc/testsuite/gcc.dg/bad-binary-ops.c
index e1da4d6..46c158e 100644
--- a/gcc/testsuite/gcc.dg/bad-binary-ops.c
+++ b/gcc/testsuite/gcc.dg/bad-binary-ops.c
@@ -13,6 +13,8 @@ void test_1 ()
{ dg-begin-multiline-output "" }
myvec[1]/ptr;
~~~~~~~~^
+ |
+ __m128
{ dg-end-multiline-output "" } */
@@ -31,8 +33,12 @@ int test_2 (void)
/* { dg-begin-multiline-output "" }
return (some_function ()
~~~~~~~~~~~~~~~~
+ |
+ struct s
+ some_other_function ());
^ ~~~~~~~~~~~~~~~~~~~~~~
+ |
+ struct t
{ dg-end-multiline-output "" } */
}
@@ -46,3 +52,23 @@ int test_3 (struct s param_s, struct t param_t)
{ dg-end-multiline-output "" } */
/* TODO: ideally we'd underline both params here. */
}
+
+typedef struct s S;
+typedef struct t T;
+
+extern S callee_4a (void);
+extern T callee_4b (void);
+
+int test_4 (void)
+{
+ return callee_4a () + callee_4b (); /* { dg-error "invalid operands to binary \+" } */
+
+/* { dg-begin-multiline-output "" }
+ return callee_4a () + callee_4b ();
+ ~~~~~~~~~~~~ ^ ~~~~~~~~~~~~
+ | |
+ | T {aka struct t}
+ S {aka struct s}
+ { dg-end-multiline-output "" } */
+}
+
diff --git a/gcc/testsuite/gcc.dg/c11-true_min-1.c b/gcc/testsuite/gcc.dg/c11-true_min-1.c
index f666c72..1fbf514 100644
--- a/gcc/testsuite/gcc.dg/c11-true_min-1.c
+++ b/gcc/testsuite/gcc.dg/c11-true_min-1.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-std=c11" } */
/* { dg-xfail-run-if "PR58757 -mieee is required to compare denormals" { alpha*-*-* } } */
+/* { dg-skip-if "No subnormal support" { csky-*-* } { "-mhard-float" } } */
/* Test that the smallest positive value is not 0. This needs to be true
even when denormals are not supported, so we do not pass any flag
diff --git a/gcc/testsuite/gcc.dg/completion-4.c b/gcc/testsuite/gcc.dg/completion-4.c
new file mode 100644
index 0000000..8116811
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/completion-4.c
@@ -0,0 +1,6 @@
+/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "--completion=-march=geo" } */
+
+/* { dg-begin-multiline-output "" }
+-march=geode
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/cpp/macsyntx.c b/gcc/testsuite/gcc.dg/cpp/macsyntx.c
index a6c8e11..dab1e9d 100644
--- a/gcc/testsuite/gcc.dg/cpp/macsyntx.c
+++ b/gcc/testsuite/gcc.dg/cpp/macsyntx.c
@@ -21,14 +21,14 @@
#define ; /* { dg-error "identifier" } */
#define SEMI; /* { dg-warning "space" } */
-#define foo(X /* { dg-error "missing" } */
+#define foo(X /* { dg-error "expected" } */
#define foo\
(X,) /* { dg-error "parameter name" } */
#define foo(, X) /* { dg-error "parameter name" } */
#define foo(X, X) /* { dg-error "duplicate" } */
-#define foo(X Y) /* { dg-error "comma" } */
-#define foo(() /* { dg-error "may not appear" } */
-#define foo(..., X) /* { dg-error "missing" } */
+#define foo(X Y) /* { dg-error "expected" } */
+#define foo(() /* { dg-error "parameter name" } */
+#define foo(..., X) /* { dg-error "expected" } */
#define foo \
__VA_ARGS__ /* { dg-warning "__VA_ARGS__" } */
#define goo(__VA_ARGS__) /* { dg-warning "__VA_ARGS__" } */
diff --git a/gcc/testsuite/gcc.dg/cpp/macsyntx2.c b/gcc/testsuite/gcc.dg/cpp/macsyntx2.c
index 1fbd115..f0fcf52 100644
--- a/gcc/testsuite/gcc.dg/cpp/macsyntx2.c
+++ b/gcc/testsuite/gcc.dg/cpp/macsyntx2.c
@@ -21,14 +21,14 @@
#define ; /* { dg-error "identifier" } */
#define SEMI; /* { dg-warning "space" } */
-#define foo(X /* { dg-error "missing" } */
+#define foo(X /* { dg-error "expected" } */
#define foo\
(X,) /* { dg-error "parameter name" } */
#define foo(, X) /* { dg-error "parameter name" } */
#define foo(X, X) /* { dg-error "duplicate" } */
-#define foo(X Y) /* { dg-error "comma" } */
-#define foo(() /* { dg-error "may not appear" } */
-#define foo(..., X) /* { dg-error "missing" } */
+#define foo(X Y) /* { dg-error "expected" } */
+#define foo(() /* { dg-error "parameter name" } */
+#define foo(..., X) /* { dg-error "expected" } */
#define foo \
__VA_ARGS__ /* { dg-warning "__VA_ARGS__" } */
#define goo(__VA_ARGS__) /* { dg-warning "__VA_ARGS__" } */
diff --git a/gcc/testsuite/gcc.dg/cpp/pr66415-1.c b/gcc/testsuite/gcc.dg/cpp/pr66415-1.c
index 515252c..cc4e417 100644
--- a/gcc/testsuite/gcc.dg/cpp/pr66415-1.c
+++ b/gcc/testsuite/gcc.dg/cpp/pr66415-1.c
@@ -11,6 +11,8 @@ fn1 (void)
/* { dg-begin-multiline-output "" }
__builtin_printf ("xxxxxxxxxxxxxxxxx%dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
~^
+ |
+ int
{ dg-end-multiline-output "" } */
}
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr80263.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr80263.c
index 57633b4..f1a6a33 100644
--- a/gcc/testsuite/gcc.dg/debug/dwarf2/pr80263.c
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr80263.c
@@ -1,6 +1,8 @@
/* PR debug/80263 */
/* { dg-do compile } */
/* { dg-options "-g -dA" } */
+/* Darwin emits pubnames/types by default - suppress this for the test. */
+/* { dg-additional-options "-gno-pubnames" { target *-*-darwin* } } */
char array[1];
diff --git a/gcc/testsuite/gcc.dg/dfp/warn-abs-2.c b/gcc/testsuite/gcc.dg/dfp/warn-abs-2.c
new file mode 100644
index 0000000..c1a1994
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/warn-abs-2.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-Wabsolute-value" } */
+
+#include <stdlib.h>
+#include <complex.h>
+#include <math.h>
+
+void tst_decimal (_Decimal32 *p32, _Decimal64 *p64, _Decimal128 *p128)
+{
+ *p32 = abs(*p32); /* { dg-warning "using integer absolute value function" } */
+ *p64 = fabs(*p64); /* { dg-warning "using floating point absolute value function" } */
+ *p128 = cabsl(*p128); /* { dg-warning "using complex absolute value function" } */
+}
+
+void tst_notdecimal (int *pi, double *pd, long double *pld, complex double *pc)
+{
+ *pi = __builtin_fabsd32 (*pi); /* { dg-warning "using decimal floating point absolute value function" } */
+ *pd = __builtin_fabsd64 (*pd); /* { dg-warning "using decimal floating point absolute value function" } */
+ *pld = __builtin_fabsd64 (*pld); /* { dg-warning "using decimal floating point absolute value function" } */
+ *pc = __builtin_fabsd128 (*pc); /* { dg-warning "using decimal floating point absolute value function" } */
+}
+
+void
+test_size (_Decimal64 *p64, _Decimal128 *p128)
+{
+ *p64 = __builtin_fabsd32 (*p64); /* { dg-warning "may cause truncation of value" } */
+ *p128 = __builtin_fabsd64 (*p128); /* { dg-warning "may cause truncation of value" } */
+}
diff --git a/gcc/testsuite/gcc.dg/diagnostic-token-ranges.c b/gcc/testsuite/gcc.dg/diagnostic-token-ranges.c
index 2ef7a01..406bd32 100644
--- a/gcc/testsuite/gcc.dg/diagnostic-token-ranges.c
+++ b/gcc/testsuite/gcc.dg/diagnostic-token-ranges.c
@@ -8,12 +8,11 @@ long double nanl (const char *);
void undeclared_identifier (void)
{
- name; /* { dg-error "'name' undeclared .first use in this function.; did you mean .nanl." } */
+ name; /* { dg-error "'name' undeclared" } */
/*
{ dg-begin-multiline-output "" }
name;
^~~~
- nanl
{ dg-end-multiline-output "" }
*/
}
diff --git a/gcc/testsuite/gcc.dg/driver-specs.c b/gcc/testsuite/gcc.dg/driver-specs.c
new file mode 100644
index 0000000..9cb66e1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/driver-specs.c
@@ -0,0 +1,4 @@
+// { dg-additional-options "-specs=not-a-file" }
+// { dg-prune-output "compilation terminated" }
+// { dg-error "cannot read spec file" "" { target *-*-* } 0 }
+
diff --git a/gcc/testsuite/gcc.dg/empty.h b/gcc/testsuite/gcc.dg/empty.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/empty.h
diff --git a/gcc/testsuite/gcc.dg/fixits-pr84852-1.c b/gcc/testsuite/gcc.dg/fixits-pr84852-1.c
index 98087ab..346626b 100644
--- a/gcc/testsuite/gcc.dg/fixits-pr84852-1.c
+++ b/gcc/testsuite/gcc.dg/fixits-pr84852-1.c
@@ -13,13 +13,10 @@
int foo (void) { return strlen(""); }
/* { dg-warning "incompatible implicit declaration of built-in function 'strlen'" "" { target *-*-* } -812156810 } */
-/* { dg-message "include '<string.h>' or provide a declaration of 'strlen'" "" { target *-*-* } -812156810 } */
+/* { dg-message "include '<string.h>' or provide a declaration of 'strlen'" "" { target *-*-* } 1 } */
#if 0
{ dg-begin-multiline-output "" }
+#include <string.h>
/* This is padding (to avoid the output containing DejaGnu directives). */
{ dg-end-multiline-output "" }
#endif
-
-/* We need this, to consume a stray line marker for the bogus line. */
-/* { dg-regexp ".*fixits-pr84852-1.c:-812156810:25:" } */
diff --git a/gcc/testsuite/gcc.dg/fixits-pr84852-2.c b/gcc/testsuite/gcc.dg/fixits-pr84852-2.c
index 0674ef5..9bc70f5 100644
--- a/gcc/testsuite/gcc.dg/fixits-pr84852-2.c
+++ b/gcc/testsuite/gcc.dg/fixits-pr84852-2.c
@@ -13,13 +13,10 @@
int foo (void) { return strlen(""); }
/* { dg-warning "incompatible implicit declaration of built-in function 'strlen'" "" { target *-*-* } -812156810 } */
-/* { dg-message "include '<string.h>' or provide a declaration of 'strlen'" "" { target *-*-* } -812156810 } */
+/* { dg-message "include '<string.h>' or provide a declaration of 'strlen'" "" { target *-*-* } 1 } */
#if 0
{ dg-begin-multiline-output "" }
+#include <string.h>
/* This is padding (to avoid the output containing DejaGnu directives). */
{ dg-end-multiline-output "" }
#endif
-
-/* We need this, to consume a stray line marker for the bogus line. */
-/* { dg-regexp ".*fixits-pr84852-2.c:-812156810:25:" } */
diff --git a/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c b/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
index e56e159..84535f0 100644
--- a/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
+++ b/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
@@ -11,6 +11,8 @@ void test_mismatching_types (const char *msg)
/* { dg-begin-multiline-output "" }
printf("hello %i", msg);
~^ ~~~
+ | |
+ int const char *
%s
{ dg-end-multiline-output "" } */
@@ -19,6 +21,9 @@ void test_mismatching_types (const char *msg)
/* { dg-begin-multiline-output "" }
printf("hello %s", 42);
~^ ~~
+ | |
+ | int
+ char *
%d
{ dg-end-multiline-output "" } */
@@ -26,6 +31,8 @@ void test_mismatching_types (const char *msg)
/* { dg-begin-multiline-output "" }
printf("hello %i", (long)0);
~^ ~~~~~~~
+ | |
+ int long int
%li
{ dg-end-multiline-output "" } */
}
@@ -37,9 +44,13 @@ void test_multiple_arguments (void)
/* { dg-begin-multiline-output "" }
printf ("arg0: %i arg1: %s arg 2: %i",
~^
+ |
+ char *
%d
100, 101, 102);
~~~
+ |
+ int
{ dg-end-multiline-output "" } */
}
@@ -50,9 +61,13 @@ void test_multiple_arguments_2 (int i, int j)
/* { dg-begin-multiline-output "" }
printf ("arg0: %i arg1: %s arg 2: %i",
~^
+ |
+ char *
%d
100, i + j, 102);
~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
}
@@ -72,6 +87,8 @@ void multiline_format_string (void) {
~~
"d"
~^
+ |
+ int
{ dg-end-multiline-output "" } */
}
@@ -84,6 +101,8 @@ void test_hex (const char *msg)
/* { dg-begin-multiline-output "" }
printf("hello \x25\x69", msg);
~~~~^~~~ ~~~
+ | |
+ int const char *
\x25s
{ dg-end-multiline-output "" } */
}
@@ -97,6 +116,8 @@ void test_oct (const char *msg)
/* { dg-begin-multiline-output "" }
printf("hello \045\151", msg);
~~~~^~~~ ~~~
+ | |
+ int const char *
\045s
{ dg-end-multiline-output "" } */
}
@@ -112,11 +133,15 @@ void test_multiple (const char *msg)
^~~~~~~~
msg);
~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
printf("prefix" "\x25" "\151" "suffix",
~~~~~~~~^~~~
+ |
+ int
\x25" "s
{ dg-end-multiline-output "" } */
}
@@ -127,6 +152,8 @@ void test_u8 (const char *msg)
/* { dg-begin-multiline-output "" }
printf(u8"hello %i", msg);
~^ ~~~
+ | |
+ int const char *
%s
{ dg-end-multiline-output "" } */
}
@@ -137,6 +164,8 @@ void test_param (long long_i, long long_j)
/* { dg-begin-multiline-output "" }
printf ("foo %s bar", long_i + long_j);
~^ ~~~~~~~~~~~~~~~
+ | |
+ char * long int
%ld
{ dg-end-multiline-output "" } */
}
@@ -147,6 +176,8 @@ void test_field_width_specifier (long l, int i1, int i2)
/* { dg-begin-multiline-output "" }
printf (" %*.*d ", l, i1, i2);
~^~~~ ~
+ | |
+ int long int
{ dg-end-multiline-output "" } */
}
@@ -158,12 +189,16 @@ void test_field_width_specifier_2 (char *d, long foo, long bar)
/* { dg-begin-multiline-output "" }
__builtin_sprintf (d, " %*ld ", foo, foo);
~^~~ ~~~
+ | |
+ int long int
{ dg-end-multiline-output "" } */
__builtin_sprintf (d, " %*ld ", foo + bar, foo); /* { dg-warning "28: field width specifier '\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */
/* { dg-begin-multiline-output "" }
__builtin_sprintf (d, " %*ld ", foo + bar, foo);
~^~~ ~~~~~~~~~
+ | |
+ int long int
{ dg-end-multiline-output "" } */
}
@@ -173,12 +208,16 @@ void test_field_precision_specifier (char *d, long foo, long bar)
/* { dg-begin-multiline-output "" }
__builtin_sprintf (d, " %.*ld ", foo, foo);
~~^~~ ~~~
+ | |
+ int long int
{ dg-end-multiline-output "" } */
__builtin_sprintf (d, " %.*ld ", foo + bar, foo); /* { dg-warning "29: field precision specifier '\\.\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */
/* { dg-begin-multiline-output "" }
__builtin_sprintf (d, " %.*ld ", foo + bar, foo);
~~^~~ ~~~~~~~~~
+ | |
+ int long int
{ dg-end-multiline-output "" } */
}
@@ -241,10 +280,14 @@ void test_macro (const char *msg)
/* { dg-begin-multiline-output "" }
printf("hello " INT_FMT " world", msg);
^~~~~~~~ ~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
#define INT_FMT "%i"
~^
+ |
+ int
%s
{ dg-end-multiline-output "" } */
#undef INT_FMT
@@ -257,10 +300,14 @@ void test_macro_2 (const char *msg)
/* { dg-begin-multiline-output "" }
printf("hello %" PRIu32 " world", msg);
^~~~~~~~~ ~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
#define PRIu32 "u"
^
+ |
+ unsigned int
{ dg-end-multiline-output "" } */
#undef PRIu32
}
@@ -295,6 +342,8 @@ void test_macro_4 (const char *msg)
/* { dg-begin-multiline-output "" }
#define FMT_STRING "hello %i world"
~^
+ |
+ int
%s
{ dg-end-multiline-output "" } */
#undef FMT_STRING
@@ -307,10 +356,14 @@ void test_non_contiguous_strings (void)
/* { dg-begin-multiline-output "" }
__builtin_printf(" %" "d ", 0.5);
^~~~ ~~~
+ |
+ double
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
__builtin_printf(" %" "d ", 0.5);
~~~~^
+ |
+ int
%" "f
{ dg-end-multiline-output "" } */
}
@@ -324,5 +377,7 @@ void test_const_arrays (void)
/* { dg-begin-multiline-output "" }
__builtin_printf(a, 0.5);
^ ~~~
+ |
+ double
{ dg-end-multiline-output "" } */
}
diff --git a/gcc/testsuite/gcc.dg/format/gcc_diag-1.c b/gcc/testsuite/gcc.dg/format/gcc_diag-1.c
index 4dcdb05..8761456 100644
--- a/gcc/testsuite/gcc.dg/format/gcc_diag-1.c
+++ b/gcc/testsuite/gcc.dg/format/gcc_diag-1.c
@@ -1,4 +1,4 @@
-/* Test for GCC diagnositc formats. */
+/* Test for GCC diagnostic formats. */
/* Origin: Kaveh Ghazi <ghazi@caip.rutgers.edu> */
/* { dg-do compile } */
/* { dg-options "-Wformat" } */
@@ -24,6 +24,7 @@ extern int diag (const char *, ...) ATTRIBUTE_DIAG(__gcc_diag__);
extern int tdiag (const char *, ...) ATTRIBUTE_DIAG(__gcc_tdiag__);
extern int cdiag (const char *, ...) ATTRIBUTE_DIAG(__gcc_cdiag__);
extern int cxxdiag (const char *, ...) ATTRIBUTE_DIAG(__gcc_cxxdiag__);
+extern int dump (const char *, ...) ATTRIBUTE_DIAG(__gcc_dump_printf__);
void
foo (int i, int i1, int i2, unsigned int u, double d, char *s, void *p,
@@ -39,36 +40,44 @@ foo (int i, int i1, int i2, unsigned int u, double d, char *s, void *p,
tdiag ("%%");
cdiag ("%%");
cxxdiag ("%%");
+ dump ("%%");
diag ("%d%i%o%u%x%c%s%p%%", i, i, u, u, u, i, s, p);
tdiag ("%d%i%o%u%x%c%s%p%%", i, i, u, u, u, i, s, p);
cdiag ("%d%i%o%u%x%c%s%p%%", i, i, u, u, u, i, s, p);
cxxdiag ("%d%i%o%u%x%c%s%p%%", i, i, u, u, u, i, s, p);
+ dump ("%d%i%o%u%x%c%s%p%%", i, i, u, u, u, i, s, p);
diag ("%qd%qi%qo%qu%qx%qc%qs%qp%<%%%'%>", i, i, u, u, u, i, s, p);
tdiag ("%qd%qi%qo%qu%qx%qc%qs%qp%<%%%'%>", i, i, u, u, u, i, s, p);
cdiag ("%qd%qi%qo%qu%qx%qc%qs%qp%<%%%'%>", i, i, u, u, u, i, s, p);
cxxdiag ("%qd%qi%qo%qu%qx%qc%qs%qp%<%%%'%>", i, i, u, u, u, i, s, p);
+ dump ("%qd%qi%qo%qu%qx%qc%qs%qp%<%%%'%>", i, i, u, u, u, i, s, p);
diag ("%ld%li%lo%lu%lx", l, l, ul, ul, ul);
tdiag ("%ld%li%lo%lu%lx", l, l, ul, ul, ul);
cdiag ("%ld%li%lo%lu%lx", l, l, ul, ul, ul);
cxxdiag ("%ld%li%lo%lu%lx", l, l, ul, ul, ul);
+ dump ("%ld%li%lo%lu%lx", l, l, ul, ul, ul);
diag ("%lld%lli%llo%llu%llx", ll, ll, ull, ull, ull);
tdiag ("%lld%lli%llo%llu%llx", ll, ll, ull, ull, ull);
cdiag ("%lld%lli%llo%llu%llx", ll, ll, ull, ull, ull);
cxxdiag ("%lld%lli%llo%llu%llx", ll, ll, ull, ull, ull);
+ dump ("%lld%lli%llo%llu%llx", ll, ll, ull, ull, ull);
diag ("%wd%wi%wo%wu%wx", ll, ll, ull, ull, ull);
tdiag ("%wd%wi%wo%wu%wx", ll, ll, ull, ull, ull);
cdiag ("%wd%wi%wo%wu%wx", ll, ll, ull, ull, ull);
cxxdiag ("%wd%wi%wo%wu%wx", ll, ll, ull, ull, ull);
+ dump ("%wd%wi%wo%wu%wx", ll, ll, ull, ull, ull);
diag ("%.*s", i, s);
tdiag ("%.*s", i, s);
cdiag ("%.*s", i, s);
cxxdiag ("%.*s", i, s);
+ dump ("%.*s", i, s);
/* Extensions provided in the diagnostic framework. */
diag ("%m");
tdiag ("%m");
cdiag ("%m");
cxxdiag ("%m");
+ dump ("%m");
/* Quote directives to avoid "warning: conversion used unquoted." */
tdiag ("%<%D%F%T%V%>", t1, t1, t1, t1);
@@ -87,27 +96,31 @@ foo (int i, int i1, int i2, unsigned int u, double d, char *s, void *p,
cxxdiag ("%<%+#A%+#D%+#E%+#F%+#T%+#V%>", t1, t1, t1, t1, t1, t1);
cxxdiag ("%C%L%O%P%Q", i, i, i, i, i);
- tdiag ("%v%qv%#v", i, i, i);
+ tdiag ("%v", i); /* { dg-warning "format" } */
cdiag ("%v%qv%#v", i, i, i);
- cxxdiag ("%v%qv%#v", i, i, i);
+ cxxdiag ("%v", i); /* { dg-warning "format" } */
tdiag ("%Z", v, v_len);
cdiag ("%Z", v, v_len);
cxxdiag ("%Z", v, v_len);
+ dump ("%Z", v, v_len);
/* Bad stuff with extensions. */
diag ("%m", i); /* { dg-warning "format" "extra arg" } */
tdiag ("%m", i); /* { dg-warning "format" "extra arg" } */
cdiag ("%m", i); /* { dg-warning "format" "extra arg" } */
cxxdiag ("%m", i); /* { dg-warning "format" "extra arg" } */
+ dump ("%m", i); /* { dg-warning "format" "extra arg" } */
diag ("%#m"); /* { dg-warning "format" "bogus modifier" } */
tdiag ("%#m"); /* { dg-warning "format" "bogus modifier" } */
cdiag ("%#m"); /* { dg-warning "format" "bogus modifier" } */
cxxdiag ("%#m"); /* { dg-warning "format" "bogus modifier" } */
+ dump ("%#m"); /* { dg-warning "format" "bogus modifier" } */
diag ("%+m"); /* { dg-warning "format" "bogus modifier" } */
tdiag ("%+m"); /* { dg-warning "format" "bogus modifier" } */
cdiag ("%+m"); /* { dg-warning "format" "bogus modifier" } */
cxxdiag ("%+m"); /* { dg-warning "format" "bogus modifier" } */
+ dump ("%+m"); /* { dg-warning "format" "bogus modifier" } */
diag ("%D", t1); /* { dg-warning "format" "bogus tree" } */
tdiag ("%A", t1); /* { dg-warning "format" "bogus tree" } */
tdiag ("%E", t1);
diff --git a/gcc/testsuite/gcc.dg/format/gcc_diag-10.c b/gcc/testsuite/gcc.dg/format/gcc_diag-10.c
index 9bda73b..2f6a002 100644
--- a/gcc/testsuite/gcc.dg/format/gcc_diag-10.c
+++ b/gcc/testsuite/gcc.dg/format/gcc_diag-10.c
@@ -15,9 +15,12 @@ typedef struct location_s
union tree_node;
typedef union tree_node *tree;
-/* Define gcall as a dummy type. The typedef must be provided for
+/* Define gimple as a dummy type. The typedef must be provided for
the C test to find the symbol. */
-typedef struct gcall gcall;
+typedef struct gimple gimple;
+
+/* Likewise for gimple. */
+typedef struct gimple gimple;
#define FORMAT(kind) __attribute__ ((format (__gcc_## kind ##__, 1, 2)))
@@ -25,15 +28,16 @@ void diag (const char*, ...) FORMAT (diag);
void cdiag (const char*, ...) FORMAT (cdiag);
void tdiag (const char*, ...) FORMAT (tdiag);
void cxxdiag (const char*, ...) FORMAT (cxxdiag);
+void dump (const char*, ...) FORMAT (dump_printf);
-void test_diag (tree t, gcall *gc)
+void test_diag (tree t, gimple *gc)
{
diag ("%<"); /* { dg-warning "unterminated quoting directive" } */
diag ("%>"); /* { dg-warning "unmatched quoting directive " } */
diag ("%<foo%<bar%>%>"); /* { dg-warning "nested quoting directive" } */
- diag ("%G", gc);
- diag ("%K", t);
+ diag ("%G", gc); /* { dg-warning "format" } */
+ diag ("%K", t); /* { dg-warning "format" } */
diag ("%R"); /* { dg-warning "unmatched color reset directive" } */
diag ("%r", ""); /* { dg-warning "unterminated color directive" } */
@@ -42,15 +46,12 @@ void test_diag (tree t, gcall *gc)
diag ("%r%r%R", "", "");
diag ("%r%R%r%R", "", "");
- diag ("%<%G%>", gc); /* { dg-warning ".G. conversion used within a quoted sequence" } */
- diag ("%<%K%>", t); /* { dg-warning ".K. conversion used within a quoted sequence" } */
-
diag ("%<%R%>"); /* { dg-warning "unmatched color reset directive" } */
diag ("%<%r%>", ""); /* { dg-warning "unterminated color directive" } */
diag ("%<%r%R%>", "");
}
-void test_cdiag (tree t, gcall *gc)
+void test_cdiag (tree t, gimple *gc)
{
cdiag ("%<"); /* { dg-warning "unterminated quoting directive" } */
cdiag ("%>"); /* { dg-warning "unmatched quoting directive " } */
@@ -90,7 +91,7 @@ void test_cdiag (tree t, gcall *gc)
cdiag ("%<%qT%>", t); /* { dg-warning ".q. flag used within a quoted sequence" } */
}
-void test_tdiag (tree t, gcall *gc)
+void test_tdiag (tree t, gimple *gc)
{
tdiag ("%<"); /* { dg-warning "unterminated quoting directive" } */
tdiag ("%>"); /* { dg-warning "unmatched quoting directive " } */
@@ -127,7 +128,7 @@ void test_tdiag (tree t, gcall *gc)
tdiag ("%<%qT%>", t); /* { dg-warning ".q. flag used within a quoted sequence" } */
}
-void test_cxxdiag (tree t, gcall *gc)
+void test_cxxdiag (tree t, gimple *gc)
{
cxxdiag ("%A", t); /* { dg-warning ".A. conversion used unquoted" } */
cxxdiag ("%D", t); /* { dg-warning ".D. conversion used unquoted" } */
@@ -160,3 +161,25 @@ void test_cxxdiag (tree t, gcall *gc)
cxxdiag ("%<%V%>", t);
cxxdiag ("%<%X%>", t);
}
+
+void test_dump (tree t, gimple *stmt)
+{
+ dump ("%<"); /* { dg-warning "unterminated quoting directive" } */
+ dump ("%>"); /* { dg-warning "unmatched quoting directive " } */
+ dump ("%<foo%<bar%>%>"); /* { dg-warning "nested quoting directive" } */
+
+ dump ("%R"); /* { dg-warning "unmatched color reset directive" } */
+ dump ("%r", ""); /* { dg-warning "unterminated color directive" } */
+ dump ("%r%r", "", ""); /* { dg-warning "unterminated color directive" } */
+ dump ("%r%R", "");
+ dump ("%r%r%R", "", "");
+ dump ("%r%R%r%R", "", "");
+
+ dump ("%<%R%>"); /* { dg-warning "unmatched color reset directive" } */
+ dump ("%<%r%>", ""); /* { dg-warning "unterminated color directive" } */
+ dump ("%<%r%R%>", "");
+
+ dump ("%E", stmt);
+ dump ("%T", t);
+ dump ("%G", stmt);
+}
diff --git a/gcc/testsuite/gcc.dg/format/pr72858.c b/gcc/testsuite/gcc.dg/format/pr72858.c
index b8c5829..7726094 100644
--- a/gcc/testsuite/gcc.dg/format/pr72858.c
+++ b/gcc/testsuite/gcc.dg/format/pr72858.c
@@ -28,12 +28,18 @@ test_x (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8x ", lexpr);
~~~^ ~~~~~
+ | |
+ | long int
+ unsigned int
%-8lx
{ dg-end-multiline-output "" } */
sprintf (d, " %-8x ", ulexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long unsigned int'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8x ", ulexpr);
~~~^ ~~~~~~
+ | |
+ | long unsigned int
+ unsigned int
%-8lx
{ dg-end-multiline-output "" } */
@@ -41,12 +47,18 @@ test_x (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8x ", llexpr);
~~~^ ~~~~~~
+ | |
+ | long long int
+ unsigned int
%-8llx
{ dg-end-multiline-output "" } */
sprintf (d, " %-8x ", ullexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long long unsigned int'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8x ", ullexpr);
~~~^ ~~~~~~~
+ | |
+ | long long unsigned int
+ unsigned int
%-8llx
{ dg-end-multiline-output "" } */
@@ -56,18 +68,27 @@ test_x (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8x ", fexpr);
~~~^ ~~~~~
+ | |
+ | double
+ unsigned int
%-8f
{ dg-end-multiline-output "" } */
sprintf (d, " %-8x ", dexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'double'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8x ", dexpr);
~~~^ ~~~~~
+ | |
+ | double
+ unsigned int
%-8f
{ dg-end-multiline-output "" } */
sprintf (d, " %-8x ", ldexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long double'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8x ", ldexpr);
~~~^ ~~~~~~
+ | |
+ | long double
+ unsigned int
%-8Lf
{ dg-end-multiline-output "" } */
@@ -76,6 +97,9 @@ test_x (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8x ", ptr);
~~~^ ~~~
+ | |
+ | void *
+ unsigned int
%-8p
{ dg-end-multiline-output "" } */
@@ -86,6 +110,9 @@ test_x (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8x ", s);
~~~^ ~
+ | |
+ | struct s
+ unsigned int
{ dg-end-multiline-output "" } */
}
@@ -105,12 +132,18 @@ test_lx (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lx ", iexpr);
~~~~^ ~~~~~
+ | |
+ | int
+ long unsigned int
%-8x
{ dg-end-multiline-output "" } */
sprintf (d, " %-8lx ", uiexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'unsigned int'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lx ", uiexpr);
~~~~^ ~~~~~~
+ | |
+ | unsigned int
+ long unsigned int
%-8x
{ dg-end-multiline-output "" } */
@@ -121,12 +154,18 @@ test_lx (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lx ", llexpr);
~~~~^ ~~~~~~
+ | |
+ | long long int
+ long unsigned int
%-8llx
{ dg-end-multiline-output "" } */
sprintf (d, " %-8lx ", ullexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'long long unsigned int'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lx ", ullexpr);
~~~~^ ~~~~~~~
+ | |
+ | long long unsigned int
+ long unsigned int
%-8llx
{ dg-end-multiline-output "" } */
@@ -136,18 +175,27 @@ test_lx (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lx ", fexpr);
~~~~^ ~~~~~
+ | |
+ | double
+ long unsigned int
%-8f
{ dg-end-multiline-output "" } */
sprintf (d, " %-8lx ", dexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'double'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lx ", dexpr);
~~~~^ ~~~~~
+ | |
+ | double
+ long unsigned int
%-8f
{ dg-end-multiline-output "" } */
sprintf (d, " %-8lx ", ldexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'long double'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lx ", ldexpr);
~~~~^ ~~~~~~
+ | |
+ | long double
+ long unsigned int
%-8Lf
{ dg-end-multiline-output "" } */
}
@@ -170,12 +218,18 @@ test_o (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8o ", lexpr);
~~~^ ~~~~~
+ | |
+ | long int
+ unsigned int
%-8lo
{ dg-end-multiline-output "" } */
sprintf (d, " %-8o ", ulexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long unsigned int'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8o ", ulexpr);
~~~^ ~~~~~~
+ | |
+ | long unsigned int
+ unsigned int
%-8lo
{ dg-end-multiline-output "" } */
@@ -183,12 +237,18 @@ test_o (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8o ", llexpr);
~~~^ ~~~~~~
+ | |
+ | long long int
+ unsigned int
%-8llo
{ dg-end-multiline-output "" } */
sprintf (d, " %-8o ", ullexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long long unsigned int'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8o ", ullexpr);
~~~^ ~~~~~~~
+ | |
+ | long long unsigned int
+ unsigned int
%-8llo
{ dg-end-multiline-output "" } */
}
@@ -208,12 +268,18 @@ test_lo (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lo ", iexpr);
~~~~^ ~~~~~
+ | |
+ | int
+ long unsigned int
%-8o
{ dg-end-multiline-output "" } */
sprintf (d, " %-8lo ", uiexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'unsigned int'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lo ", uiexpr);
~~~~^ ~~~~~~
+ | |
+ | unsigned int
+ long unsigned int
%-8o
{ dg-end-multiline-output "" } */
@@ -224,12 +290,18 @@ test_lo (char *d,
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lo ", llexpr);
~~~~^ ~~~~~~
+ | |
+ | long long int
+ long unsigned int
%-8llo
{ dg-end-multiline-output "" } */
sprintf (d, " %-8lo ", ullexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'long long unsigned int'" } */
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8lo ", ullexpr);
~~~~^ ~~~~~~~
+ | |
+ | long long unsigned int
+ long unsigned int
%-8llo
{ dg-end-multiline-output "" } */
}
@@ -246,6 +318,9 @@ test_e (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8e ", iexpr);
~~~^ ~~~~~
+ | |
+ | int
+ double
%-8d
{ dg-end-multiline-output "" } */
@@ -257,6 +332,9 @@ test_e (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8e ", ldexpr);
~~~^ ~~~~~~
+ | |
+ | long double
+ double
%-8Le
{ dg-end-multiline-output "" } */
}
@@ -273,6 +351,9 @@ test_Le (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8Le ", iexpr);
~~~~^ ~~~~~
+ | |
+ | int
+ long double
%-8d
{ dg-end-multiline-output "" } */
@@ -282,6 +363,9 @@ test_Le (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8Le ", fexpr);
~~~~^ ~~~~~
+ | |
+ | double
+ long double
%-8e
{ dg-end-multiline-output "" } */
@@ -289,6 +373,9 @@ test_Le (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8Le ", dexpr);
~~~~^ ~~~~~
+ | |
+ | double
+ long double
%-8e
{ dg-end-multiline-output "" } */
@@ -307,6 +394,9 @@ test_E (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8E ", iexpr);
~~~^ ~~~~~
+ | |
+ | int
+ double
%-8d
{ dg-end-multiline-output "" } */
@@ -318,6 +408,9 @@ test_E (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8E ", ldexpr);
~~~^ ~~~~~~
+ | |
+ | long double
+ double
%-8LE
{ dg-end-multiline-output "" } */
}
@@ -334,6 +427,9 @@ test_LE (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8LE ", iexpr);
~~~~^ ~~~~~
+ | |
+ | int
+ long double
%-8d
{ dg-end-multiline-output "" } */
@@ -341,6 +437,9 @@ test_LE (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8LE ", fexpr);
~~~~^ ~~~~~
+ | |
+ | double
+ long double
%-8E
{ dg-end-multiline-output "" } */
@@ -348,6 +447,9 @@ test_LE (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, " %-8LE ", dexpr);
~~~~^ ~~~~~
+ | |
+ | double
+ long double
%-8E
{ dg-end-multiline-output "" } */
@@ -367,18 +469,24 @@ test_everything (char *d, long lexpr)
/* { dg-begin-multiline-output "" }
sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr);
~~~^~~~~~ ~~~~~
+ | |
+ int long int
{ dg-end-multiline-output "" } */
/* { dg-warning "28: field precision specifier '\\.\\*' expects argument of type 'int', but argument 4 has type 'long int'" "" { target *-*-* } test_everything_sprintf } */
/* { dg-begin-multiline-output "" }
sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr);
~~~~~^~~~ ~~~~~
+ | |
+ int long int
{ dg-end-multiline-output "" } */
/* { dg-warning "31: format '%lld' expects argument of type 'long long int', but argument 5 has type 'long int'" "" { target *-*-* } test_everything_sprintf } */
/* { dg-begin-multiline-output "" }
sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr);
~~~~~~~~^ ~~~~~
+ | |
+ long long int long int
%-+*.*ld
{ dg-end-multiline-output "" } */
}
diff --git a/gcc/testsuite/gcc.dg/format/pr78498.c b/gcc/testsuite/gcc.dg/format/pr78498.c
index 4b53a68..b911b04 100644
--- a/gcc/testsuite/gcc.dg/format/pr78498.c
+++ b/gcc/testsuite/gcc.dg/format/pr78498.c
@@ -7,6 +7,8 @@ void f (void)
/* { dg-begin-multiline-output "" }
__builtin_printf ("%i", "");
~^ ~~
+ | |
+ int char *
%s
{ dg-end-multiline-output "" } */
}
diff --git a/gcc/testsuite/gcc.dg/graphite/pr82451.c b/gcc/testsuite/gcc.dg/graphite/pr82451.c
index 802b931..b2c439b 100644
--- a/gcc/testsuite/gcc.dg/graphite/pr82451.c
+++ b/gcc/testsuite/gcc.dg/graphite/pr82451.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-O -floop-parallelize-all" } */
-static int a[];
+extern int a[];
int b[1];
int c;
static void
diff --git a/gcc/testsuite/gcc.dg/guality/const-volatile.c b/gcc/testsuite/gcc.dg/guality/const-volatile.c
index 3bfca0d..21f84b5 100644
--- a/gcc/testsuite/gcc.dg/guality/const-volatile.c
+++ b/gcc/testsuite/gcc.dg/guality/const-volatile.c
@@ -80,8 +80,6 @@ main (int argc, char **argv)
/* { dg-final { gdb-test "@main" "type:vs" "volatile struct { const long cli; const signed char csc; }" } } */
-/* { dg-final { gdb-test "@main" "type:cvip" "int * const volatile" } } */
-
/* { dg-final { gdb-test "@main" "type:bar" "struct bar { short s; const short cs; volatile short vs; const volatile short cvs; volatile long long vll; }" } } */
/* { dg-final { gdb-test "@main" "type:foo" "struct foo { const long cli; const signed char csc; }" } } */
/* { dg-final { gdb-test "@main" "type:cfoo" "const struct foo { const long cli; const signed char csc; }" } } */
diff --git a/gcc/testsuite/gcc.dg/guality/zero-length-array.c b/gcc/testsuite/gcc.dg/guality/zero-length-array.c
new file mode 100644
index 0000000..33f34d9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/guality/zero-length-array.c
@@ -0,0 +1,21 @@
+/* PR debug/86985 */
+/* { dg-do run } */
+/* { dg-options "-g" } */
+
+struct {
+ int foo;
+ int bar[0];
+} zla; /* Zero length array. */
+
+struct {
+ int foo;
+ int bar[];
+} fam; /* Flexible array member. */
+
+int
+main ()
+{
+ /* { dg-final { gdb-test . "type:zla" "struct { int foo; int bar[0]; }" } } */
+ /* { dg-final { gdb-test . "type:fam" "struct { int foo; int bar[]; }" } } */
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/init-string-3.c b/gcc/testsuite/gcc.dg/init-string-3.c
new file mode 100644
index 0000000..e955f2e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/init-string-3.c
@@ -0,0 +1,58 @@
+/* PR tree-optimization/71625 - missing strlen optimization on different
+ array initialization style
+
+ Verify that zero-length array initialization results in the expected
+ array sizes.
+
+ { dg-do compile }
+ { dg-options "-Wall -Wno-unused-local-typedefs" } */
+
+#define A(expr) typedef char A[-1 + 2 * !!(expr)];
+
+const char a[] = { };
+
+A (sizeof a == 0);
+
+
+const char b[0] = { };
+
+A (sizeof b == 0);
+
+
+const char c[0] = { 1 }; /* { dg-warning "excess elements" } */
+
+A (sizeof c == 0);
+
+
+void test_auto_empty (void)
+{
+ const char a[] = { };
+
+ A (sizeof a == 0);
+}
+
+void test_auto_zero_length (void)
+{
+ const char a[0] = { };
+
+ A (sizeof a == 0);
+
+ const char b[0] = { 0 }; /* { dg-warning "excess elements" } */
+
+ A (sizeof b == 0);
+
+ const char c[0] = "";
+
+ A (sizeof c == 0);
+}
+
+
+void test_compound_zero_length (void)
+{
+ A (sizeof (const char[]){ } == 0);
+ A (sizeof (const char[0]){ } == 0);
+ A (sizeof (const char[0]){ 0 } == 0); /* { dg-warning "excess elements" } */
+ A (sizeof (const char[0]){ 1 } == 0); /* { dg-warning "excess elements" } */
+ A (sizeof (const char[0]){ "" } == 0);
+ A (sizeof (const char[0]){ "1" } == 0); /* { dg-warning "too long" } */
+}
diff --git a/gcc/testsuite/gcc.dg/ipa/pr85734.c b/gcc/testsuite/gcc.dg/ipa/pr85734.c
index e5fa21f..cbd524b 100644
--- a/gcc/testsuite/gcc.dg/ipa/pr85734.c
+++ b/gcc/testsuite/gcc.dg/ipa/pr85734.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -Wsuggest-attribute=malloc" } */
+/* { dg-options "-O2 -Wsuggest-attribute=malloc -fdelete-null-pointer-checks" } */
__attribute__((noinline))
static void *f1(__SIZE_TYPE__ sz) /* { dg-bogus "function might be candidate for attribute 'malloc'" } */
diff --git a/gcc/testsuite/gcc.dg/ipa/propmalloc-1.c b/gcc/testsuite/gcc.dg/ipa/propmalloc-1.c
index 9a95f81..4813627 100644
--- a/gcc/testsuite/gcc.dg/ipa/propmalloc-1.c
+++ b/gcc/testsuite/gcc.dg/ipa/propmalloc-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-ipa-pure-const-details" } */
+/* { dg-options "-O2 -fdump-ipa-pure-const-details -fdelete-null-pointer-checks" } */
__attribute__((noinline, no_icf, used))
static void *f(__SIZE_TYPE__ n)
diff --git a/gcc/testsuite/gcc.dg/ipa/propmalloc-2.c b/gcc/testsuite/gcc.dg/ipa/propmalloc-2.c
index 95b2fd7..4ad8fb1 100644
--- a/gcc/testsuite/gcc.dg/ipa/propmalloc-2.c
+++ b/gcc/testsuite/gcc.dg/ipa/propmalloc-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-ipa-pure-const-details" } */
+/* { dg-options "-O2 -fdump-ipa-pure-const-details -fdelete-null-pointer-checks" } */
__attribute__((noinline, used, no_icf))
static void *foo (__SIZE_TYPE__ n)
diff --git a/gcc/testsuite/gcc.dg/ipa/propmalloc-3.c b/gcc/testsuite/gcc.dg/ipa/propmalloc-3.c
index 13558dd..c322544 100644
--- a/gcc/testsuite/gcc.dg/ipa/propmalloc-3.c
+++ b/gcc/testsuite/gcc.dg/ipa/propmalloc-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-ipa-pure-const-details" } */
+/* { dg-options "-O2 -fdump-ipa-pure-const-details -fdelete-null-pointer-checks" } */
static void *foo(__SIZE_TYPE__, int) __attribute__((noinline, no_icf, used));
diff --git a/gcc/testsuite/gcc.dg/lto/pr45736_0.c b/gcc/testsuite/gcc.dg/lto/pr45736_0.c
index d481c45..cb7811b 100644
--- a/gcc/testsuite/gcc.dg/lto/pr45736_0.c
+++ b/gcc/testsuite/gcc.dg/lto/pr45736_0.c
@@ -1,5 +1,5 @@
/* { dg-lto-do link } */
-/* { dg-lto-options {{-flto -r -nostdlib -O}} } */
+/* { dg-lto-options {{-flto -r -O}} } */
/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
extern void baz (void);
diff --git a/gcc/testsuite/gcc.dg/lto/pr52634_0.c b/gcc/testsuite/gcc.dg/lto/pr52634_0.c
index 7aba0cd..5e14ad9 100644
--- a/gcc/testsuite/gcc.dg/lto/pr52634_0.c
+++ b/gcc/testsuite/gcc.dg/lto/pr52634_0.c
@@ -1,7 +1,7 @@
/* { dg-require-weak "" } */
/* { dg-require-alias "" } */
/* { dg-lto-do link } */
-/* { dg-lto-options {{-flto -r -nostdlib -flto-partition=1to1}} */
+/* { dg-lto-options {{-flto -r -flto-partition=1to1}} */
/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
extern int cfliteValueCallBacks;
void baz (int *);
diff --git a/gcc/testsuite/gcc.dg/lto/pr83719_0.c b/gcc/testsuite/gcc.dg/lto/pr83719_0.c
index 6d5c16d..cd4cab3 100644
--- a/gcc/testsuite/gcc.dg/lto/pr83719_0.c
+++ b/gcc/testsuite/gcc.dg/lto/pr83719_0.c
@@ -1,4 +1,5 @@
/* { dg-lto-do assemble } */
+/* { dg-skip-if "split DWARF unsupported" { *-*-darwin* } } */
/* { dg-lto-options { { -flto -g -gsplit-dwarf } } } */
/* Empty. */
diff --git a/gcc/testsuite/gcc.dg/lto/pr85248_0.c b/gcc/testsuite/gcc.dg/lto/pr85248_0.c
index df61ac9..902f4b6 100644
--- a/gcc/testsuite/gcc.dg/lto/pr85248_0.c
+++ b/gcc/testsuite/gcc.dg/lto/pr85248_0.c
@@ -2,8 +2,13 @@
/* { dg-lto-do run } */
/* { dg-lto-options { { -flto -O2 } } } */
-extern void test_alias (int s, int e) __asm__ (__USER_LABEL_PREFIX__ "test");
-extern void test_noreturn (int s, int e) __asm__ (__USER_LABEL_PREFIX__ "test")
+#define STR1(X) #X
+#define STR2(X) STR1(X)
+
+extern void test_alias (int s, int e)
+ __asm__ (STR2(__USER_LABEL_PREFIX__) "test");
+extern void test_noreturn (int s, int e)
+ __asm__ (STR2(__USER_LABEL_PREFIX__) "test")
__attribute__ ((__noreturn__));
extern inline __attribute__ ((__always_inline__, __gnu_inline__)) void
diff --git a/gcc/testsuite/gcc.dg/lvalue-5.c b/gcc/testsuite/gcc.dg/lvalue-5.c
index 514f35e..ff3598a 100644
--- a/gcc/testsuite/gcc.dg/lvalue-5.c
+++ b/gcc/testsuite/gcc.dg/lvalue-5.c
@@ -1,7 +1,7 @@
/* Test assignment to elements of a string literal is a warning, not
an error. PR 27676. */
/* { dg-do compile } */
-/* { dg-options "-pedantic-errors" } */
+/* { dg-options "-O -pedantic-errors" } */
void
f (void)
diff --git a/gcc/testsuite/gcc.dg/memcmp-1.c b/gcc/testsuite/gcc.dg/memcmp-1.c
index a79db51..619cf9b 100644
--- a/gcc/testsuite/gcc.dg/memcmp-1.c
+++ b/gcc/testsuite/gcc.dg/memcmp-1.c
@@ -8,8 +8,13 @@
#include <string.h>
#include <stdint.h>
-int lib_memcmp(const void *a, const void *b, size_t n) asm("memcmp");
-int lib_strncmp(const char *a, const char *b, size_t n) asm("strncmp");
+#define STR1(X) #X
+#define STR2(X) STR1(X)
+
+int lib_memcmp(const void *a, const void *b, size_t n)
+ asm(STR2(__USER_LABEL_PREFIX__) "memcmp");
+int lib_strncmp(const char *a, const char *b, size_t n)
+ asm(STR2(__USER_LABEL_PREFIX__) "strncmp");
#ifndef NRAND
#ifdef TEST_ALL
diff --git a/gcc/testsuite/gcc.dg/missing-header-fixit-3.c b/gcc/testsuite/gcc.dg/missing-header-fixit-3.c
new file mode 100644
index 0000000..a692b4d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/missing-header-fixit-3.c
@@ -0,0 +1,21 @@
+/* Example of a fix-it hint that adds a #include directive,
+ adding them to the top of the file, given that there is no
+ pre-existing #include. */
+
+/* { dg-options "-fdiagnostics-show-caret -fdiagnostics-show-line-numbers" } */
+
+void test (int i, int j)
+{
+ printf ("%i of %i\n", i, j); /* { dg-warning "implicit declaration" } */
+ /* { dg-message "include '<stdio.h>' or provide a declaration of 'printf'" "" { target *-*-* } 1 } */
+#if 0
+/* { dg-begin-multiline-output "" }
+9 | printf ("%i of %i\n", i, j);
+ | ^~~~~~
+ { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
++ |+#include <stdio.h>
+1 | /* Example of a fix-it hint that adds a #include directive,
+ { dg-end-multiline-output "" } */
+#endif
+}
diff --git a/gcc/testsuite/gcc.dg/missing-header-fixit-4.c b/gcc/testsuite/gcc.dg/missing-header-fixit-4.c
new file mode 100644
index 0000000..0ed3e2c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/missing-header-fixit-4.c
@@ -0,0 +1,23 @@
+/* Example of a fix-it hint that adds a #include directive,
+ adding them after a pre-existing #include directive. */
+#include "empty.h"
+int the_next_line;
+
+/* { dg-options "-fdiagnostics-show-caret -fdiagnostics-show-line-numbers" } */
+
+void test (int i, int j)
+{
+ printf ("%i of %i\n", i, j); /* { dg-line printf } */
+ /* { dg-warning "implicit declaration of function" "" { target *-*-* } printf } */
+ /* { dg-warning "incompatible implicit declaration" "" { target *-*-* } printf } */
+ /* { dg-begin-multiline-output "" }
+10 | printf ("%i of %i\n", i, j);
+ | ^~~~~~
+ { dg-end-multiline-output "" } */
+ /* { dg-message "include '<stdio.h>' or provide a declaration of 'printf'" "" { target *-*-* } 4 } */
+ /* { dg-begin-multiline-output "" }
+3 | #include "empty.h"
++ |+#include <stdio.h>
+4 | int the_next_line;
+ { dg-end-multiline-output "" } */
+}
diff --git a/gcc/testsuite/gcc.dg/nested-func-11.c b/gcc/testsuite/gcc.dg/nested-func-11.c
new file mode 100644
index 0000000..01096b4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/nested-func-11.c
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-omit-frame-pointer" } */
+
+int __attribute__((noipa)) foo (int i)
+{
+ int a;
+
+ void __attribute__((noipa)) nested2 (int i)
+ {
+ a = i;
+ }
+
+ void __attribute__((noipa)) nested1 (int i)
+ {
+ int b[32];
+
+ for (int j = 0; j < 32; j++)
+ b[j] = i + j;
+
+ nested2 (b[i]);
+ }
+
+ nested1 (i);
+
+ return a;
+}
+
+int main (void)
+{
+ if (foo (4) != 8)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/param-type-mismatch.c b/gcc/testsuite/gcc.dg/param-type-mismatch.c
index 9498a74..9e654a9 100644
--- a/gcc/testsuite/gcc.dg/param-type-mismatch.c
+++ b/gcc/testsuite/gcc.dg/param-type-mismatch.c
@@ -1,4 +1,4 @@
-/* { dg-options "-fdiagnostics-show-caret" } */
+/* { dg-options "-fdiagnostics-show-caret -Wpointer-sign" } */
/* A collection of calls where argument 2 is of the wrong type. */
@@ -12,6 +12,8 @@ int test_1 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_1 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-message "expected 'const char \\*' but argument is of type 'int'" "" { target *-*-* } callee_1 } */
/* { dg-begin-multiline-output "" }
@@ -30,6 +32,8 @@ int test_2 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_2 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-message "expected 'const char \\*' but argument is of type 'int'" "" { target *-*-* } callee_2 } */
/* { dg-begin-multiline-output "" }
@@ -51,6 +55,8 @@ int test_3 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_3 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-message "expected 'const char \\*' but argument is of type 'int'" "" { target *-*-* } callee_3 } */
/* { dg-begin-multiline-output "" }
@@ -69,6 +75,8 @@ int test_4 (int first, const char *second, float third)
/* { dg-begin-multiline-output "" }
return callee_4 (first, second, third);
^~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
/* { dg-message "expected 'float' but argument is of type 'const char \\*'" "" { target *-*-* } callee_4 } */
/* { dg-begin-multiline-output "" }
@@ -87,6 +95,8 @@ int test_5 (int first, const char *second, float third)
/* { dg-begin-multiline-output "" }
return callee_5 (first, second, third);
^~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
/* { dg-message "expected 'float' but argument is of type 'const char \\*'" "" { target *-*-* } callee_5 } */
/* { dg-begin-multiline-output "" }
@@ -105,6 +115,8 @@ int test_6 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_6 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-message " expected 'int \\(\\*\\)\\(int, int\\)' but argument is of type 'int'" "" { target *-*-* } callee_6 } */
/* { dg-begin-multiline-output "" }
@@ -123,6 +135,8 @@ int test_7 (int first, int second, float third)
/* { dg-begin-multiline-output "" }
return callee_7 (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-message " expected 'int \\(\\*\\)\\(int, int\\)' but argument is of type 'int'" "" { target *-*-* } callee_7 } */
/* { dg-begin-multiline-output "" }
@@ -130,3 +144,43 @@ int test_7 (int first, int second, float third)
^~~~~~~~~~~~~~~~~
{ dg-end-multiline-output "" } */
}
+
+/* -Wincompatible-pointer-types for a parameter. */
+
+extern int callee_8 (int one, float *two, float (three)); /* { dg-line callee_8 } */
+
+int test_8 (int first, int *second, float third)
+{
+ return callee_8 (first, second, third); /* { dg-warning "passing argument 2 of 'callee_8' from incompatible pointer type" } */
+ /* { dg-begin-multiline-output "" }
+ return callee_8 (first, second, third);
+ ^~~~~~
+ |
+ int *
+ { dg-end-multiline-output "" } */
+ /* { dg-message "expected 'float \\*' but argument is of type 'int \\*'" "" { target *-*-* } callee_8 } */
+ /* { dg-begin-multiline-output "" }
+ extern int callee_8 (int one, float *two, float (three));
+ ~~~~~~~^~~
+ { dg-end-multiline-output "" } */
+}
+
+/* -Wpointer-sign for a parameter. */
+
+extern int callee_9 (int one, int *two, float (three)); /* { dg-line callee_9 } */
+
+int test_9 (int first, unsigned int *second, float third)
+{
+ return callee_9 (first, second, third); /* { dg-warning "pointer targets in passing argument 2 of 'callee_9' differ in signedness" } */
+ /* { dg-begin-multiline-output "" }
+ return callee_9 (first, second, third);
+ ^~~~~~
+ |
+ unsigned int *
+ { dg-end-multiline-output "" } */
+ /* { dg-message "expected 'int \\*' but argument is of type 'unsigned int \\*'" "" { target *-*-* } callee_9 } */
+ /* { dg-begin-multiline-output "" }
+ extern int callee_9 (int one, int *two, float (three));
+ ~~~~~^~~
+ { dg-end-multiline-output "" } */
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-group-test-1.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-group-test-1.c
new file mode 100644
index 0000000..962cba69
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-group-test-1.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-fdiagnostics-show-caret" } */
+
+extern void __emit_warning (const char *message);
+
+static void test_1 (void)
+{
+ __emit_warning ("warning 1");
+}
+
+/* { dg-begin-multiline-output "" }
+================================= BEGIN GROUP ==============================
+PREFIX
+ __emit_warning ("warning 1");
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
+PREFIX: message for note
+PREFIX: some more detail
+PREFIX: yet more detail
+---------------------------------- END GROUP -------------------------------
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+================================= BEGIN GROUP ==============================
+PREFIX: an unrelated message
+---------------------------------- END GROUP -------------------------------
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw-line-numbers.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw-line-numbers.c
new file mode 100644
index 0000000..63e5855
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw-line-numbers.c
@@ -0,0 +1,120 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdiagnostics-show-caret -fdiagnostics-show-line-numbers" } */
+
+/* This is a collection of unittests for diagnostic_show_locus;
+ see the overview in diagnostic_plugin_test_show_locus.c.
+
+ In particular, note the discussion of why we need a very long line here:
+01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+ and that we can't use macros in this file. */
+
+void test_simple (void)
+{
+#if 0
+ myvar = myvar.x; /* { dg-warning "test" } */
+
+/* { dg-begin-multiline-output "" }
+14 | myvar = myvar.x;
+ | ~~~~~^~
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+void test_multiline (void)
+{
+#if 0
+ x = (first_function ()
+ + second_function ()); /* { dg-warning "test" } */
+
+/* { dg-begin-multiline-output "" }
+26 | x = (first_function ()
+ | ~~~~~~~~~~~~~~~~~
+27 | + second_function ());
+ | ^ ~~~~~~~~~~~~~~~~~~
+ | |
+ | label
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+void test_very_wide_line (void)
+{
+#if 0
+ float f = foo * bar; /* { dg-warning "95: test" } */
+/* { dg-begin-multiline-output "" }
+ | 0 0 0 0 0 0 1
+ | 4 5 6 7 8 9 0
+ | 0123456789012345678901234567890123456789012345678901234567890123456789
+43 | float f = foo * bar;
+ | ~~~~^~~~~
+ | |
+ | label
+ | bar * foo
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+/* Unit test for rendering of insertion fixit hints
+ (example taken from PR 62316). */
+
+void test_fixit_insert (void)
+{
+#if 0
+ int a[2][2] = { 0, 1 , 2, 3 }; /* { dg-warning "insertion hints" } */
+/* { dg-begin-multiline-output "" }
+63 | int a[2][2] = { 0, 1 , 2, 3 };
+ | ^~~~
+ | { }
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+/* Unit test for rendering of "remove" fixit hints. */
+
+void test_fixit_remove (void)
+{
+#if 0
+ int a;; /* { dg-warning "example of a removal hint" } */
+/* { dg-begin-multiline-output "" }
+77 | int a;;
+ | ^
+ | -
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+/* Unit test for rendering of "replace" fixit hints. */
+
+void test_fixit_replace (void)
+{
+#if 0
+ gtk_widget_showall (dlg); /* { dg-warning "example of a replacement hint" } */
+/* { dg-begin-multiline-output "" }
+91 | gtk_widget_showall (dlg);
+ | ^~~~~~~~~~~~~~~~~~
+ | gtk_widget_show_all
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+
+/* Unit test for rendering of fix-it hints that add new lines. */
+
+void test_fixit_insert_newline (void)
+{
+#if 0
+ switch (op)
+ {
+ case 'a':
+ x = a;
+ case 'b': /* { dg-warning "newline insertion" } */
+ x = b;
+ }
+/* { dg-begin-multiline-output "" }
+109 | x = a;
++++ |+ break;
+110 | case 'b':
+ | ^~~~~~~~
+ { dg-end-multiline-output "" } */
+#endif
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c
index 513c0af..be6f103 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c
@@ -44,6 +44,8 @@ void test_multiline (void)
~~~~~~~~~~~~~~~~~
+ second_function ());
^ ~~~~~~~~~~~~~~~~~~
+ |
+ label
{ dg-end-multiline-output "" } */
#endif
}
@@ -66,6 +68,8 @@ void test_many_lines (void)
/* { dg-begin-multiline-output "" }
x = (first_function_with_a_very_long_name (lorem, ipsum, dolor, sit, amet,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ |
+ label 1
consectetur, adipiscing, elit,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sed, eiusmod, tempor,
@@ -76,6 +80,9 @@ void test_many_lines (void)
~~~~~~~~~~~~~~~~~~~~~~
+ second_function_with_a_very_long_name (lorem, ipsum, dolor, sit,
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | |
+ | label 2
+ label 0
amet, consectetur,
~~~~~~~~~~~~~~~~~~
adipiscing, elit, sed,
@@ -115,13 +122,32 @@ void test_caret_within_proper_range (void)
void test_very_wide_line (void)
{
#if 0
- float f = foo * bar; /* { dg-warning "95: test" } */
+ float x = foo * bar; /* { dg-warning "95: test" } */
/* { dg-begin-multiline-output "" }
0 0 0 0 0 0 1
4 5 6 7 8 9 0
6789012345678901234567890123456789012345678901234567890123456789012345
- float f = foo * bar;
+ x = foo * bar;
+ ~ ~~~~^~~~~
+ | |
+ label 1 label 0
+ bar * foo
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+void test_very_wide_line_2 (void)
+{
+#if 0
+ float x = foo * bar; /* { dg-warning "95: test" } */
+/* { dg-begin-multiline-output "" }
+ 0 0 0 0 0 0 1
+ 4 5 6 7 8 9 0
+ 6789012345678901234567890123456789012345678901234567890123456789012345
+ = foo * bar;
~~~~^~~~~
+ |
+ label 0
bar * foo
{ dg-end-multiline-output "" } */
#endif
@@ -226,27 +252,69 @@ void test_many_nested_locations (void)
^
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
^~~~~ ^~~~~ ^~~~~ ^~~ ^~~~ ^~~~~~~~~~~ ^~~~~~~~~~ ^~~~
+ | | | | | | | |
+ | | | | label label label label
+ label label label label
LOREM IPSUM DOLOR SIT AMET CONSECTETUR ADIPISCING ELIT
sed do eiusmod tempor incididunt ut labore et dolore magna
^~~ ^~ ^~~~~~~ ^~~~~~ ^~~~~~~~~~ ^~ ^~~~~~ ^~ ^~~~~~ ^~~~~
+ | | | | | | | | | |
+ | | | | | | | | label label
+ | | | | | | label label
+ | | label label label label
+ | label
+ label
SED DO EIUSMOD TEMPOR INCIDIDUNT UT LABORE ET DOLORE MAGNA
aliqua. Ut enim ad minim veniam, quis nostrud exercitation
^~~~~~ ^~ ^~~~ ^~ ^~~~~ ^~~~~~ ^~~~ ^~~~~~~ ^~~~~~~~~~~~
+ | | | | | | | | |
+ | | | | | | | label label
+ | | | | label label label
+ | | | label
+ | | label
+ label label
ALIQUA UT ENIM AD MINIM VENIAM QUIS NOSTRUD EXERCITATION
ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis
^~~~~~~ ^~~~~~~ ^~~~ ^~ ^~~~~~~ ^~ ^~ ^~~~~~~ ^~~~~~~~~ ^~~~
+ | | | | | | | | | |
+ | | | | | | | label label label
+ | | | | | | label
+ | | | | label label
+ | | | label
+ label label label
ULLAMCO LABORIS NISI UT ALIQUIP EX EA COMMODO CONSEQUAT DUIS
aute irure dolor in reprehenderit in voluptate velit esse cillum
^~~~ ^~~~~ ^~~~~ ^~ ^~~~~~~~~~~~~ ^~ ^~~~~~~~~ ^~~~~ ^~~~ ^~~~~~
+ | | | | | | | | | |
+ | | | | | | | | | label
+ | | | | | | label label label
+ | | | | label label
+ | label label label
+ label
AUTE IRURE DOLOR IN REPREHENDERIT IN VOLUPTATE VELIT ESSE CILLUM
dolore eu fugiat nulla pariatur. Excepteur sint occaecat
^~~~~~ ^~ ^~~~~~ ^~~~~ ^~~~~~~~ ^~~~~~~~~ ^~~~ ^~~~~~~~
+ | | | | | | | |
+ | | | | | | | label
+ | | label label label label label
+ label label
DOLORE EU FUGIAT NULLA PARIATUR EXCEPTEUR SINT OCCAECAT
cupidatat non proident, sunt in culpa qui officia deserunt
^~~~~~~~~ ^~~ ^~~~~~~~ ^~~~ ^~ ^~~~~ ^~~ ^~~~~~~ ^~~~~~~~
+ | | | | | | | | |
+ | | | | | | | label label
+ | | | | | label label
+ | | | | label
+ | | label label
+ label label
CUPIDATAT NON PROIDENT SUNT IN CULPA QUI OFFICIA DESERUNT
mollit anim id est laborum.
^~~~~~ ^~~~ ^~ ^~~ ^~~~~~~
+ | | | | |
+ | | | | label
+ | | | label
+ | | label
+ label label
MOLLIT ANIM ID EST LABORUM
{ dg-end-multiline-output "" } */
}
@@ -264,6 +332,7 @@ void test_fixit_insert_newline (void)
x = b;
}
/* { dg-begin-multiline-output "" }
+ x = a;
+ break;
case 'b':
^~~~~~~~
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color-line-numbers.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color-line-numbers.c
new file mode 100644
index 0000000..0453c52
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color-line-numbers.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdiagnostics-show-caret -fplugin-arg-diagnostic_plugin_test_show_locus-color -fdiagnostics-show-line-numbers" } */
+
+/* This is a collection of unittests for diagnostic_show_locus;
+ see the overview in diagnostic_plugin_test_show_locus.c.
+
+ In particular, note the discussion of why we need a very long line here:
+01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+ and that we can't use macros in this file. */
+
+void test_multiline (void)
+{
+#if 0
+ x = (first_function ()
+ + second_function ()); /* { dg-warning "test" } */
+
+/* { dg-begin-multiline-output "" }
+14 | x = (first_function ()
+ | ~~~~~~~~~~~~~~~~~
+15 | + second_function ());
+ | ^ ~~~~~~~~~~~~~~~~~~
+ | |
+ | label
+ { dg-end-multiline-output "" } */
+#endif
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color.c
index 4cc406d..7ae3801 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color.c
@@ -44,6 +44,8 @@ void test_multiline (void)
~~~~~~~~~~~~~~~~~
+ second_function ());
^ ~~~~~~~~~~~~~~~~~~
+ |
+ label
{ dg-end-multiline-output "" } */
#endif
}
@@ -66,6 +68,8 @@ void test_many_lines (void)
/* { dg-begin-multiline-output "" }
x = (first_function_with_a_very_long_name (lorem, ipsum, dolor, sit, amet,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ |
+ label 1
 consectetur, adipiscing, elit,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 sed, eiusmod, tempor,
@@ -76,6 +80,9 @@ void test_many_lines (void)
~~~~~~~~~~~~~~~~~~~~~~
+ second_function_with_a_very_long_name (lorem, ipsum, dolor, sit,
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | |
+ | label 2
+ label 0
 amet, consectetur,
~~~~~~~~~~~~~~~~~~
 adipiscing, elit, sed,
@@ -115,13 +122,15 @@ void test_caret_within_proper_range (void)
void test_very_wide_line (void)
{
#if 0
- float f = foo * bar; /* { dg-warning "95: test" } */
+ float x = foo * bar; /* { dg-warning "95: test" } */
/* { dg-begin-multiline-output "" }
0 0 0 0 0 0 1
4 5 6 7 8 9 0
6789012345678901234567890123456789012345678901234567890123456789012345
- float f = foo * bar;
- ~~~~^~~~~
+ x = foo * bar;
+ ~ ~~~~^~~~~
+ | |
+ label 1 label 0
bar * foo
{ dg-end-multiline-output "" } */
#endif
@@ -208,6 +217,7 @@ void test_fixit_insert_newline (void)
x = b;
}
/* { dg-begin-multiline-output "" }
+ x = a;
+ break;
case 'b':
^~~~~~~~
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-no-labels.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-no-labels.c
new file mode 100644
index 0000000..4c06368
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-no-labels.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdiagnostics-show-caret -fno-diagnostics-show-labels" } */
+
+/* Verify that -fno-diagnostics-show-labels works. */
+
+/* This is a collection of unittests for diagnostic_show_locus;
+ see the overview in diagnostic_plugin_test_show_locus.c.
+
+ In particular, note the discussion of why we need a very long line here:
+01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+ and that we can't use macros in this file. */
+
+void test_multiline (void)
+{
+#if 0
+ x = (first_function ()
+ + second_function ()); /* { dg-warning "test" } */
+
+ /* This shouldn't have a label. */
+ /* { dg-begin-multiline-output "" }
+ x = (first_function ()
+ ~~~~~~~~~~~~~~~~~
+ + second_function ());
+ ^ ~~~~~~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+#endif
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_group_plugin.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_group_plugin.c
new file mode 100644
index 0000000..3083e12
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_group_plugin.c
@@ -0,0 +1,234 @@
+/* { dg-options "-O" } */
+
+#include "gcc-plugin.h"
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "stringpool.h"
+#include "toplev.h"
+#include "basic-block.h"
+#include "hash-table.h"
+#include "vec.h"
+#include "ggc.h"
+#include "basic-block.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-fold.h"
+#include "tree-eh.h"
+#include "gimple-expr.h"
+#include "is-a.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "tree.h"
+#include "tree-pass.h"
+#include "intl.h"
+#include "plugin-version.h"
+#include "c-family/c-common.h"
+#include "diagnostic.h"
+#include "context.h"
+
+int plugin_is_GPL_compatible;
+
+/* A custom pass for emitting dummy warnings from the middle-end. */
+
+const pass_data pass_data_test_groups =
+{
+ GIMPLE_PASS, /* type */
+ "test_groups", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ PROP_ssa, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_test_groups : public gimple_opt_pass
+{
+public:
+ pass_test_groups(gcc::context *ctxt)
+ : gimple_opt_pass(pass_data_test_groups, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ bool gate (function *) { return true; }
+ virtual unsigned int execute (function *);
+
+}; // class pass_test_groups
+
+/* Determine if STMT is a call with NUM_ARGS arguments to a function
+ named FUNCNAME.
+ If so, return STMT as a gcall *. Otherwise return NULL. */
+
+static gcall *
+check_for_named_call (gimple *stmt,
+ const char *funcname, unsigned int num_args)
+{
+ gcc_assert (funcname);
+
+ gcall *call = dyn_cast <gcall *> (stmt);
+ if (!call)
+ return NULL;
+
+ tree fndecl = gimple_call_fndecl (call);
+ if (!fndecl)
+ return NULL;
+
+ if (strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), funcname))
+ return NULL;
+
+ if (gimple_call_num_args (call) != num_args)
+ {
+ error_at (stmt->location, "expected number of args: %i (got %i)",
+ num_args, gimple_call_num_args (call));
+ return NULL;
+ }
+
+ return call;
+}
+
+/* Emit a warning at LOC. */
+
+static void
+emit_warning (location_t loc)
+{
+ source_range src_range = get_range_from_loc (line_table, loc);
+ warning_at (loc, 0, "range %i:%i-%i:%i",
+ LOCATION_LINE (src_range.m_start),
+ LOCATION_COLUMN (src_range.m_start),
+ LOCATION_LINE (src_range.m_finish),
+ LOCATION_COLUMN (src_range.m_finish));
+}
+
+/* Code for simulating the emission of a warning from the middle-end.
+ Emit a warning for each call to a function named "__emit_warning". */
+
+static void
+test_groups (gimple *stmt)
+{
+ gcall *call = check_for_named_call (stmt, "__emit_warning", 1);
+ if (!call)
+ return;
+
+ /* We expect an ADDR_EXPR with a STRING_CST inside it for the
+ initial arg. */
+ tree t_addr_string = gimple_call_arg (call, 0);
+ if (TREE_CODE (t_addr_string) != ADDR_EXPR)
+ {
+ error_at (call->location, "string literal required for arg 1");
+ return;
+ }
+
+ tree t_string = TREE_OPERAND (t_addr_string, 0);
+ if (TREE_CODE (t_string) != STRING_CST)
+ {
+ error_at (call->location, "string literal required for arg 1");
+ return;
+ }
+
+ {
+ auto_diagnostic_group d;
+ if (warning_at (call->location, 0, "%s", call,
+ TREE_STRING_POINTER (t_string)))
+ {
+ inform (call->location, "message for note");
+ inform (call->location, " some more detail");
+ inform (call->location, " yet more detail");
+ }
+ }
+ inform (call->location, "an unrelated message");
+}
+
+/* Call test_groups on every statement within FUN. */
+
+unsigned int
+pass_test_groups::execute (function *fun)
+{
+ gimple_stmt_iterator gsi;
+ basic_block bb;
+
+ FOR_EACH_BB_FN (bb, fun)
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ test_groups (stmt);
+ }
+
+ return 0;
+}
+
+/* Custom diagnostic callback, to avoid having the path in the
+ expected output. */
+
+void
+test_diagnostic_starter (diagnostic_context *context,
+ diagnostic_info *diagnostic)
+{
+ pp_set_prefix (context->printer, xstrdup ("PREFIX: "));
+}
+
+/* Custom diagnostic callback, to avoid having the path in the
+ expected output. */
+
+void
+test_diagnostic_start_span_fn (diagnostic_context *context,
+ expanded_location exploc)
+{
+ pp_string (context->printer, "START_SPAN_FN: ");
+ pp_newline (context->printer);
+}
+
+/* Custom diagnostic callback: loudly announce a new diagnostic group. */
+
+static void
+test_begin_group_cb (diagnostic_context * context)
+{
+ pp_string (context->printer,
+ "================================= BEGIN GROUP ==============================");
+ pp_newline (context->printer);
+}
+
+/* Custom diagnostic callback: loudly announce the end of a
+ diagnostic group. */
+
+static void
+test_end_group_cb (diagnostic_context * context)
+{
+ pp_string (context->printer,
+ "---------------------------------- END GROUP -------------------------------");
+ pp_newline_and_flush (context->printer);
+}
+
+/* Entrypoint for the plugin.
+ Install custom callbacks into the global_dc.
+ Create and register the custom pass. */
+
+int
+plugin_init (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version)
+{
+ struct register_pass_info pass_info;
+ const char *plugin_name = plugin_info->base_name;
+ int argc = plugin_info->argc;
+ struct plugin_argument *argv = plugin_info->argv;
+
+ if (!plugin_default_version_check (version, &gcc_version))
+ return 1;
+
+ diagnostic_starter (global_dc) = test_diagnostic_starter;
+ global_dc->start_span = test_diagnostic_start_span_fn;
+ global_dc->begin_group_cb = test_begin_group_cb;
+ global_dc->end_group_cb = test_end_group_cb;
+
+ pass_info.pass = new pass_test_groups (g);
+ pass_info.reference_pass_name = "*warn_function_noreturn";
+ pass_info.ref_pass_instance_number = 1;
+ pass_info.pos_op = PASS_POS_INSERT_AFTER;
+ register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
+ &pass_info);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c
index 0bdd877..71e6740 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.c
@@ -41,7 +41,7 @@ show_tree (tree node)
return;
gcc_rich_location richloc (EXPR_LOCATION (node));
- richloc.add_expr (node);
+ richloc.add_expr (node, NULL);
if (richloc.get_num_locations () < 2)
{
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
index 1d340aa..a55efaf 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
@@ -145,9 +145,12 @@ custom_diagnostic_finalizer (diagnostic_context *context,
static void
add_range (rich_location *richloc, location_t start, location_t finish,
- bool show_caret_p)
+ enum range_display_kind range_display_kind
+ = SHOW_RANGE_WITHOUT_CARET,
+ const range_label *label = NULL)
{
- richloc->add_range (make_location (start, start, finish), show_caret_p);
+ richloc->add_range (make_location (start, start, finish), range_display_kind,
+ label);
}
/* Exercise the diagnostic machinery to emit various warnings,
@@ -175,8 +178,8 @@ test_show_locus (function *fun)
{
const int line = fnstart_line + 2;
rich_location richloc (line_table, get_loc (line, 15));
- add_range (&richloc, get_loc (line, 10), get_loc (line, 14), false);
- add_range (&richloc, get_loc (line, 16), get_loc (line, 16), false);
+ add_range (&richloc, get_loc (line, 10), get_loc (line, 14));
+ add_range (&richloc, get_loc (line, 16), get_loc (line, 16));
warning_at (&richloc, 0, "test");
}
@@ -184,28 +187,32 @@ test_show_locus (function *fun)
{
const int line = fnstart_line + 2;
rich_location richloc (line_table, get_loc (line, 24));
- add_range (&richloc, get_loc (line, 6), get_loc (line, 22), false);
- add_range (&richloc, get_loc (line, 26), get_loc (line, 43), false);
+ add_range (&richloc, get_loc (line, 6), get_loc (line, 22));
+ add_range (&richloc, get_loc (line, 26), get_loc (line, 43));
warning_at (&richloc, 0, "test");
}
if (0 == strcmp (fnname, "test_multiline"))
{
const int line = fnstart_line + 2;
- rich_location richloc (line_table, get_loc (line + 1, 7));
- add_range (&richloc, get_loc (line, 7), get_loc (line, 23), false);
- add_range (&richloc, get_loc (line + 1, 9), get_loc (line + 1, 26),
- false);
+ text_range_label label ("label");
+ rich_location richloc (line_table, get_loc (line + 1, 7), &label);
+ add_range (&richloc, get_loc (line, 7), get_loc (line, 23));
+ add_range (&richloc, get_loc (line + 1, 9), get_loc (line + 1, 26));
warning_at (&richloc, 0, "test");
}
if (0 == strcmp (fnname, "test_many_lines"))
{
const int line = fnstart_line + 2;
- rich_location richloc (line_table, get_loc (line + 5, 7));
- add_range (&richloc, get_loc (line, 7), get_loc (line + 4, 65), false);
+ text_range_label label0 ("label 0");
+ text_range_label label1 ("label 1");
+ text_range_label label2 ("label 2");
+ rich_location richloc (line_table, get_loc (line + 5, 7), &label0);
+ add_range (&richloc, get_loc (line, 7), get_loc (line + 4, 65),
+ SHOW_RANGE_WITHOUT_CARET, &label1);
add_range (&richloc, get_loc (line + 5, 9), get_loc (line + 10, 61),
- false);
+ SHOW_RANGE_WITHOUT_CARET, &label2);
warning_at (&richloc, 0, "test");
}
@@ -231,20 +238,46 @@ test_show_locus (function *fun)
}
/* Example of a very wide line, where the information of interest
- is beyond the width of the terminal (hardcoded above). */
+ is beyond the width of the terminal (hardcoded above), with
+ a secondary location that exactly fits on the left-margin. */
if (0 == strcmp (fnname, "test_very_wide_line"))
{
const int line = fnstart_line + 2;
global_dc->show_ruler_p = true;
+ text_range_label label0 ("label 0");
+ text_range_label label1 ("label 1");
rich_location richloc (line_table,
make_location (get_loc (line, 94),
get_loc (line, 90),
- get_loc (line, 98)));
+ get_loc (line, 98)),
+ &label0);
+ richloc.add_range (get_loc (line, 35), SHOW_RANGE_WITHOUT_CARET,
+ &label1);
richloc.add_fixit_replace ("bar * foo");
warning_at (&richloc, 0, "test");
global_dc->show_ruler_p = false;
}
+ /* Likewise, but with a secondary location that's immediately before
+ the left margin; the location and label should be gracefully dropped. */
+ if (0 == strcmp (fnname, "test_very_wide_line_2"))
+ {
+ const int line = fnstart_line + 2;
+ global_dc->show_ruler_p = true;
+ text_range_label label0 ("label 0");
+ text_range_label label1 ("label 1");
+ rich_location richloc (line_table,
+ make_location (get_loc (line, 94),
+ get_loc (line, 90),
+ get_loc (line, 98)),
+ &label0);
+ richloc.add_fixit_replace ("bar * foo");
+ richloc.add_range (get_loc (line, 34), SHOW_RANGE_WITHOUT_CARET,
+ &label1);
+ warning_at (&richloc, 0, "test");
+ global_dc->show_ruler_p = false;
+ }
+
/* Example of multiple carets. */
if (0 == strcmp (fnname, "test_multiple_carets"))
{
@@ -252,7 +285,7 @@ test_show_locus (function *fun)
location_t caret_a = get_loc (line, 7);
location_t caret_b = get_loc (line, 11);
rich_location richloc (line_table, caret_a);
- add_range (&richloc, caret_b, caret_b, true);
+ add_range (&richloc, caret_b, caret_b, SHOW_RANGE_WITH_CARET);
global_dc->caret_chars[0] = 'A';
global_dc->caret_chars[1] = 'B';
warning_at (&richloc, 0, "test");
@@ -370,7 +403,7 @@ test_show_locus (function *fun)
location_t caret_a = get_loc (line, 5);
location_t caret_b = get_loc (line - 1, 19);
rich_location richloc (line_table, caret_a);
- richloc.add_range (caret_b, true);
+ richloc.add_range (caret_b, SHOW_RANGE_WITH_CARET);
global_dc->caret_chars[0] = '1';
global_dc->caret_chars[1] = '2';
warning_at (&richloc, 0, "test");
@@ -391,13 +424,14 @@ test_show_locus (function *fun)
/* Example of many locations and many fixits.
Underline (separately) every word in a comment, and convert them
- to upper case. */
+ to upper case. Give all of the ranges labels (sharing one label). */
if (0 == strcmp (fnname, "test_many_nested_locations"))
{
const char *file = LOCATION_FILE (fnstart);
const int start_line = fnstart_line + 2;
const int finish_line = start_line + 7;
location_t loc = get_loc (start_line - 1, 2);
+ text_range_label label ("label");
rich_location richloc (line_table, loc);
for (int line = start_line; line <= finish_line; line++)
{
@@ -418,7 +452,7 @@ test_show_locus (function *fun)
location_t word
= make_location (start_of_word, start_of_word,
end_of_word);
- richloc.add_range (word, true);
+ richloc.add_range (word, SHOW_RANGE_WITH_CARET, &label);
/* Add a fixit, converting to upper case. */
char_span word_span = content.subspan (start_idx, idx - start_idx);
diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp
index 5a19fc9..46246a2 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
+++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
@@ -69,11 +69,16 @@ set plugin_test_list [list \
{ poly-int-05_plugin.c poly-int-test-1.c } \
{ poly-int-06_plugin.c poly-int-test-1.c } \
{ poly-int-07_plugin.c poly-int-test-1.c } \
+ { diagnostic_group_plugin.c \
+ diagnostic-group-test-1.c } \
{ diagnostic_plugin_test_show_locus.c \
diagnostic-test-show-locus-bw.c \
diagnostic-test-show-locus-color.c \
+ diagnostic-test-show-locus-no-labels.c \
+ diagnostic-test-show-locus-bw-line-numbers.c \
+ diagnostic-test-show-locus-color-line-numbers.c \
diagnostic-test-show-locus-parseable-fixits.c \
- diagnostic-test-show-locus-generate-patch.c } \
+ diagnostic-test-show-locus-generate-patch.c }\
{ diagnostic_plugin_test_tree_expression_range.c \
diagnostic-test-expressions-1.c } \
{ diagnostic_plugin_show_trees.c \
diff --git a/gcc/testsuite/gcc.dg/plugin/poly-int-07_plugin.c b/gcc/testsuite/gcc.dg/plugin/poly-int-07_plugin.c
index e3203d9..53819d9 100644
--- a/gcc/testsuite/gcc.dg/plugin/poly-int-07_plugin.c
+++ b/gcc/testsuite/gcc.dg/plugin/poly-int-07_plugin.c
@@ -1,5 +1,5 @@
/* Not worth spending time optimizing this. */
-/* { dg-options "-O" } */
+/* { dg-options "-O0" } */
#include "config.h"
#include "gcc-plugin.h"
diff --git a/gcc/testsuite/gcc.dg/pointer-range-check-1.c b/gcc/testsuite/gcc.dg/pointer-range-check-1.c
new file mode 100644
index 0000000..9868658
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pointer-range-check-1.c
@@ -0,0 +1,37 @@
+/* { dg-do compile { target { ilp32 || lp64 } } } */
+/* { dg-options "-O2 -fno-ipa-icf -fdump-tree-optimized" } */
+
+/* All four functions should be folded to:
+
+ (sizetype) (a + 15 - b) < 30. */
+
+_Bool
+f1 (char *a, char *b)
+{
+ return (a + 16 <= b) || (b + 16 <= a);
+}
+
+_Bool
+f2 (char *a, char *b)
+{
+ return (a + 15 < b) || (b + 15 < a);
+}
+
+_Bool
+f3 (char *a, char *b)
+{
+ return (a + 16 <= b) | (b + 16 <= a);
+}
+
+_Bool
+f4 (char *a, char *b)
+{
+ return (a + 15 < b) | (b + 15 < a);
+}
+
+/* { dg-final { scan-tree-dump-times { = [^\n]* - [^\n]*;} 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-times { = [^\n]* \+ [^\n]*;} 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-times { = [^\n]*\ > [^\n]*;} 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-not {=[^\n]*\ < [^\n]*;} "optimized" } } */
+/* { dg-final { scan-tree-dump-times { \+ 15} 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-times { > 30} 4 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/pointer-range-check-2.c b/gcc/testsuite/gcc.dg/pointer-range-check-2.c
new file mode 100644
index 0000000..4ccc413
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pointer-range-check-2.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-ipa-icf -fwrapv-pointer -fdump-tree-optimized" } */
+
+_Bool
+f1 (char *a, char *b)
+{
+ return (a + 16 <= b) || (b + 16 <= a);
+}
+
+_Bool
+f2 (char *a, char *b)
+{
+ return (a + 15 < b) || (b + 15 < a);
+}
+
+_Bool
+f3 (char *a, char *b)
+{
+ return (a + 16 <= b) | (b + 16 <= a);
+}
+
+_Bool
+f4 (char *a, char *b)
+{
+ return (a + 15 < b) | (b + 15 < a);
+}
+
+/* { dg-final { scan-tree-dump-not { = [^\n]* - [^\n]*;} "optimized" } } */
+/* { dg-final { scan-tree-dump-times { = [^\n]* \+ [^\n]*;} 8 "optimized" } } */
+/* { dg-final { scan-tree-dump-times { \+ 15} 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-times { \+ 16} 4 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/pr33092.c b/gcc/testsuite/gcc.dg/pr33092.c
deleted file mode 100644
index 8f48fab..0000000
--- a/gcc/testsuite/gcc.dg/pr33092.c
+++ /dev/null
@@ -1,6 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O1 -fno-tree-salias" } */
-int foo ()
-{
- return 0;
-}
diff --git a/gcc/testsuite/gcc.dg/pr41837.c b/gcc/testsuite/gcc.dg/pr41837.c
index 1ff9915..de6bd06 100644
--- a/gcc/testsuite/gcc.dg/pr41837.c
+++ b/gcc/testsuite/gcc.dg/pr41837.c
@@ -1,6 +1,6 @@
/* PR middle-end/41837 */
/* { dg-do compile } */
-/* { dg-options "-fipa-struct-reorg -O -fwhole-program -fprofile-generate" } */
+/* { dg-options "-O -fwhole-program -fprofile-generate" } */
typedef struct { int a, b; } T1;
typedef struct S1 *T2;
diff --git a/gcc/testsuite/gcc.dg/pr41841.c b/gcc/testsuite/gcc.dg/pr41841.c
index 595bc75..8bce4e6 100644
--- a/gcc/testsuite/gcc.dg/pr41841.c
+++ b/gcc/testsuite/gcc.dg/pr41841.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/41841 */
/* { dg-do compile } */
-/* { dg-options "-O -fipa-struct-reorg -fwhole-program -fipa-cp" } */
+/* { dg-options "-O -fwhole-program -fipa-cp" } */
typedef struct S *T;
typedef struct { } *U;
diff --git a/gcc/testsuite/gcc.dg/pr42250.c b/gcc/testsuite/gcc.dg/pr42250.c
index 3ba8e84..21b29ba 100644
--- a/gcc/testsuite/gcc.dg/pr42250.c
+++ b/gcc/testsuite/gcc.dg/pr42250.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fipa-struct-reorg" } */
+/* { dg-options "-O2" } */
extern double log10 (double __x);
extern double ceil (double __x);
diff --git a/gcc/testsuite/gcc.dg/pr43084.c b/gcc/testsuite/gcc.dg/pr43084.c
index 2afc484..f70ed86 100644
--- a/gcc/testsuite/gcc.dg/pr43084.c
+++ b/gcc/testsuite/gcc.dg/pr43084.c
@@ -1,6 +1,6 @@
/* PR debug/43084 */
/* { dg-do compile } */
-/* { dg-options "-O1 -fipa-struct-reorg -fwhole-program -fcompare-debug" } */
+/* { dg-options "-O1 -fwhole-program -fcompare-debug" } */
/* { dg-xfail-if "" { powerpc-ibm-aix* } } */
struct S
diff --git a/gcc/testsuite/gcc.dg/pr43317.c b/gcc/testsuite/gcc.dg/pr43317.c
index cc5832a..de81c44 100644
--- a/gcc/testsuite/gcc.dg/pr43317.c
+++ b/gcc/testsuite/gcc.dg/pr43317.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O -fipa-struct-reorg -fwhole-program -g" } */
+/* { dg-options "-O -fwhole-program -g" } */
extern void *malloc(__SIZE_TYPE__);
diff --git a/gcc/testsuite/gcc.dg/pr51879-18.c b/gcc/testsuite/gcc.dg/pr51879-18.c
index 2944bea..1601225 100644
--- a/gcc/testsuite/gcc.dg/pr51879-18.c
+++ b/gcc/testsuite/gcc.dg/pr51879-18.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -ftree-tail-merge -fdump-tree-pre -fno-tree-copy-prop -fno-tree-dominator-opts -fno-tree-copyrename" } */
+/* { dg-options "-O2 -ftree-tail-merge -fdump-tree-pre -fno-tree-copy-prop -fno-tree-dominator-opts" } */
extern int foo (void);
diff --git a/gcc/testsuite/gcc.dg/pr69554-1.c b/gcc/testsuite/gcc.dg/pr69554-1.c
index 07ad0db..b979b55 100644
--- a/gcc/testsuite/gcc.dg/pr69554-1.c
+++ b/gcc/testsuite/gcc.dg/pr69554-1.c
@@ -12,6 +12,9 @@ int test_1 (const char *p, const char *q)
/* { dg-begin-multiline-output "" }
return (p + 1) + (q + 1);
~~~~~~~ ^ ~~~~~~~
+ | |
+ | const char *
+ const char *
{ dg-end-multiline-output "" } */
}
@@ -26,10 +29,14 @@ int test_2 (const char *p, const char *q)
/* { dg-begin-multiline-output "" }
return (p + 1)
~~~~~~~
+ |
+ const char *
+
^
(q + 1);
~~~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
}
@@ -43,16 +50,20 @@ int test_3 (const char *p, const char *q)
+ /* { dg-error "invalid operands" } */
(q + 1);
-/* { dg-locus "12" "" { target *-*-* } "44" } */
+/* { dg-locus "12" "" { target *-*-* } "51" } */
/* { dg-begin-multiline-output "" }
return (p + 1)
~~~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
+
^
(q + 1);
~~~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
}
@@ -68,12 +79,16 @@ int test_4 (const char *p, const char *q)
/* { dg-begin-multiline-output "" }
return (p + 1)
~~~~~~~
+ |
+ const char *
+
^
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
(q + 1);
~~~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
}
@@ -88,10 +103,12 @@ int test_5 (const char *p, const char *q)
+ /* { dg-error "invalid operands" } */
(q + 1); /* { dg-locus "14" } */
-/* { dg-locus "12" "" { target *-*-* } "88" } */
+/* { dg-locus "12" "" { target *-*-* } "103" } */
/* { dg-begin-multiline-output "" }
return (p + 1)
~~~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
+
@@ -100,6 +117,8 @@ int test_5 (const char *p, const char *q)
/* { dg-begin-multiline-output "" }
(q + 1);
~~~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
}
@@ -136,10 +155,12 @@ int test_6 (const char *p, const char *q)
fringilla sapien elit vitae nisl. Fusce mattis commodo risus
nec convallis. */
(q + 1); /* { dg-locus "14" } */
-/* { dg-locus "12" "" { target *-*-* } "125" } */
+/* { dg-locus "12" "" { target *-*-* } "144" } */
/* { dg-begin-multiline-output "" }
return (p + 1)
~~~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
+
@@ -148,5 +169,7 @@ int test_6 (const char *p, const char *q)
/* { dg-begin-multiline-output "" }
(q + 1);
~~~~~~~
+ |
+ const char *
{ dg-end-multiline-output "" } */
}
diff --git a/gcc/testsuite/gcc.dg/pr69627.c b/gcc/testsuite/gcc.dg/pr69627.c
index b7f56cd..bc48bb1 100644
--- a/gcc/testsuite/gcc.dg/pr69627.c
+++ b/gcc/testsuite/gcc.dg/pr69627.c
@@ -11,6 +11,8 @@ foo ()
/* { dg-begin-multiline-output "" }
t[1] / s;
~~~~ ^
+ |
+ float
{ dg-end-multiline-output "" } */
}
@@ -23,5 +25,7 @@ bar ()
/* { dg-begin-multiline-output "" }
t[1] / s[0];
~~~~ ^ ~~~~
+ | |
+ float const int *
{ dg-end-multiline-output "" } */
}
diff --git a/gcc/testsuite/gcc.dg/pr79342.c b/gcc/testsuite/gcc.dg/pr79342.c
new file mode 100644
index 0000000..958de55
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr79342.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -gsplit-dwarf -g3" } */
+/* { dg-additional-options "-march=skylake -mrtm -mabm" { target x86_64-*-* i?86-*-* } } */
+
+int a;
+void b(void);
+
+void e(int *);
+int f(void);
+
+void
+c(void)
+{
+ int d;
+ e(&d);
+ if (f())
+ b();
+}
diff --git a/gcc/testsuite/gcc.dg/pr83666.c b/gcc/testsuite/gcc.dg/pr83666.c
index 7bd1ed3..1c43c43 100644
--- a/gcc/testsuite/gcc.dg/pr83666.c
+++ b/gcc/testsuite/gcc.dg/pr83666.c
@@ -1,6 +1,6 @@
/* PR debug/83666 */
/* { dg-do compile } */
-/* { dg-options "-O2 -g --param=sccvn-max-scc-size=10 -Wno-psabi" } */
+/* { dg-options "-O2 -g -Wno-psabi" } */
/* { dg-additional-options "-fno-common" { target hppa*-*-hpux* } } */
typedef int __attribute__ ((vector_size (64))) V;
diff --git a/gcc/testsuite/gcc.dg/pr85195.c b/gcc/testsuite/gcc.dg/pr85195.c
index 0cc696b..fb21ee9 100644
--- a/gcc/testsuite/gcc.dg/pr85195.c
+++ b/gcc/testsuite/gcc.dg/pr85195.c
@@ -1,6 +1,6 @@
/* PR middle-end/85195 */
/* { dg-do compile { target int128 } } */
-/* { dg-options "-Wno-psabi -O -fno-tree-ccp --param=sccvn-max-scc-size=10" } */
+/* { dg-options "-Wno-psabi -O -fno-tree-ccp" } */
typedef __int128 V __attribute__ ((vector_size (16)));
diff --git a/gcc/testsuite/gcc.dg/pr85467.c b/gcc/testsuite/gcc.dg/pr85467.c
index 4895e37..fad94fc 100644
--- a/gcc/testsuite/gcc.dg/pr85467.c
+++ b/gcc/testsuite/gcc.dg/pr85467.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/85467 */
/* { dg-do compile } */
-/* { dg-options "-O2 -fno-tree-ccp --param=sccvn-max-scc-size=10" } */
+/* { dg-options "-O2 -fno-tree-ccp" } */
#define TEST(N, T) \
typedef T V##N __attribute__ ((__vector_size__ (sizeof (T)))); \
diff --git a/gcc/testsuite/gcc.dg/pr85799.c b/gcc/testsuite/gcc.dg/pr85799.c
new file mode 100644
index 0000000..0e93785
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr85799.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-profile_estimate" } */
+
+void unlikely();
+void likely();
+
+inline int expect_false(int b) {
+ return __builtin_expect(b, 0);
+}
+
+void inline_func_hint(int b) {
+ if (expect_false(b)) {
+ unlikely();
+ } else {
+ likely();
+ }
+}
+
+/* { dg-final { scan-tree-dump "_builtin_expect heuristics of edge" "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/pr86064.c b/gcc/testsuite/gcc.dg/pr86064.c
index 5be820c..3397427 100644
--- a/gcc/testsuite/gcc.dg/pr86064.c
+++ b/gcc/testsuite/gcc.dg/pr86064.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-skip-if "split DWARF unsupported" { *-*-darwin* } } */
/* { dg-options "-g -O2 -fno-var-tracking-assignments -gsplit-dwarf" } */
/* This used to fail with location views (implicitly) enabled, because
diff --git a/gcc/testsuite/gcc.dg/pr86835.c b/gcc/testsuite/gcc.dg/pr86835.c
new file mode 100644
index 0000000..a0ebc74
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr86835.c
@@ -0,0 +1,29 @@
+/* PR tree-optimization/86835 */
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -Wuninitialized" } */
+
+__attribute__((noipa)) void
+foo (int n, double *x, double *y)
+{ /* { dg-bogus "is used uninitialized in this function" "" { target *-*-* } 0 } */
+ int i;
+ double b = y[4];
+ for (i = 0; i < n; ++i)
+ y[3] += __builtin_sin (x[i] / b);
+ y[0] /= b;
+ y[1] /= b * b;
+ y[2] /= b;
+}
+
+int
+main ()
+{
+ double y[] = { 16.0, 64.0, 128.0, 0.0, 2.0 };
+ foo (0, y, y);
+ if (__builtin_fabs (y[0] - 8.0) > 0.0001
+ || __builtin_fabs (y[1] - 16.0) > 0.0001
+ || __builtin_fabs (y[2] - 64.0) > 0.0001
+ || y[3] != 0.0
+ || y[4] != 2.0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr87009.c b/gcc/testsuite/gcc.dg/pr87009.c
new file mode 100644
index 0000000..eb8a4ec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr87009.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-original" } */
+/* { dg-final { scan-tree-dump-times "return s \\^ x;" 4 "original" } } */
+
+int f1 (int x, int s)
+{
+ return ~(~(x|s)|x)|~(~(x|s)|s);
+}
+
+int f2 (int x, int s)
+{
+ return ~(~(~x&s)&~(x&~s));
+}
+
+int f3 (int x, int s)
+{
+ return ~((x|~s)&(~x|s));
+}
+
+int f4 (int x, int s)
+{
+ return (x|~s)^(~x|s);
+}
diff --git a/gcc/testsuite/gcc.dg/pr87024.c b/gcc/testsuite/gcc.dg/pr87024.c
new file mode 100644
index 0000000..a8a58aa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr87024.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fno-tree-dce" } */
+
+static inline void __attribute__((always_inline))
+mp ()
+{
+ (void) __builtin_va_arg_pack_len ();
+}
+
+void
+ui (void)
+{
+ mp ();
+}
diff --git a/gcc/testsuite/gcc.dg/pr87052.c b/gcc/testsuite/gcc.dg/pr87052.c
new file mode 100644
index 0000000..2affc48
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr87052.c
@@ -0,0 +1,41 @@
+/* PR middle-end/87052 - STRING_CST printing incomplete in Gimple dumps
+ { dg-do compile }
+ { dg-options "-fdump-tree-gimple" } */
+
+void sink (const void*, ...);
+
+void test (void)
+{
+ const char a[3] = "\000ab";
+
+ /* Expect the following in the dump:
+ a = "\x00ab"; */
+
+ const char b[] = { 'a', 0, 'b', 'c' };
+
+ /* Expect the following:
+ b = "a\x00bc"; */
+
+ const char c[] = "";
+
+ /* Expect the following:
+ c = ""; */
+
+ const char d[0] = { };
+
+ /* Expect the following:
+ d = ""; */
+
+ const char e[0] = "";
+
+ /* Expect nothing. */
+
+ sink (a, b, c, d, e);
+}
+
+/* { dg-final { scan-tree-dump-times "a = \"\\\\x00ab\";" 1 "gimple" } }
+ { dg-final { scan-tree-dump-times "b = \"a\\\\x00bc\";" 1 "gimple" } }
+ { dg-final { scan-tree-dump-times "c = \"\";" 1 "gimple" } }
+ { dg-final { scan-tree-dump-times "d = { *};" 1 "gimple" } }
+ { dg-final { scan-tree-dump-times "e = " 1 "gimple" } }
+ { dg-final { scan-tree-dump-times "e = {CLOBBER}" 1 "gimple" } } */
diff --git a/gcc/testsuite/gcc.dg/pr87054.c b/gcc/testsuite/gcc.dg/pr87054.c
new file mode 100644
index 0000000..3cb3b7d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr87054.c
@@ -0,0 +1,29 @@
+// { dg-do run }
+// { dg-options "-O2" }
+
+#ifndef T
+# if __SIZEOF_INT128__ && defined __SSE__
+# define T __int128
+# else
+# define T long
+# endif
+#endif
+#ifndef R
+# ifdef __SSE__
+# define R "x"
+# else
+# define R "r"
+# endif
+#endif
+
+
+typedef T A; // #define T to long or __int128
+struct B { char d; A c; } __attribute__((packed));
+struct B b[50]; // many elements to avoid loop unrolling
+
+int main () {
+ int i;
+ for (i = 0; i < sizeof(b) / sizeof(*b); i++) {
+ asm ("" : "+" R (b[i].c)); // #define R to "r" on ppc or "x" on x86_64
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pr87074.c b/gcc/testsuite/gcc.dg/pr87074.c
new file mode 100644
index 0000000..d838fcd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr87074.c
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -floop-unroll-and-jam --param unroll-jam-min-percent=0" } */
+long b;
+unsigned c[5];
+unsigned long long d = 3;
+int e, f, g;
+
+void h() {
+ for (; f < 11; f++) {
+ b = g;
+ for (e = 0; e < 5; e++) {
+ c[e] = e - b - (c[e] >> 5);
+ g = c[e];
+ }
+ }
+ if (c[0])
+ d = 0;
+}
+
+extern void abort(void);
+int main() {
+ h();
+ if (d != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/pr87092.c b/gcc/testsuite/gcc.dg/pr87092.c
new file mode 100644
index 0000000..4a6faeb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr87092.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fwrapv" } */
+
+int a, b;
+
+void
+c(void) {
+ if (b)
+ b = a / b;
+}
diff --git a/gcc/testsuite/gcc.dg/pr87099.c b/gcc/testsuite/gcc.dg/pr87099.c
new file mode 100644
index 0000000..599d721
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr87099.c
@@ -0,0 +1,21 @@
+/* PR middle-end/87099 */
+/* { dg-do compile } */
+/* { dg-options "-Wstringop-overflow" } */
+
+void bar (char *);
+
+int
+foo (int n)
+{
+ char v[n];
+ bar (v);
+ return __builtin_strncmp (&v[1], "aaa", 3);
+}
+
+int
+baz (int n, char *s)
+{
+ char v[n];
+ bar (v);
+ return __builtin_strncmp (&v[1], s, 3);
+}
diff --git a/gcc/testsuite/gcc.dg/pr87112.c b/gcc/testsuite/gcc.dg/pr87112.c
new file mode 100644
index 0000000..7510956
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr87112.c
@@ -0,0 +1,31 @@
+/* PR tree-optimization/87112 - ICE due to strnlen mixing integer types
+ { dg-do compile }
+ { dg-options "-Os -Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern size_t strnlen (const char*, size_t);
+
+size_t fi (int i)
+{
+ int n = i & 3;
+ return strnlen ("int", n);
+}
+
+size_t fui (unsigned i)
+{
+ unsigned n = i & 3;
+ return strnlen ("unsigned", n);
+}
+
+size_t fl (long i)
+{
+ long n = i & 3;
+ return strnlen ("long", n);
+}
+
+size_t fsz (size_t i)
+{
+ size_t n = i & 3;
+ return strnlen ("size_t", n);
+}
diff --git a/gcc/testsuite/gcc.dg/pr87117-1.c b/gcc/testsuite/gcc.dg/pr87117-1.c
new file mode 100644
index 0000000..06d7008
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr87117-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-inline -fno-tree-dce" } */
+
+int a, b, c;
+long *d;
+void fn1()
+{
+ for (; 0 < a;)
+ a++;
+}
+void fn3()
+{
+ for (; c; c++)
+ d[c] = 0;
+}
+void fn2()
+{
+ if (b)
+ fn3();
+ fn1();
+}
diff --git a/gcc/testsuite/gcc.dg/pr87117-2.c b/gcc/testsuite/gcc.dg/pr87117-2.c
new file mode 100644
index 0000000..aefa813
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr87117-2.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fcode-hoisting" } */
+
+void e();
+
+void a(int c, char **d)
+{
+ char b;
+ if (1 < c)
+ b = (char)(__INTPTR_TYPE__)d[0];
+ if (1 < c && b)
+ e();
+ while (1 < c)
+ ;
+}
diff --git a/gcc/testsuite/gcc.dg/pr87259.c b/gcc/testsuite/gcc.dg/pr87259.c
new file mode 100644
index 0000000..527a60a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr87259.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast" } */
+
+int a, b, c;
+int *e;
+float f;
+void h() {
+ for (int g;;) {
+ float d = b, i = 0 / f, j = a / (f * f), k, l = 0 / d;
+ c = i + j;
+ g = l;
+ e[g] = c / d * k / d;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pr87309.c b/gcc/testsuite/gcc.dg/pr87309.c
new file mode 100644
index 0000000..8bd5a44
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr87309.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-fopt-info-vec-optimized -O3" } */
+
+void a() {} /* { dg-bogus "note" } */
diff --git a/gcc/testsuite/gcc.dg/predict-1.c b/gcc/testsuite/gcc.dg/predict-1.c
index 4ba26e6..9e5605a 100644
--- a/gcc/testsuite/gcc.dg/predict-1.c
+++ b/gcc/testsuite/gcc.dg/predict-1.c
@@ -23,4 +23,4 @@ void foo (int bound)
}
}
-/* { dg-final { scan-tree-dump-times "guess loop iv compare heuristics of edge\[^:\]*: 36.0%" 4 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "guess loop iv compare heuristics of edge\[^:\]*: 36.00%" 4 "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-13.c b/gcc/testsuite/gcc.dg/predict-13.c
index 385be9e..c6da45f 100644
--- a/gcc/testsuite/gcc.dg/predict-13.c
+++ b/gcc/testsuite/gcc.dg/predict-13.c
@@ -20,5 +20,5 @@ int main(int argc, char **argv)
return 10;
}
-/* { dg-final { scan-tree-dump-times "combined heuristics of edge\[^:\]*: 33.3%" 3 "profile_estimate"} } */
-/* { dg-final { scan-tree-dump-times "combined heuristics of edge\[^:\]*: 0.1%" 2 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "combined heuristics of edge\[^:\]*: 33.30%" 3 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "combined heuristics of edge\[^:\]*: 0.05%" 2 "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-16.c b/gcc/testsuite/gcc.dg/predict-16.c
new file mode 100644
index 0000000..e1f331b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/predict-16.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-profile_estimate" } */
+
+#include <stdlib.h>
+#include <string.h>
+
+void *r;
+void *r2;
+void *r3;
+void *r4;
+void *r5;
+
+void *m (size_t s, int c)
+{
+ r = malloc (s);
+ if (r)
+ memset (r, 0, s);
+
+ r2 = calloc (s, 0);
+ if (r2)
+ memset (r2, 0, s);
+
+ r3 = __builtin_malloc (s);
+ if (r3)
+ memset (r3, 0, s);
+
+ r4 = __builtin_calloc (s, 0);
+ if (r4)
+ memset (r4, 0, s);
+
+ r5 = __builtin_realloc (r4, s);
+ if (r5)
+ memset (r4, 0, s);
+}
+
+/* { dg-final { scan-tree-dump-times "malloc returned non-NULL heuristics of edge\[^:\]*: 99.96%" 5 "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-17.c b/gcc/testsuite/gcc.dg/predict-17.c
new file mode 100644
index 0000000..5069aa4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/predict-17.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-profile_estimate" } */
+
+extern int global;
+
+void foo (int base)
+{
+ for (int i = 0; __builtin_expect_with_probability (i < base, 1, 0.05f); i++)
+ global++;
+}
+
+/* { dg-final { scan-tree-dump "first match heuristics: 5.00%" "profile_estimate"} } */
+/* { dg-final { scan-tree-dump "__builtin_expect_with_probability heuristics of edge .*->.*: 5.00%" "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-18.c b/gcc/testsuite/gcc.dg/predict-18.c
new file mode 100644
index 0000000..0c93638
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/predict-18.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-profile_estimate" } */
+
+extern int global;
+
+int x;
+
+short v = 0;
+short expected = 0;
+short max = ~0;
+#define STRONG 0
+
+void foo (int a, int b)
+{
+ if (__builtin_expect_with_probability (a < b, 1, 0.6f) > __builtin_expect (b, 0))
+ global++;
+
+ if (__builtin_expect_with_probability (a < b, 1, 0.777f) > 0)
+ global++;
+
+ if (__builtin_expect_with_probability (a < b, 1, 0.99) == __atomic_compare_exchange_n (&v, &expected, max, STRONG , __ATOMIC_RELAXED, __ATOMIC_RELAXED))
+ global++;
+
+ if (__builtin_expect_with_probability (a < 10, 1, 0.9f) > __builtin_expect_with_probability (b, 0, 0.8f))
+ global++;
+}
+
+/* { dg-final { scan-tree-dump "__builtin_expect_with_probability heuristics of edge .*->.*: 54.00%" "profile_estimate"} } */
+/* { dg-final { scan-tree-dump "__builtin_expect_with_probability heuristics of edge .*->.*: 77.70%" "profile_estimate"} } */
+/* { dg-final { scan-tree-dump "__builtin_expect_with_probability heuristics of edge .*->.*: 98.96%" "profile_estimate"} } */
+/* { dg-final { scan-tree-dump "__builtin_expect_with_probability heuristics of edge .*->.*: 71.99%" "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-19.c b/gcc/testsuite/gcc.dg/predict-19.c
new file mode 100644
index 0000000..38ca25a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/predict-19.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-profile_estimate" } */
+
+extern int global;
+
+void foo (int base)
+{
+ if (__builtin_expect_with_probability (base == 100, 1, 0.001f))
+ global++;
+}
+
+/* { dg-final { scan-tree-dump "first match heuristics: 0.10%" "profile_estimate"} } */
+/* { dg-final { scan-tree-dump "__builtin_expect_with_probability heuristics of edge .*->.*: 0.10%" "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-20.c b/gcc/testsuite/gcc.dg/predict-20.c
new file mode 100644
index 0000000..31d0183
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/predict-20.c
@@ -0,0 +1,23 @@
+/* PR tree-optimization/86925 */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-profile_estimate" } */
+
+int a, b;
+
+void
+c ()
+{
+ for (;;)
+ {
+ if (__builtin_expect (b < 0, 0))
+ break;
+ if (__builtin_expect (a, 1))
+ break;
+ }
+ int d = b < 0;
+ if (__builtin_expect (d, 0))
+ asm("");
+}
+
+/* { dg-final { scan-tree-dump-times "__builtin_expect heuristics of edge" 3 "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-21.c b/gcc/testsuite/gcc.dg/predict-21.c
new file mode 100644
index 0000000..5949e5f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/predict-21.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-profile_estimate -frounding-math" } */
+
+extern int global;
+
+void foo (int base)
+{
+ for (int i = 0; __builtin_expect_with_probability (i < base, 1, 0.05f); i++)
+ global++;
+}
+
+/* { dg-final { scan-tree-dump "first match heuristics: 5.00%" "profile_estimate"} } */
+/* { dg-final { scan-tree-dump "__builtin_expect_with_probability heuristics of edge .*->.*: 5.00%" "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-3.c b/gcc/testsuite/gcc.dg/predict-3.c
index 81addde..f3f4163 100644
--- a/gcc/testsuite/gcc.dg/predict-3.c
+++ b/gcc/testsuite/gcc.dg/predict-3.c
@@ -25,4 +25,4 @@ void foo (int bound)
}
}
-/* { dg-final { scan-tree-dump-times "guess loop iv compare heuristics of edge\[^:\]*: 64.0%" 3 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "guess loop iv compare heuristics of edge\[^:\]*: 64.00%" 3 "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-4.c b/gcc/testsuite/gcc.dg/predict-4.c
index 2ac2ec5..851afb1 100644
--- a/gcc/testsuite/gcc.dg/predict-4.c
+++ b/gcc/testsuite/gcc.dg/predict-4.c
@@ -15,4 +15,4 @@ void foo (int bound)
}
}
-/* { dg-final { scan-tree-dump " loop iv compare heuristics of edge\[^:\]*: 50.0%" "profile_estimate"} } */
+/* { dg-final { scan-tree-dump " loop iv compare heuristics of edge\[^:\]*: 50.00%" "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-5.c b/gcc/testsuite/gcc.dg/predict-5.c
index c80b292..5af5db1 100644
--- a/gcc/testsuite/gcc.dg/predict-5.c
+++ b/gcc/testsuite/gcc.dg/predict-5.c
@@ -21,4 +21,4 @@ void foo (int base, int bound)
}
}
-/* { dg-final { scan-tree-dump-times "guess loop iv compare heuristics of edge\[^:\]*: 64.0%" 4 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "guess loop iv compare heuristics of edge\[^:\]*: 64.00%" 4 "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-6.c b/gcc/testsuite/gcc.dg/predict-6.c
index 3acc764..5d6fbf1 100644
--- a/gcc/testsuite/gcc.dg/predict-6.c
+++ b/gcc/testsuite/gcc.dg/predict-6.c
@@ -21,4 +21,4 @@ void foo (int base, int bound)
}
}
-/* { dg-final { scan-tree-dump-times "guess loop iv compare heuristics of edge\[^:\]*: 36.0%" 4 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "guess loop iv compare heuristics of edge\[^:\]*: 36.00%" 4 "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-9.c b/gcc/testsuite/gcc.dg/predict-9.c
index 3823775..7e5ba08 100644
--- a/gcc/testsuite/gcc.dg/predict-9.c
+++ b/gcc/testsuite/gcc.dg/predict-9.c
@@ -19,5 +19,5 @@ void foo (int base)
}
}
-/* { dg-final { scan-tree-dump-times "first match heuristics: 2.2%" 3 "profile_estimate"} } */
-/* { dg-final { scan-tree-dump-times "first match heuristics: 5.5%" 1 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "first match heuristics: 2.20%" 3 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "first match heuristics: 5.50%" 1 "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/recip_sqrt_mult_1.c b/gcc/testsuite/gcc.dg/recip_sqrt_mult_1.c
new file mode 100644
index 0000000..188390a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/recip_sqrt_mult_1.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-recip" } */
+
+double res, res2, tmp;
+void
+foo (double a, double b)
+{
+ tmp = 1.0 / __builtin_sqrt (a);
+ res = tmp * tmp;
+ res2 = a * tmp;
+}
+
+/* { dg-final { scan-tree-dump "Optimizing reciprocal sqrt multiplications" "recip" } } */
+/* { dg-final { scan-tree-dump "Replacing squaring multiplication" "recip" } } */
+/* { dg-final { scan-tree-dump "Replacing original division" "recip" } } */
diff --git a/gcc/testsuite/gcc.dg/recip_sqrt_mult_2.c b/gcc/testsuite/gcc.dg/recip_sqrt_mult_2.c
new file mode 100644
index 0000000..c5fc3de
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/recip_sqrt_mult_2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-optimized" } */
+
+float
+foo (float a)
+{
+ float tmp = 1.0f / __builtin_sqrtf (a);
+ return a * tmp;
+}
+
+/* { dg-final { scan-tree-dump-not " / " "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/recip_sqrt_mult_3.c b/gcc/testsuite/gcc.dg/recip_sqrt_mult_3.c
new file mode 100644
index 0000000..e7d185b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/recip_sqrt_mult_3.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-optimized" } */
+
+double
+foo (double a)
+{
+ double tmp = 1.0f / __builtin_sqrt (a);
+ return tmp * tmp;
+}
+
+/* { dg-final { scan-tree-dump-not "__builtin_sqrt" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/recip_sqrt_mult_4.c b/gcc/testsuite/gcc.dg/recip_sqrt_mult_4.c
new file mode 100644
index 0000000..e3005f2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/recip_sqrt_mult_4.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-recip" } */
+
+/* The main path doesn't have any multiplications.
+ Avoid introducing them in the recip pass. */
+
+double res, res2, tmp;
+void
+foo (double a, double b, int c, int d)
+{
+ tmp = 1.0 / __builtin_sqrt (a);
+ if (c)
+ res = tmp * tmp;
+
+ if (d)
+ res2 = a * tmp;
+}
+
+/* { dg-final { scan-tree-dump-not "Optimizing reciprocal sqrt multiplications" "recip" } } */
+/* { dg-final { scan-tree-dump-not "Replacing squaring multiplication" "recip" } } */
+/* { dg-final { scan-tree-dump-not "Replacing original division" "recip" } } */
diff --git a/gcc/testsuite/gcc.dg/recip_sqrt_mult_5.c b/gcc/testsuite/gcc.dg/recip_sqrt_mult_5.c
new file mode 100644
index 0000000..e871f0f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/recip_sqrt_mult_5.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-recip" } */
+
+/* We want to do the recip_sqrt transformations here there is already
+ a multiplication on the main path. */
+
+double res, res2, tmp;
+void
+foo (double a, double b, int c, int d)
+{
+ tmp = 1.0 / __builtin_sqrt (a);
+ res = tmp * tmp;
+
+ if (d)
+ res2 = a * tmp;
+}
+
+/* { dg-final { scan-tree-dump "Optimizing reciprocal sqrt multiplications" "recip" } } */
+/* { dg-final { scan-tree-dump "Replacing squaring multiplication" "recip" } } */
+/* { dg-final { scan-tree-dump "Replacing original division" "recip" } } */
diff --git a/gcc/testsuite/gcc.dg/redecl-10.c b/gcc/testsuite/gcc.dg/redecl-10.c
index 525961e..0864311 100644
--- a/gcc/testsuite/gcc.dg/redecl-10.c
+++ b/gcc/testsuite/gcc.dg/redecl-10.c
@@ -5,7 +5,7 @@
/* { dg-do compile } */
/* { dg-options "-g" } */
-static int w[];
+static int w[]; /* { dg-warning "array 'w' assumed to have one element" } */
void
f (void)
{
@@ -19,7 +19,7 @@ g (void)
extern int x[] = { 3, 4, 5 }; /* { dg-error "has both" } */
}
-static int y[];
+static int y[]; /* { dg-warning "array 'y' assumed to have one element" } */
void
h (void)
{
diff --git a/gcc/testsuite/gcc.dg/sibcall-10.c b/gcc/testsuite/gcc.dg/sibcall-10.c
index d89909a..54cc604 100644
--- a/gcc/testsuite/gcc.dg/sibcall-10.c
+++ b/gcc/testsuite/gcc.dg/sibcall-10.c
@@ -5,7 +5,7 @@
Copyright (C) 2002 Free Software Foundation Inc.
Contributed by Hans-Peter Nilsson <hp@bitrange.com> */
-/* { dg-do run { xfail { { cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* msp430*-*-* nds32*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */
+/* { dg-do run { xfail { { cris-*-* crisv32-*-* csky-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* msp430*-*-* nds32*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */
/* -mlongcall disables sibcall patterns. */
/* { dg-skip-if "" { powerpc*-*-* } { "-mlongcall" } { "" } } */
/* -msave-restore disables sibcall patterns. */
diff --git a/gcc/testsuite/gcc.dg/sibcall-9.c b/gcc/testsuite/gcc.dg/sibcall-9.c
index 8e30952..fc3bd9d 100644
--- a/gcc/testsuite/gcc.dg/sibcall-9.c
+++ b/gcc/testsuite/gcc.dg/sibcall-9.c
@@ -5,7 +5,7 @@
Copyright (C) 2002 Free Software Foundation Inc.
Contributed by Hans-Peter Nilsson <hp@bitrange.com> */
-/* { dg-do run { xfail { { cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* msp430*-*-* nds32*-*-* nvptx-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */
+/* { dg-do run { xfail { { cris-*-* crisv32-*-* csky-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* msp430*-*-* nds32*-*-* nvptx-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */
/* -mlongcall disables sibcall patterns. */
/* { dg-skip-if "" { powerpc*-*-* } { "-mlongcall" } { "" } } */
/* -msave-restore disables sibcall patterns. */
diff --git a/gcc/testsuite/gcc.dg/spec-barrier-3.c b/gcc/testsuite/gcc.dg/spec-barrier-3.c
new file mode 100644
index 0000000..3ed4d39
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/spec-barrier-3.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-Wpedantic" } */
+
+/* __builtin_speculation_safe_value returns a value with the same type
+ as its first argument. There should be a warning if that isn't
+ type-compatible with the use. */
+int *
+f (int x)
+{
+ return __builtin_speculation_safe_value (x); /* { dg-warning "returning 'int' from a function with return type 'int \\*' makes pointer from integer without a cast" } */
+}
+
+/* { dg-prune-output "this target does not define a speculation barrier;" } */
diff --git a/gcc/testsuite/gcc.dg/spellcheck-identifiers-4.c b/gcc/testsuite/gcc.dg/spellcheck-identifiers-4.c
new file mode 100644
index 0000000..f9b7d8d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/spellcheck-identifiers-4.c
@@ -0,0 +1,10 @@
+/* { dg-options "-Wimplicit-function-declaration" } */
+
+extern double sqrt (double);
+
+void test (float pf, float inff)
+{
+ assert (pf == inff); /* { dg-bogus "sqrt" } */
+ /* { dg-warning "implicit declaration of function 'assert'" "" { target *-*-* } .-1 } */
+ /* { dg-message "header '<assert.h>'" "" { target *-*-* } .-2 } */
+}
diff --git a/gcc/testsuite/gcc.dg/stack-usage-1.c b/gcc/testsuite/gcc.dg/stack-usage-1.c
index 038bd4e..e644014 100644
--- a/gcc/testsuite/gcc.dg/stack-usage-1.c
+++ b/gcc/testsuite/gcc.dg/stack-usage-1.c
@@ -101,6 +101,8 @@
#define SIZE 252
#elif defined (__M32R__)
#define SIZE 252
+#elif defined (__csky__)
+# define SIZE 252
#else
# define SIZE 256
#endif
diff --git a/gcc/testsuite/gcc.dg/store_merging_22.c b/gcc/testsuite/gcc.dg/store_merging_22.c
new file mode 100644
index 0000000..bcd4235
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/store_merging_22.c
@@ -0,0 +1,16 @@
+/* PR tree-optimization/86844 */
+/* { dg-do compile } */
+/* { dg-require-effective-target store_merge } */
+/* { dg-options "-O2 -fdump-tree-store-merging" } */
+
+void
+foo (int *p)
+{
+ *p = 0;
+ *((char *)p + 3) = 1;
+ *((char *)p + 1) = 2;
+ *((char *)p + 2) = *((char *)p + 38);
+}
+
+/* { dg-final { scan-tree-dump-times "Merging successful" 1 "store-merging" } } */
+/* { dg-final { scan-tree-dump-times "New sequence of 1 stores to replace old one of 3 stores" 1 "store-merging" } } */
diff --git a/gcc/testsuite/gcc.dg/store_merging_23.c b/gcc/testsuite/gcc.dg/store_merging_23.c
new file mode 100644
index 0000000..dd197fb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/store_merging_23.c
@@ -0,0 +1,16 @@
+/* PR tree-optimization/86844 */
+/* { dg-do compile } */
+/* { dg-require-effective-target store_merge } */
+/* { dg-options "-O2 -fdump-tree-store-merging" } */
+
+void
+foo (int *p)
+{
+ *p = 0;
+ int one = 1;
+ __builtin_memcpy ((char *) p + 3, &one, sizeof (int));
+ *((char *)p + 4) = *((char *)p + 36);
+ *((char *)p + 1) = 2;
+}
+
+/* { dg-final { scan-tree-dump-not "Merging successful" "store-merging" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-55.c b/gcc/testsuite/gcc.dg/strlenopt-55.c
new file mode 100644
index 0000000..d5a0295
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-55.c
@@ -0,0 +1,230 @@
+/* PR tree-optimization/71625 - missing strlen optimization on different
+ array initialization style
+
+ Verify that strlen() of braced initialized array is folded
+ { dg-do compile }
+ { dg-options "-O1 -Wall -fdump-tree-gimple -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+#define S \
+ "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" \
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" \
+ "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" \
+ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" \
+ "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" \
+ "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" \
+ "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" \
+ "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" \
+ "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" \
+ "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" \
+ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf" \
+ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" \
+ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" \
+ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" \
+ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" \
+ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+
+/* Arrays of char, signed char, and unsigned char to verify that
+ the length and contents of all are the same as that of the string
+ literal above. */
+
+const char c256[] = {
+ S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+ S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+ S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+ S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+ S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+ S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+ S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+ S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+ S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+ S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+ S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+ S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+ S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+ S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+ S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+ S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+ S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+ S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+ S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+ S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+ S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+ S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+ S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+ S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+ S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+ S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+ S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+ S[254], S[255] /* = NUL */
+};
+
+const signed char sc256[] = {
+ S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+ S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+ S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+ S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+ S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+ S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+ S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+ S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+ S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+ S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+ S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+ S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+ S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+ S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+ S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+ S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+ S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+ S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+ S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+ S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+ S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+ S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+ S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+ S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+ S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+ S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+ S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+ S[254], S[255] /* = NUL */
+};
+
+const unsigned char uc256[] = {
+ S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+ S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+ S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+ S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+ S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+ S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+ S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+ S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+ S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+ S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+ S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+ S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+ S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+ S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+ S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+ S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+ S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+ S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+ S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+ S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+ S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+ S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+ S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+ S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+ S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+ S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+ S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+ S[254], S[255] /* = NUL */
+};
+
+const __CHAR16_TYPE__ c16_4[] = {
+ 1, 0x7fff, 0x8000, 0xffff,
+ 0x10000 /* { dg-warning "\\\[-Woverflow]" } */
+};
+
+const char a2_implicit[2] = { };
+const char a3_implicit[3] = { };
+
+const char a3_nul[3] = { 0 };
+const char a5_nul1[3] = { [1] = 0 };
+const char a7_nul2[3] = { [2] = 0 };
+
+const char ax_2_nul[] = { '1', '2', '\0' };
+const char ax_3_nul[] = { '1', '2', '3', '\0' };
+
+const char ax_3_des_nul[] = { [3] = 0, [2] = '3', [1] = '2', [0] = '1' };
+
+const char ax_3[] = { '1', '2', '3' };
+const char a3_3[3] = { '1', '2', '3' };
+
+const char ax_100_3[] = { '1', '2', '3', [100] = '\0' };
+
+#define CONCAT(x, y) x ## y
+#define CAT(x, y) CONCAT (x, y)
+#define FAILNAME(name) CAT (call_ ## name ##_on_line_, __LINE__)
+
+#define FAIL(name) do { \
+ extern void FAILNAME (name) (void); \
+ FAILNAME (name)(); \
+ } while (0)
+
+/* Macro to emit a call to funcation named
+ call_in_true_branch_not_eliminated_on_line_NNN()
+ for each call that's expected to be eliminated. The dg-final
+ scan-tree-dump-time directive at the bottom of the test verifies
+ that no such call appears in output. */
+#define ELIM(expr) \
+ if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
+
+#define T(s, n) ELIM (strlen (s) == n)
+
+void test_nulstring (void)
+{
+ T (a2_implicit, 0);
+ T (a3_implicit, 0);
+
+ T (a3_nul, 0);
+ T (a5_nul1, 0);
+ T (a7_nul2, 0);
+
+ T (ax_2_nul, 2);
+ T (ax_3_nul, 3);
+ T (ax_3_des_nul, 3);
+
+ T (ax_100_3, 3);
+ T (ax_100_3 + 4, 0);
+ ELIM (101 == sizeof ax_100_3);
+ ELIM ('\0' == ax_100_3[100]);
+
+ /* Verify that all three character arrays have the same length
+ as the string literal they are initialized with. */
+ T (S, 255);
+ T (c256, 255);
+ T ((const char*)sc256, 255);
+ T ((const char*)uc256, 255);
+
+ /* Verify that all three character arrays have the same contents
+ as the string literal they are initialized with. */
+ ELIM (0 == memcmp (c256, S, sizeof c256));
+ ELIM (0 == memcmp (c256, (const char*)sc256, sizeof c256));
+ ELIM (0 == memcmp (c256, (const char*)uc256, sizeof c256));
+
+ ELIM (0 == strcmp (c256, (const char*)sc256));
+ ELIM (0 == strcmp (c256, (const char*)uc256));
+
+ /* Verify that the char16_t array has the expected contents. */
+ ELIM (c16_4[0] == 1 && c16_4[1] == 0x7fff
+ && c16_4[2] == 0x8000 && c16_4[3] == 0xffff
+ && c16_4[4] == 0);
+}
+
+/* Verify that excessively large initializers don't run out of
+ memory. Also verify that the they have the expected size and
+ contents. */
+
+#define MAX (__PTRDIFF_MAX__ - 1)
+
+const char large_string[] = { 'a', [1234] = 'b', [MAX] = '\0' };
+
+const void test_large_string_size (void)
+{
+ ELIM (sizeof large_string == MAX + 1);
+
+ /* The following expressions are not folded without optimization. */
+ ELIM ('a' == large_string[0]);
+ ELIM ('\0' == large_string[1233]);
+ ELIM ('b' == large_string[1234]);
+ ELIM ('\0' == large_string[1235]);
+ ELIM ('\0' == large_string[MAX - 1]);
+}
+
+
+/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
+ { dg-final { scan-tree-dump-times "memcmp" 0 "gimple" } }
+ { dg-final { scan-tree-dump-times "strcmp" 0 "gimple" } }
+ { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated" 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-56.c b/gcc/testsuite/gcc.dg/strlenopt-56.c
new file mode 100644
index 0000000..39a532b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-56.c
@@ -0,0 +1,50 @@
+/* PR tree-optimization/71625 - conversion of braced initializers to strings
+ Verify that array elements have the expected values regardless of sign
+ and non-ASCII execution character set.
+ { dg-do compile }
+ { dg-require-iconv "IBM1047" }
+ { dg-options "-O -Wall -fexec-charset=IBM1047 -fdump-tree-gimple -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+const char a[] = { 'a', 129, 0 };
+const signed char b[] = { 'b', 130, 0 };
+const unsigned char c[] = { 'c', 131, 0 };
+
+const char s[] = "a\201";
+const signed char ss[] = "b\202";
+const unsigned char us[] = "c\203";
+
+
+#define A(expr) ((expr) ? (void)0 : __builtin_abort ())
+
+void test_values (void)
+{
+ A (a[0] == a[1]);
+ A (a[1] == 'a');
+
+ A (b[0] == b[1]);
+ A (b[1] == (signed char)'b');
+
+ A (c[0] == c[1]);
+ A (c[1] == (unsigned char)'c');
+}
+
+void test_lengths (void)
+{
+ A (2 == strlen (a));
+ A (2 == strlen ((const char*)b));
+ A (2 == strlen ((const char*)c));
+}
+
+void test_contents (void)
+{
+ A (0 == strcmp (a, s));
+ A (0 == strcmp ((const char*)b, (const char*)ss));
+ A (0 == strcmp ((const char*)c, (const char*)us));
+}
+
+
+/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
+ { dg-final { scan-tree-dump-times "strcmp" 0 "gimple" } }
+ { dg-final { scan-tree-dump-times "abort" 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-57.c b/gcc/testsuite/gcc.dg/strlenopt-57.c
new file mode 100644
index 0000000..49dc8cd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-57.c
@@ -0,0 +1,49 @@
+/* PR tree-optimization/86914 - wrong code with strlen() of poor-man's
+ flexible array member plus offset
+ { dg-do compile }
+ { dg-options "-O2 -Wall -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+struct A0 { char i, a[0]; };
+struct A1 { char i, a[1]; };
+struct A9 { char i, a[9]; };
+struct Ax { char i, a[]; };
+
+extern int a[];
+
+extern struct A0 a0;
+extern struct A1 a1;
+extern struct A9 a9;
+extern struct Ax ax;
+
+void test_var_flexarray_cst_off (void)
+{
+ /* Use arbitrary constants greater than 16 in case GCC ever starts
+ unrolling strlen() calls with small array arguments. */
+ a[0] = 17 < strlen (a0.a + 1);
+ a[1] = 19 < strlen (a1.a + 1);
+ a[2] = 23 < strlen (a9.a + 9);
+ a[3] = 29 < strlen (ax.a + 3);
+}
+
+void test_ptr_flexarray_cst_off (struct A0 *p0, struct A1 *p1,
+ struct A9 *p9, struct Ax *px)
+{
+ a[0] = 17 < strlen (p0->a + 1);
+ a[1] = 19 < strlen (p1->a + 1);
+ a[2] = 23 < strlen (p9->a + 9);
+ a[3] = 29 < strlen (px->a + 3);
+}
+
+void test_ptr_flexarray_var_off (struct A0 *p0, struct A1 *p1,
+ struct A9 *p9, struct Ax *px,
+ int i)
+{
+ a[0] = 17 < strlen (p0->a + i);
+ a[1] = 19 < strlen (p1->a + i);
+ a[2] = 23 < strlen (p9->a + i);
+ a[3] = 29 < strlen (px->a + i);
+}
+
+/* { dg-final { scan-tree-dump-times "strlen" 12 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-58.c b/gcc/testsuite/gcc.dg/strlenopt-58.c
new file mode 100644
index 0000000..e0e8068
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-58.c
@@ -0,0 +1,93 @@
+/* PR tree-optimization/86711 - wrong folding of memchr
+
+ Verify that calls to memchr() with constant arrays initialized
+ with wide string literals are folded.
+
+ { dg-do compile }
+ { dg-options "-O1 -Wall -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+typedef __WCHAR_TYPE__ wchar_t;
+
+extern void* memchr (const void*, int, size_t);
+
+#define CONCAT(x, y) x ## y
+#define CAT(x, y) CONCAT (x, y)
+#define FAILNAME(name) CAT (call_ ## name ##_on_line_, __LINE__)
+
+#define FAIL(name) do { \
+ extern void FAILNAME (name) (void); \
+ FAILNAME (name)(); \
+ } while (0)
+
+/* Macro to emit a call to funcation named
+ call_in_true_branch_not_eliminated_on_line_NNN()
+ for each call that's expected to be eliminated. The dg-final
+ scan-tree-dump-time directive at the bottom of the test verifies
+ that no such call appears in output. */
+#define ELIM(expr) \
+ if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
+
+#define T(s, n) ELIM (strlen (s) == n)
+
+
+static const wchar_t wc = L'1';
+static const wchar_t ws1[] = L"1";
+static const wchar_t wsx[] = L"\x12345678";
+static const wchar_t ws4[] = L"\x00123456\x12005678\x12340078\x12345600";
+
+void test_wide (void)
+{
+ int i0 = 0;
+ int i1 = i0 + 1;
+ int i2 = i1 + 1;
+ int i3 = i2 + 1;
+ int i4 = i3 + 1;
+
+ ELIM (memchr (L"" + 1, 0, 0) == 0);
+ ELIM (memchr (&wc + 1, 0, 0) == 0);
+ ELIM (memchr (L"\x12345678", 0, sizeof (wchar_t)) == 0);
+
+ const size_t nb = sizeof ws4;
+ const size_t nwb = sizeof (wchar_t);
+
+ const char *pws1 = (const char*)ws1;
+ const char *pws4 = (const char*)ws4;
+ const char *pwsx = (const char*)wsx;
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ ELIM (memchr (ws1, 0, sizeof ws1) == pws1 + 1);
+ ELIM (memchr (wsx, 0, sizeof wsx) == pwsx + sizeof *wsx);
+
+ ELIM (memchr (&ws4[0], 0, nb) == pws4 + 3);
+ ELIM (memchr (&ws4[1], 0, nb - 1 * nwb) == pws4 + 1 * nwb + 2);
+ ELIM (memchr (&ws4[2], 0, nb - 2 * nwb) == pws4 + 2 * nwb + 1);
+ ELIM (memchr (&ws4[3], 0, nb - 3 * nwb) == pws4 + 3 * nwb + 0);
+ ELIM (memchr (&ws4[4], 0, nb - 4 * nwb) == pws4 + 4 * nwb + 0);
+
+ ELIM (memchr (&ws4[i0], 0, nb) == pws4 + 3);
+ ELIM (memchr (&ws4[i1], 0, nb - 1 * nwb) == pws4 + 1 * nwb + 2);
+ ELIM (memchr (&ws4[i2], 0, nb - 2 * nwb) == pws4 + 2 * nwb + 1);
+ ELIM (memchr (&ws4[i3], 0, nb - 3 * nwb) == pws4 + 3 * nwb + 0);
+ ELIM (memchr (&ws4[i4], 0, nb - 4 * nwb) == pws4 + 4 * nwb + 0);
+#else
+ ELIM (memchr (ws1, 0, sizeof ws1) == pws1 + 0);
+ ELIM (memchr (wsx, 0, sizeof wsx) == pwsx + sizeof *wsx);
+
+ ELIM (memchr (&ws4[0], 0, nb) == pws4 + 0);
+ ELIM (memchr (&ws4[1], 0, nb - 1 * nwb) == pws4 + 1 * nwb + 1);
+ ELIM (memchr (&ws4[2], 0, nb - 2 * nwb) == pws4 + 2 * nwb + 2);
+ ELIM (memchr (&ws4[3], 0, nb - 3 * nwb) == pws4 + 3 * nwb + 3);
+ ELIM (memchr (&ws4[4], 0, nb - 4 * nwb) == pws4 + 4 * nwb + 0);
+
+ ELIM (memchr (&ws4[i0], 0, nb) == pws4 + 0);
+ ELIM (memchr (&ws4[i1], 0, nb - 1 * nwb) == pws4 + 1 * nwb + 1);
+ ELIM (memchr (&ws4[i2], 0, nb - 2 * nwb) == pws4 + 2 * nwb + 2);
+ ELIM (memchr (&ws4[i3], 0, nb - 3 * nwb) == pws4 + 3 * nwb + 3);
+ ELIM (memchr (&ws4[i4], 0, nb - 4 * nwb) == pws4 + 4 * nwb + 0);
+#endif
+}
+
+/* { dg-final { scan-tree-dump-times "memchr" 0 "optimized" } }
+ { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated" 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/torture/float32-tg-3.c b/gcc/testsuite/gcc.dg/torture/float32-tg-3.c
index b07c07a..e478a23 100644
--- a/gcc/testsuite/gcc.dg/torture/float32-tg-3.c
+++ b/gcc/testsuite/gcc.dg/torture/float32-tg-3.c
@@ -4,6 +4,7 @@
/* { dg-add-options float32 } */
/* { dg-add-options ieee } */
/* { dg-require-effective-target float32_runtime } */
+/* { dg-skip-if "No subnormal support" { csky-*-* } { "-mhard-float" } } */
#define WIDTH 32
#define EXT 0
diff --git a/gcc/testsuite/gcc.dg/torture/float32x-tg-3.c b/gcc/testsuite/gcc.dg/torture/float32x-tg-3.c
index 9f9f982..6f55779 100644
--- a/gcc/testsuite/gcc.dg/torture/float32x-tg-3.c
+++ b/gcc/testsuite/gcc.dg/torture/float32x-tg-3.c
@@ -4,6 +4,7 @@
/* { dg-add-options float32x } */
/* { dg-add-options ieee } */
/* { dg-require-effective-target float32x_runtime } */
+/* { dg-skip-if "No subnormal support" { csky-*-* } { "-mhard-float" } } */
#define WIDTH 32
#define EXT 1
diff --git a/gcc/testsuite/gcc.dg/torture/float64-tg-3.c b/gcc/testsuite/gcc.dg/torture/float64-tg-3.c
index a83e781..a1fead7 100644
--- a/gcc/testsuite/gcc.dg/torture/float64-tg-3.c
+++ b/gcc/testsuite/gcc.dg/torture/float64-tg-3.c
@@ -4,6 +4,7 @@
/* { dg-add-options float64 } */
/* { dg-add-options ieee } */
/* { dg-require-effective-target float64_runtime } */
+/* { dg-skip-if "No subnormal support" { csky-*-* } { "-mhard-float" } } */
#define WIDTH 64
#define EXT 0
diff --git a/gcc/testsuite/gcc.dg/torture/float64x-tg-3.c b/gcc/testsuite/gcc.dg/torture/float64x-tg-3.c
index 195c4fd..3cdd933 100644
--- a/gcc/testsuite/gcc.dg/torture/float64x-tg-3.c
+++ b/gcc/testsuite/gcc.dg/torture/float64x-tg-3.c
@@ -4,6 +4,7 @@
/* { dg-add-options float64x } */
/* { dg-add-options ieee } */
/* { dg-require-effective-target float64x_runtime } */
+/* { dg-skip-if "No subnormal support" { csky-*-* } { "-mhard-float" } } */
#define WIDTH 64
#define EXT 1
diff --git a/gcc/testsuite/gcc.dg/torture/pr36066.c b/gcc/testsuite/gcc.dg/torture/pr36066.c
index 0e1d1ce..547806a 100644
--- a/gcc/testsuite/gcc.dg/torture/pr36066.c
+++ b/gcc/testsuite/gcc.dg/torture/pr36066.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-funsafe-loop-optimizations -ftree-vrp" } */
+/* { dg-options "-ftree-vrp" } */
typedef int FLAC__int32;
typedef int FLAC__bool;
diff --git a/gcc/testsuite/gcc.dg/torture/pr52969.c b/gcc/testsuite/gcc.dg/torture/pr52969.c
deleted file mode 100644
index 05331d9..0000000
--- a/gcc/testsuite/gcc.dg/torture/pr52969.c
+++ /dev/null
@@ -1,16 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-ftree-loop-if-convert-stores" } */
-
-int a, b;
-float xsum[100];
-void foo (float *cluster)
-{
- int j;
- for (; a ; ++j) {
- xsum[j] = cluster[j];
- if (xsum[j] > 0)
- xsum[j] = 0;
- }
- if (xsum[0])
- b = 0;
-}
diff --git a/gcc/testsuite/gcc.dg/torture/pr81790.c b/gcc/testsuite/gcc.dg/torture/pr81790.c
index b5e02f6..b69946f 100644
--- a/gcc/testsuite/gcc.dg/torture/pr81790.c
+++ b/gcc/testsuite/gcc.dg/torture/pr81790.c
@@ -1,5 +1,4 @@
/* { dg-do compile } */
-/* { dg-additional-options "--param sccvn-max-scc-size=10" } */
typedef int a __attribute__ ((__vector_size__ (16)));
typedef struct
diff --git a/gcc/testsuite/gcc.dg/torture/pr86505.c b/gcc/testsuite/gcc.dg/torture/pr86505.c
new file mode 100644
index 0000000..db102d3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr86505.c
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+
+static inline __attribute__(( __always_inline__)) int
+funA(unsigned int param, ...)
+{
+ return __builtin_va_arg_pack_len();
+}
+
+static inline __attribute__(( __always_inline__)) int
+funB(unsigned int param, ...)
+{
+ return funA(param, 2, 4, __builtin_va_arg_pack());
+}
+
+int
+testBuiltin(void)
+{
+ int rc = funB(0,1,2);
+ if (rc != 4)
+ return 1;
+ return 0;
+}
+
+int
+main()
+{
+ int rc = testBuiltin();
+ if (rc == 1)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr86945.c b/gcc/testsuite/gcc.dg/torture/pr86945.c
new file mode 100644
index 0000000..4b722f5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr86945.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+
+void __attribute__((noinline,noipa))
+foo(int id)
+{
+ switch (id)
+ {
+ case (-__INT_MAX__ - 1)...-1:
+ __builtin_abort ();
+ default:;
+ }
+}
+
+int main()
+{
+ foo(1);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr87132.c b/gcc/testsuite/gcc.dg/torture/pr87132.c
new file mode 100644
index 0000000..48b8673
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87132.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+
+extern void abort (void);
+int c, d;
+int main()
+{
+ int e[] = {4, 4, 4, 4, 4, 4, 4, 4, 4};
+ d = 8;
+ for (; d; d--)
+ for (int a = 0; a <= 8; a++)
+ {
+ c = e[1];
+ e[d] = 0;
+ }
+ if (c != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr87147.c b/gcc/testsuite/gcc.dg/torture/pr87147.c
new file mode 100644
index 0000000..385cfce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87147.c
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+
+short a;
+long b;
+int c, d, g;
+char e, h;
+long f[] = {0};
+int main()
+{
+ int i = 1;
+ for (; a <= 3; a++) {
+ c = 0;
+ for (; c <= 2; c++) {
+ b = 0;
+ for (; b <= 3; b++) {
+ h = i && f[d];
+ e = g && i;
+ i = 0;
+ }
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr87168.c b/gcc/testsuite/gcc.dg/torture/pr87168.c
new file mode 100644
index 0000000..d66ed98
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87168.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+
+int a, b, c, d, e, f, *g;
+
+int main ()
+{
+ unsigned i;
+ while (b)
+ {
+ int j, m;
+L1:
+ f = j;
+L2:
+ if (i && e)
+ {
+ i = f;
+ goto L2;
+ }
+ j = f;
+ if (a)
+ goto L3;
+ for (m = 0; m < 2; m++)
+ if (d)
+ goto L1;
+ goto L2;
+L3:
+ (&j != g) | c;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr87169.c b/gcc/testsuite/gcc.dg/torture/pr87169.c
new file mode 100644
index 0000000..ed878e0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87169.c
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+/* { dg-additional-options "--param rpo-vn-max-loop-depth=7" } */
+
+int a, b, c;
+
+int main ()
+{
+ int d;
+ b = 1;
+L1:
+ for (; b > 1;)
+ goto L2;
+ {
+ int e[1];
+L3:;
+ }
+L2:
+ while (a)
+ {
+ d--;
+ goto L1;
+ }
+ while (c)
+ {
+ if (a)
+ goto L3;
+ if (a)
+ break;
+ if (a)
+ goto L2;
+ while (c)
+ while (c)
+ while (c)
+ while (c)
+ while (c)
+ while (c)
+ while (c)
+ ;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr87176.c b/gcc/testsuite/gcc.dg/torture/pr87176.c
new file mode 100644
index 0000000..6295779
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87176.c
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+
+int a, b, c;
+
+int main ()
+{
+ int d = a = 0;
+ while (1)
+ {
+ a = a ^ 6;
+ if (!a)
+ break;
+ if (d)
+ goto L;
+ d = a;
+ for (b = 0; b < 2; b++)
+ {
+ const int *f[3] = { &c };
+ const int **g[] = { &f[2] };
+ int h = ~d;
+ if (d)
+ L:
+ if (h > 1)
+ continue;
+ }
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr87177-2.c b/gcc/testsuite/gcc.dg/torture/pr87177-2.c
new file mode 100644
index 0000000..5592076
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87177-2.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-w" } */
+
+int dk;
+
+void
+lv (void)
+{
+ int nm;
+
+ dk = 1;
+ while (dk != 0)
+ {
+ }
+
+ if (1 / 0)
+ {
+ dk = 0;
+ while (dk != 0)
+ {
+ }
+ }
+
+ for (;;)
+ nm = !!dk;
+
+ (void) nm;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr87177.c b/gcc/testsuite/gcc.dg/torture/pr87177.c
new file mode 100644
index 0000000..efeaebf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87177.c
@@ -0,0 +1,61 @@
+/* { dg-do run } */
+
+int __attribute__((noinline)) my_printf (const char *p, ...)
+{
+ static volatile int x;
+ ++x;
+}
+
+int a, b, c, e, f, g, h, i, j, k, l;
+unsigned d;
+
+static void p ()
+{
+ while (1)
+ {
+ int n = h;
+ h = 8;
+ if (!e)
+ break;
+ h = n;
+ while (1)
+ ;
+ }
+ for (; c != 4; c++)
+ {
+ int o = g = 1;
+ for (; g; g--)
+ {
+ while (d < b)
+ e--;
+ a = g;
+ int q = o;
+ if (q)
+ L1:
+ j = f;
+ if (l)
+ {
+ my_printf ("%d", g);
+ goto L1;
+ }
+ o = l;
+ k = q;
+ }
+ }
+}
+
+void s ()
+{
+ int m = 0;
+L2:
+ if (i && g)
+ goto L2;
+ for (; m < 2; m++)
+ p ();
+}
+
+int main ()
+{
+ s ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr87197.c b/gcc/testsuite/gcc.dg/torture/pr87197.c
new file mode 100644
index 0000000..4c70224
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87197.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+
+int a, c, e, f, g;
+void
+h (int i)
+{
+ a = i;
+}
+void
+j (char *i, long k)
+{
+ while (k--)
+ c = *i++;
+}
+void
+l (unsigned char *i, long k)
+{
+ unsigned char *b = i + k;
+ while (i < b)
+ {
+ h (*i);
+ i++;
+ }
+}
+void
+m ()
+{
+ while (e)
+ {
+ float d = g;
+ l ((char *) &d, sizeof (g));
+ if (f)
+ j ((char *) &d, sizeof (g));
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr87200.c b/gcc/testsuite/gcc.dg/torture/pr87200.c
new file mode 100644
index 0000000..a035631
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87200.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+
+unsigned long long int ry;
+
+int
+gl (void)
+{
+ long long int my = 0;
+ unsigned long long int *oi = (unsigned long long int *) &my;
+ int s9;
+
+ s9 = !!gl () ? ry : 0;
+ if (s9 != 0)
+ oi = &ry;
+ else
+ {
+ my = ry;
+ *oi += my;
+ }
+
+ return *oi;
+}
+
diff --git a/gcc/testsuite/gcc.dg/torture/pr87211.c b/gcc/testsuite/gcc.dg/torture/pr87211.c
new file mode 100644
index 0000000..386d2a4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87211.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+int a, b;
+int i(int *);
+int *c(int *d, int *e)
+{
+ for (; b;)
+ d = e;
+ return d;
+}
+void f()
+{
+ for (;;)
+ {
+ int *g[1];
+ int h = 0;
+ for (; h < 3; h++)
+ g[0] = &a;
+ &a == g[0] || i(c((int *)g, g[0]));
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr87263.c b/gcc/testsuite/gcc.dg/torture/pr87263.c
new file mode 100644
index 0000000..3d6a0d7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87263.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+
+int a, b, c;
+
+int main ()
+{
+ int g, *h[3] = {&g, &g, &g};
+ if (h[2] == 0)
+ ;
+ else
+ {
+ int i[1];
+ if (a)
+ while (a)
+ L:;
+ else
+ {
+ int k = b;
+ }
+ }
+ if ((b < c) > b)
+ goto L;
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr87266-1.c b/gcc/testsuite/gcc.dg/torture/pr87266-1.c
new file mode 100644
index 0000000..dc0a4a1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87266-1.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fno-tree-ccp -fno-tree-forwprop" } */
+
+void
+iw (int gu, int mq, int r2)
+{
+ int yn = 0;
+
+ while (gu < 1)
+ {
+ for (;;)
+ ;
+
+ bb:;
+ int ay = 0;
+
+ while (ay < 1)
+ ++mq;
+ }
+
+ if (yn != 0)
+ goto up;
+
+ if (0)
+ {
+ up:
+ if (r2 == 0)
+ goto bb;
+ }
+
+ goto up;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr87266-2.c b/gcc/testsuite/gcc.dg/torture/pr87266-2.c
new file mode 100644
index 0000000..cf0254f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87266-2.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fno-tree-ccp -fno-tree-forwprop" } */
+
+void
+iw (int gu, int mq, int r2)
+{
+ int yn = 0;
+
+ while (gu < 1)
+ {
+ for (;;)
+ ;
+
+ bb:;
+ int ay = 0;
+
+ while (yn < 1)
+ ++mq;
+ }
+
+ if (yn != 0)
+ goto up;
+
+ if (0)
+ {
+ up:
+ if (r2 == 0)
+ goto bb;
+ }
+
+ goto up;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr87266-3.c b/gcc/testsuite/gcc.dg/torture/pr87266-3.c
new file mode 100644
index 0000000..0f3f3ba
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87266-3.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fno-tree-ccp -fno-tree-forwprop" } */
+
+void
+iw (int gu, int mq, int r2)
+{
+ int yn = 0;
+
+ while (gu < 1)
+ {
+ int ay = 0;
+
+ for (;;)
+ ;
+
+ bb:
+ while (ay < 1)
+ ++mq;
+ }
+
+ if (yn != 0)
+ goto up;
+
+ if (0)
+ {
+ up:
+ if (r2 == 0)
+ goto bb;
+ }
+
+ goto up;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr87266-4.c b/gcc/testsuite/gcc.dg/torture/pr87266-4.c
new file mode 100644
index 0000000..e8d5ff1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87266-4.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fno-tree-dominator-opts -fno-tree-forwprop" } */
+
+unsigned long int
+re (long int j9)
+{
+ if (j9 == 0)
+ return 1;
+
+ return j9;
+}
+
+void
+zq (int bt, int yy)
+{
+ int p3 = 0, go = 4, ez = go;
+
+ while (go != 0)
+ {
+ if (ez + !!bt - re (bt) != 0 && go != 0)
+ {
+ if (yy != 0)
+ p3 = yy;
+ }
+ else
+ return;
+
+ go = 2;
+ }
+}
+
+void
+my (unsigned long int n6, int bt, int yy)
+{
+ zq (bt, yy);
+ n6 = n6 == bt;
+ zq (bt, yy);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr87280.c b/gcc/testsuite/gcc.dg/torture/pr87280.c
new file mode 100644
index 0000000..c62e8be
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87280.c
@@ -0,0 +1,61 @@
+/* { dg-do compile } */
+/* { dg-additional-options "--param rpo-vn-max-loop-depth=5" } */
+
+int uc;
+
+void
+j8 (int *xv, int f3)
+{
+ uc = 0;
+ while (uc < 1)
+ {
+ }
+
+ if (*xv == 0)
+ {
+ int *o8 = xv;
+
+ if (0)
+ {
+n3:
+ *o8 = 0;
+ while (*o8 < 1)
+ {
+h5:
+ *o8 = 0;
+ }
+ }
+
+ while (*xv < 1)
+ if (*xv == 0)
+ goto h5;
+
+g5:
+ ;
+ }
+
+ *xv = 0;
+ for (;;)
+ {
+ while (uc < 1)
+ {
+ }
+
+ while (f3 < 1)
+ {
+ if (*xv == 0)
+ goto n3;
+
+ while (f3 < 1)
+ while (*xv < 1)
+ while (*xv < 1)
+ while (*xv < 1)
+ while (*xv < 1)
+ {
+ }
+ }
+
+ if (*xv == 0)
+ goto g5;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr87301.c b/gcc/testsuite/gcc.dg/torture/pr87301.c
new file mode 100644
index 0000000..67d914f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87301.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-Wno-div-by-zero" } */
+
+void
+bl (int *be)
+{
+ int lo;
+ {
+ int **ny;
+
+ if (*be == 0)
+ {
+ int ***k8 = &ny;
+ int uj = (__INTPTR_TYPE__)&lo;
+
+ for (;;)
+ if (***k8 == 0)
+ {
+ uj = !!(1 / 0) ? !(lo = 0) : 0;
+ (void) uj;
+
+ if (*ny == 0)
+ for (;;)
+ if (***k8 == 0)
+ {
+ }
+
+ for (lo = 0; lo < 2; ++lo)
+ {
+ }
+ }
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr87328.c b/gcc/testsuite/gcc.dg/torture/pr87328.c
new file mode 100644
index 0000000..50e1cdf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87328.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fno-tree-ccp -fno-tree-forwprop" } */
+
+void
+tp (void)
+{
+ int qt;
+
+ qt = 0;
+ if (qt != 0)
+ {
+ if (0)
+ {
+h5:
+ qt = 0;
+ while (qt < 1)
+ {
+ }
+ }
+
+ ++qt;
+ }
+
+ goto h5;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr87342.c b/gcc/testsuite/gcc.dg/torture/pr87342.c
new file mode 100644
index 0000000..ba33fb4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87342.c
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+
+int ix;
+
+void
+o6 (int rh)
+{
+ if (rh == 0)
+ {
+ ix = 0;
+ while (ix < 1)
+ {
+ }
+
+ for (;;)
+ if (ix == 0)
+ while (rh < 1)
+ {
+ if (rh == 0)
+ {
+ __builtin_unreachable ();
+
+kp:
+ if (ix == 0)
+ {
+hk:
+ ix = 0;
+ }
+ }
+
+ while (rh < 1)
+ if (ix == 0)
+ goto kp;
+
+ while (rh < 1)
+ {
+ }
+ }
+ else
+ goto kp;
+ }
+
+ goto hk;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr87349-1.c b/gcc/testsuite/gcc.dg/torture/pr87349-1.c
new file mode 100644
index 0000000..27e5fdb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87349-1.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+
+void
+h1 (int *fh, int pw)
+{
+ *fh = 0;
+ if (*fh != 0)
+ for (;;)
+ {
+ fh = &pw;
+
+ if (pw == 0)
+ {
+ }
+ else
+ while (pw < 1)
+ {
+ if (pw == 0)
+ {
+ut:
+ ;
+ }
+
+ ++pw;
+ }
+
+ if (pw == 0)
+ goto ut;
+ }
+
+ goto ut;
+}
+
diff --git a/gcc/testsuite/gcc.dg/torture/pr87349-2.c b/gcc/testsuite/gcc.dg/torture/pr87349-2.c
new file mode 100644
index 0000000..e8160ac
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr87349-2.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+
+void
+h1 (int *fh, int pw)
+{
+ *fh = 0;
+ if (*fh != 0)
+ for (;;)
+ {
+ fh = &pw;
+
+ if (pw == 0)
+ {
+ }
+ else
+ while (pw < 1)
+ {
+ if (pw == 0)
+ {
+ut:
+ ;
+ }
+
+ ++pw;
+ }
+
+ if (pw == *fh)
+ goto ut;
+ }
+
+ goto ut;
+}
+
diff --git a/gcc/testsuite/gcc.dg/torture/ssa-fre-1.c b/gcc/testsuite/gcc.dg/torture/ssa-fre-1.c
new file mode 100644
index 0000000..1597122
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/ssa-fre-1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+/* { dg-additional-options "-fstrict-aliasing -fdump-tree-fre1" } */
+
+float f;
+int foo(int *p, int *q)
+{
+ *p = 0;
+ if (*p)
+ *q = 1;
+ else
+ f = 8.0f;
+ return *p;
+}
+
+/* { dg-final { scan-tree-dump "return 0;" "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/torture/ssa-fre-2.c b/gcc/testsuite/gcc.dg/torture/ssa-fre-2.c
new file mode 100644
index 0000000..5ce47d2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/ssa-fre-2.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+
+int x;
+int main()
+{
+ int i = 0;
+ x = 0;
+ if (x)
+ {
+ for (; i < 10; ++i)
+ {
+doit:
+ x = i;
+ }
+ }
+ if (!x)
+ goto doit;
+ if (x != 9)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/ssa-fre-3.c b/gcc/testsuite/gcc.dg/torture/ssa-fre-3.c
new file mode 100644
index 0000000..2ec1c28
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/ssa-fre-3.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+/* { dg-additional-options "-fdump-tree-fre1" } */
+
+int x;
+int main()
+{
+ x = 0;
+ int z = x;
+ int w = 1;
+ for (int i = 0; i < 32; ++i)
+ {
+ if (z)
+ w = 2;
+ else
+ w = 1;
+ if (w == 2)
+ __builtin_abort ();
+ }
+ return w;
+}
+
+/* { dg-final { scan-tree-dump-not "abort" "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/torture/ssa-fre-4.c b/gcc/testsuite/gcc.dg/torture/ssa-fre-4.c
new file mode 100644
index 0000000..d09af78
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/ssa-fre-4.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+/* { dg-additional-options "-fdump-tree-fre1" } */
+
+int x;
+int main()
+{
+ x = 0;
+ if (x)
+ {
+ for (int i = 0; i < 10; ++i)
+ x = i;
+ }
+ return x;
+}
+
+/* { dg-final { scan-tree-dump "return 0;" "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/torture/type-generic-1.c b/gcc/testsuite/gcc.dg/torture/type-generic-1.c
index ef32b78..a5fa8e8 100644
--- a/gcc/testsuite/gcc.dg/torture/type-generic-1.c
+++ b/gcc/testsuite/gcc.dg/torture/type-generic-1.c
@@ -3,6 +3,7 @@
/* { dg-do run } */
/* { dg-skip-if "No Inf/NaN support" { spu-*-* } } */
+/* { dg-skip-if "No subnormal support" { csky-*-* } { "-mhard-float" } } */
/* { dg-options "-DUNSAFE" { target tic6x*-*-* visium-*-* nvptx-*-* } } */
/* { dg-add-options ieee } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/pr59521-3.c b/gcc/testsuite/gcc.dg/tree-prof/pr59521-3.c
new file mode 100644
index 0000000..0023217
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-prof/pr59521-3.c
@@ -0,0 +1,34 @@
+/* { dg-options "-O2 -save-temps" } */
+
+#include <stdio.h>
+
+__attribute__((noinline,noclone)) void
+sink(const char *s) {
+ asm("" :: "r"(s));
+}
+
+void
+foo(int ch) {
+ switch (ch) {
+ case 100: sink("100"); break;
+ case 10: sink("10"); break;
+ case 1: sink("1"); break;
+ }
+}
+
+int main()
+{
+ for (int i = 0; i < 10000; i++)
+ {
+ int v;
+ if (i % 100 == 0)
+ v = 100;
+ else if(i % 10 == 0)
+ v = 10;
+ else
+ v = 1;
+ foo(v);
+ }
+}
+
+/* { dg-final-use-not-autofdo { scan-assembler "\n_?foo:\n.*cmp.*1,.*cmp.*10,.*cmp.*100" { target i?86-*-* x86_64-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/section-attr-1.c b/gcc/testsuite/gcc.dg/tree-prof/section-attr-1.c
index ee6662e..1f99b31 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/section-attr-1.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/section-attr-1.c
@@ -13,7 +13,11 @@ const char *buf_cold;
void foo (int path);
+#ifdef __APPLE__
+__attribute__ ((section ("__TEXT,__text")))
+#else
__attribute__((section(".text")))
+#endif
int
main (int argc, char *argv[])
{
@@ -43,3 +47,4 @@ foo (int path)
}
/* { dg-final-use { scan-assembler "\.section\[\t \]*\.text\.unlikely\[\\n\\r\]+\[\t \]*\.size\[\t \]*foo\.cold\.0" { target *-*-linux* *-*-gnu* } } } */
+/* { dg-final-use { scan-assembler "\.section\[\t \]*__TEXT,__text_cold\.\*\[\\n\\r\]+_foo\.cold\.0" { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/section-attr-2.c b/gcc/testsuite/gcc.dg/tree-prof/section-attr-2.c
index 898a395..9bdc63a 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/section-attr-2.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/section-attr-2.c
@@ -28,7 +28,11 @@ main (int argc, char *argv[])
void NOINLINE
foo (int path)
{
+#ifdef __APPLE__
+ static int i __attribute__ ((section ("__DATA,__data")));
+#else
static int i __attribute__((section(".data")));
+#endif
if (path)
{
for (i = 0; i < SIZE; i++)
@@ -42,3 +46,4 @@ foo (int path)
}
/* { dg-final-use { scan-assembler "\.section\[\t \]*\.text\.unlikely\[\\n\\r\]+\[\t \]*\.size\[\t \]*foo\.cold\.0" { target *-*-linux* *-*-gnu* } } } */
+/* { dg-final-use { scan-assembler "\.section\[\t \]*__TEXT,__text_cold\.\*\[\\n\\r\]+_foo\.cold\.0:" { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/section-attr-3.c b/gcc/testsuite/gcc.dg/tree-prof/section-attr-3.c
index 36829dc..29eee45 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/section-attr-3.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/section-attr-3.c
@@ -9,7 +9,11 @@
#define NOINLINE __attribute__((noinline)) __attribute__ ((noclone))
const char *sarr[SIZE];
+#ifdef __APPLE__
+const char *buf_hot __attribute__ ((section ("__DATA,__data")));
+#else
const char *buf_hot __attribute__ ((section (".data")));
+#endif
const char *buf_cold;
void foo (int path);
@@ -43,3 +47,4 @@ foo (int path)
}
/* { dg-final-use { scan-assembler "\.section\[\t \]*\.text\.unlikely\[\\n\\r\]+\[\t \]*\.size\[\t \]*foo\.cold\.0" { target *-*-linux* *-*-gnu* } } } */
+/* { dg-final-use { scan-assembler "\.section\[\t \]*__TEXT,__text_cold\.\*\[\\n\\r\]+_foo\.cold\.0:" { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/stringop-1.c b/gcc/testsuite/gcc.dg/tree-prof/stringop-1.c
index 6f8908a..d75b254 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/stringop-1.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/stringop-1.c
@@ -15,7 +15,7 @@ main()
return 0;
}
/* autofdo doesn't support value profiling for now: */
-/* { dg-final-use-not-autofdo { scan-ipa-dump "Single value 4 stringop" "profile"} } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: single value 4 stringop" "profile"} } */
/* Really this ought to simplify into assignment, but we are not there yet. */
/* a[0] = b[0] is what we fold the resulting memcpy into. */
/* { dg-final-use-not-autofdo { scan-tree-dump " = MEM.*&b" "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/stringop-2.c b/gcc/testsuite/gcc.dg/tree-prof/stringop-2.c
index 330b159..3242cf5 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/stringop-2.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/stringop-2.c
@@ -20,6 +20,6 @@ main()
return 0;
}
/* autofdo doesn't support value profiling for now: */
-/* { dg-final-use-not-autofdo { scan-ipa-dump "Single value 4 stringop" "profile"} } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: single value 4 stringop" "profile"} } */
/* The versioned memset of size 4 should be optimized to an assignment. */
/* { dg-final-use-not-autofdo { scan-tree-dump "MEM\\\[\\(void .\\)&a\\\] = 168430090" "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/val-prof-1.c b/gcc/testsuite/gcc.dg/tree-prof/val-prof-1.c
index 35e0f90..492c4c1 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/val-prof-1.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/val-prof-1.c
@@ -17,6 +17,6 @@ main ()
return 0;
}
/* autofdo does not do value profiling so far */
-/* { dg-final-use-not-autofdo { scan-ipa-dump "Div.mod by constant n_\[0-9\]*=257 transformation on insn" "profile"} } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: div.mod by constant 257" "profile"} } */
/* { dg-final-use-not-autofdo { scan-tree-dump "if \\(n_\[0-9\]* != 257\\)" "optimized"} } */
/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/val-prof-10.c b/gcc/testsuite/gcc.dg/tree-prof/val-prof-10.c
new file mode 100644
index 0000000..57854b59
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-prof/val-prof-10.c
@@ -0,0 +1,31 @@
+/* { dg-options "-O2 -fdump-rtl-expand -mtune=core2" } */
+/* { dg-skip-if "" { ! { i?86-*-* x86_64-*-* } } } */
+
+long buffer1[128], buffer2[128];
+char *x;
+
+void foo(long *r)
+{
+ x = (char *)r;
+ asm volatile("" ::: "memory");
+}
+
+void
+__attribute__((noinline))
+compute()
+{
+ volatile int n = 24;
+ __builtin_memcpy (buffer1, buffer2, n);
+ foo (&buffer1[0]);
+}
+
+int
+main()
+{
+ for (unsigned i = 0; i < 10000; i++)
+ compute ();
+
+ return 0;
+}
+
+/* { dg-final-use-not-autofdo { scan-rtl-dump "Selected stringop expansion strategy: rep_byte" "expand" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/val-prof-2.c b/gcc/testsuite/gcc.dg/tree-prof/val-prof-2.c
index ad78043..8cb3c64 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/val-prof-2.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/val-prof-2.c
@@ -25,7 +25,7 @@ main ()
return 0;
}
/* autofdo does not do value profiling so far */
-/* { dg-final-use-not-autofdo { scan-ipa-dump "Mod power of 2 transformation on insn" "profile" } } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: mod power of 2" "profile" } } */
/* This is part of code checking that n is power of 2, so we are sure that the transformation
didn't get optimized out. */
/* { dg-final-use-not-autofdo { scan-tree-dump "n_\[0-9\]* \\+ (4294967295|0x0*ffffffff)" "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/val-prof-3.c b/gcc/testsuite/gcc.dg/tree-prof/val-prof-3.c
index 366ada1..60953d0 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/val-prof-3.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/val-prof-3.c
@@ -25,7 +25,7 @@ main ()
return 0;
}
/* autofdo does not do value profiling so far */
-/* { dg-final-use-not-autofdo { scan-ipa-dump "Mod subtract transformation on insn" "profile" } } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: mod subtract" "profile" } } */
/* This is part of code checking that n is greater than the divisor so we are sure that it
didn't get optimized out. */
/* { dg-final-use-not-autofdo { scan-tree-dump "if \\(_\[0-9\]* \\< n_\[0-9\]*" "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/val-prof-4.c b/gcc/testsuite/gcc.dg/tree-prof/val-prof-4.c
index 374428e..50ae2de 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/val-prof-4.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/val-prof-4.c
@@ -25,7 +25,7 @@ main ()
return 0;
}
/* autofdo does not do value profiling so far */
-/* { dg-final-use-not-autofdo { scan-ipa-dump "Mod subtract transformation on insn" "profile" } } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: mod subtract" "profile" } } */
/* This is part of code checking that n is greater than the divisor so we are sure that it
didn't get optimized out. */
/* { dg-final-use-not-autofdo { scan-tree-dump "if \\(n_\[0-9\]* \\>" "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/val-prof-5.c b/gcc/testsuite/gcc.dg/tree-prof/val-prof-5.c
index 7f4a15b..80eb320 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/val-prof-5.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/val-prof-5.c
@@ -13,5 +13,5 @@ main()
return 0;
}
/* autofdo does not do value profiling so far */
-/* { dg-final-use-not-autofdo { scan-ipa-dump "Div.mod by constant b.*=997 transformation on insn" "profile" } } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: div.mod by constant 997" "profile" } } */
/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/val-prof-7.c b/gcc/testsuite/gcc.dg/tree-prof/val-prof-7.c
index c9303e0..18b2b25 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/val-prof-7.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/val-prof-7.c
@@ -24,12 +24,18 @@ void memset_test_ ## N (int len) \
{ \
__builtin_memset (buffer1, 'c', len); \
} \
+__attribute__((noinline)) \
+void memmove_test_ ## N (int len) \
+{ \
+ __builtin_memmove (buffer1, buffer2, len); \
+} \
\
void test_stringops_ ## N(int len) \
{ \
memcpy_test_## N (len); \
mempcpy_test_ ## N (len); \
memset_test_ ## N (len); \
+ memmove_test_ ## N (len); \
} \
\
void test_stringops_with_values_ ## N (int common, int not_common) \
@@ -59,14 +65,18 @@ int main() {
return 0;
}
-/* { dg-final-use-not-autofdo { scan-ipa-dump "Single value 8 stringop transformation on __builtin_memcpy" "profile" } } */
-/* { dg-final-use-not-autofdo { scan-ipa-dump "Single value 55 stringop transformation on __builtin_memcpy" "profile" } } */
-/* { dg-final-use-not-autofdo { scan-ipa-dump-times "Single value 32 stringop transformation on __builtin_memcpy" 0 "profile" } } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: single value 8 stringop for BUILT_IN_MEMCPY" "profile" } } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: single value 55 stringop for BUILT_IN_MEMCPY" "profile" } } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump-times "Transformation done: single value 32 stringop for BUILT_IN_MEMCPY" 0 "profile" } } */
+
+/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: single value 8 stringop for BUILT_IN_MEMPCPY" "profile" } } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: single value 55 stringop for BUILT_IN_MEMPCPY" "profile" } } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump-times "Transformation done: single value 32 stringop for BUILT_IN_MEMPCPY" 0 "profile" } } */
-/* { dg-final-use-not-autofdo { scan-ipa-dump "Single value 8 stringop transformation on __builtin_mempcpy" "profile" } } */
-/* { dg-final-use-not-autofdo { scan-ipa-dump "Single value 55 stringop transformation on __builtin_mempcpy" "profile" } } */
-/* { dg-final-use-not-autofdo { scan-ipa-dump-times "Single value 32 stringop transformation on __builtin_mempcpy" 0 "profile" } } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: single value 8 stringop for BUILT_IN_MEMSET" "profile" } } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: single value 55 stringop for BUILT_IN_MEMSET" "profile" } } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump-times "Transformation done: single value 32 stringop for BUILT_IN_MEMSET" 0 "profile" } } */
-/* { dg-final-use-not-autofdo { scan-ipa-dump "Single value 8 stringop transformation on __builtin_memset" "profile" } } */
-/* { dg-final-use-not-autofdo { scan-ipa-dump "Single value 55 stringop transformation on __builtin_memset" "profile" } } */
-/* { dg-final-use-not-autofdo { scan-ipa-dump-times "Single value 32 stringop transformation on __builtin_memset" 0 "profile" } } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: single value 8 stringop for BUILT_IN_MEMMOVE" "profile" } } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: single value 55 stringop for BUILT_IN_MEMMOVE" "profile" } } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump-times "Transformation done: single value 32 stringop for BUILT_IN_MEMMOVE" 0 "profile" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-10.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-10.c
new file mode 100644
index 0000000..837b6f4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-10.c
@@ -0,0 +1,119 @@
+/* PR tree-optimization/86853 - sprintf optimization for wide strings
+ doesn't account for conversion failure​
+ { dg-do compile }
+ { dg-options "-O2 -Wall -fdump-tree-optimized" } */
+
+typedef __SIZE_TYPE__ size_t;
+typedef __WCHAR_TYPE__ wchar_t;
+
+extern int snprintf (char*, size_t, const char*, ...);
+
+#define CONCAT(x, y) x ## y
+#define CAT(x, y) CONCAT (x, y)
+#define FAILNAME(name) CAT (call_ ## name ##_on_line_, __LINE__)
+
+#define FAIL(name) do { \
+ extern void FAILNAME (name) (void); \
+ FAILNAME (name)(); \
+ } while (0)
+
+/* Macro to emit a call to funcation named
+ call_in_true_branch_not_eliminated_on_line_NNN()
+ for each call that's expected to be eliminated. The dg-final
+ scan-tree-dump-time directive at the bottom of the test verifies
+ that no such call appears in output. */
+#define ELIM(expr) \
+ if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
+
+/* Macro to emit a call to a function named
+ call_made_in_{true,false}_branch_on_line_NNN()
+ for each call that's expected to be retained. The dg-final
+ scan-tree-dump-time directive at the bottom of the test verifies
+ that the expected number of both kinds of calls appears in output
+ (a pair for each line with the invocation of the KEEP() macro. */
+#define KEEP(expr) \
+ if (expr) \
+ FAIL (made_in_true_branch); \
+ else \
+ FAIL (made_in_false_branch)
+
+
+extern wchar_t wc;
+extern wchar_t ws[];
+
+const wchar_t ws3[] = L"12\xff";
+
+/* Verify that the following calls are eliminated. */
+
+void elim_wide_char_call (void)
+{
+ ELIM (snprintf (0, 0, "%lc", L'\0'));
+ ELIM (snprintf (0, 0, "%lc", L'1'));
+ ELIM (snprintf (0, 0, "%lc", L'a'));
+ ELIM (snprintf (0, 0, "%lc", ws3[0]));
+ ELIM (snprintf (0, 0, "%lc", ws3[1]));
+ ELIM (snprintf (0, 0, "%lc", ws3[3]));
+
+ ELIM (snprintf (0, 0, "%C", L'\0'));
+ ELIM (snprintf (0, 0, "%C", L'9'));
+ ELIM (snprintf (0, 0, "%C", L'z'));
+ ELIM (snprintf (0, 0, "%C", ws3[0]));
+ ELIM (snprintf (0, 0, "%C", ws3[1]));
+ ELIM (snprintf (0, 0, "%C", ws3[3]));
+
+ /* Verify an unknown character value within the ASCII range. */
+ if (wc < 1 || 127 < wc)
+ wc = 0;
+
+ ELIM (snprintf (0, 0, "%C", wc));
+ ELIM (snprintf (0, 0, "%C", wc));
+}
+
+void elim_wide_string_call (void)
+{
+ ELIM (snprintf (0, 0, "%ls", L""));
+}
+
+
+#line 1000
+
+ /* Verify that the following calls are not eliminated. */
+
+void keep_wide_char_call (void)
+{
+ KEEP (snprintf (0, 0, "%lc", L'\xff'));
+ KEEP (snprintf (0, 0, "%lc", L'\xffff'));
+ KEEP (snprintf (0, 0, "%lc", wc));
+ KEEP (snprintf (0, 0, "%lc", ws3[2]));
+
+ KEEP (snprintf (0, 0, "%C", L'\xff'));
+ KEEP (snprintf (0, 0, "%C", L'\xffff'));
+ KEEP (snprintf (0, 0, "%C", wc));
+ KEEP (snprintf (0, 0, "%C", ws3[2]));
+
+ /* Verify an unknown character value outside the ASCII range
+ (with 128 being the only one). */
+ if (wc < 32 || 128 < wc)
+ wc = 32;
+
+ KEEP (snprintf (0, 0, "%lc", wc));
+ KEEP (snprintf (0, 0, "%C", wc));
+}
+
+void keep_wide_string_call (void)
+{
+ KEEP (snprintf (0, 0, "%ls", L"\xff"));
+ KEEP (snprintf (0, 0, "%ls", L"\xffff"));
+ KEEP (snprintf (0, 0, "%ls", ws));
+ KEEP (snprintf (0, 0, "%ls", ws3));
+
+ KEEP (snprintf (0, 0, "%S", L"\xff"));
+ KEEP (snprintf (0, 0, "%S", L"\xffff"));
+ KEEP (snprintf (0, 0, "%S", ws));
+ KEEP (snprintf (0, 0, "%S", ws3));
+}
+
+/* { dg-final { scan-tree-dump-times "call_made_in_true_branch_not_eliminated" 0 "optimized" } }
+
+ { dg-final { scan-tree-dump-times "call_made_in_true_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 18 "optimized" } }
+ { dg-final { scan-tree-dump-times "call_made_in_false_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 18 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-11.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-11.c
new file mode 100644
index 0000000..e1effe6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-11.c
@@ -0,0 +1,65 @@
+/* PR tree-optimization/86853 - sprintf optimization for wide strings
+ doesn't account for conversion failure​
+ Exercise wide character handling in an EBCDIC execution charset.
+ { dg-do compile }
+ { dg-require-iconv "IBM1047" }
+ { dg-options "-O2 -Wall -Wno-format -Wformat-overflow -fexec-charset=IBM1047 -fdump-tree-optimized" } */
+
+typedef __WCHAR_TYPE__ wchar_t;
+
+/* Exercise wide character constants. */
+
+void test_lc_cst (void)
+{
+ /* IBM1047 0x30 maps to ASCII 0x94 which neeed not be representable
+ in the current locale (and the snprintf() call may fail). Verify
+ that snprintf() doesn't assume it is. */
+ wchar_t wc = 0x30;
+
+ int n = __builtin_snprintf (0, 0, "%lc", wc);
+ if (n < 0)
+ __builtin_abort ();
+}
+
+void test_C_cst (void)
+{
+ /* Same as above but for %C and 0x31 which maps to 0x95. */
+ wchar_t wc = 0x31;
+
+ int n = __builtin_snprintf (0, 0, "%C", wc);
+ if (n < 0)
+ __builtin_abort ();
+}
+
+/* Exercise wide character values in known ranges. */
+
+void test_lc_range (wchar_t wc)
+{
+ if (wc < 0x40 || 0x49 < wc)
+ wc = 0x40;
+
+ int n = __builtin_snprintf (0, 0, "%lc", wc);
+ if (n < 0)
+ __builtin_abort ();
+}
+
+void test_C_range (wchar_t wc)
+{
+ if (wc < 0x41 || 0x48 < wc)
+ wc = 0x41;
+
+ int n = __builtin_snprintf (0, 0, "%C", wc);
+ if (n < 0)
+ __builtin_abort ();
+}
+
+/* Exercise unknown wide character values. */
+
+void test_var (wchar_t wc)
+{
+ int n = __builtin_snprintf (0, 0, "%lc", wc);
+ if (n < 0)
+ __builtin_abort ();
+}
+
+/* { dg-final { scan-tree-dump-times "abort" 5 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c
index 3fb3e6d..a94d123 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c
@@ -1558,9 +1558,10 @@ void test_snprintf_c_const (char *d)
T (3, "%lc%c", (wint_t)'1', '2');
/* Here %lc may result in anywhere between 0 and MB_CUR_MAX characters
- so the minimum number of bytes on output is 2 (plus the terminating
- nul), but the likely number is 3 (plus the nul). */
- T (3, "%lc%c%c", (wint_t)'\x80', '2', '3'); /* { dg-warning ".%c. directive output may be truncated writing 1 byte into a region of size between 0 and 2" } */
+ so the output range is [0, 2, 6, 6] with the middle being used for
+ the diagnostic (and the extremes for optimization). The cast is
+ to prevent sign extension. */
+ T (3, "%lc%c%c", (wint_t)(unsigned char)'\x80', '2', '3'); /* { dg-warning ".%c. directive output may be truncated writing 1 byte into a region of size between 0 and 2" } */
/* It's reasonably safe that L'1' converts into the single byte '1'. */
T (3, "%lc%c%c", (wint_t)'1', '2', '3'); /* { dg-warning "output may be truncated" } */
T (3, "%lc%lc%c", (wint_t)'1', (wint_t)'2', '3'); /* { dg-warning "output may be truncated" } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-18.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-18.c
index 961fa48..7064f8a 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-18.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-18.c
@@ -18,7 +18,7 @@ void test_characters ()
T ("%A", 0.0); /* { dg-warning ".%A. directive writing between 6 and 20 " } */
T ("%a", 0.0); /* { dg-warning ".%a. directive writing between 6 and 20 " } */
- T ("%C", 'a'); /* { dg-warning ".%C. directive writing 1 byte" "bug 80537" { xfail *-*-* } } */
+ T ("%C", L'a'); /* { dg-warning ".%C. directive writing up to 6 bytes" } */
T ("%c", 'a'); /* { dg-warning ".%c. directive writing 1 byte" } */
T ("%d", 12); /* { dg-warning ".%d. directive writing 2 bytes" } */
@@ -93,7 +93,8 @@ void test_characters ()
T ("%x", 1234); /* { dg-warning ".%x. directive writing 3 bytes" } */
T ("%#X", 1235); /* { dg-warning ".%#X. directive writing 5 bytes" } */
- T ("%S", L"1"); /* { dg-warning ".%S. directive writing 1 byte" } */
+ T ("%S", L"1"); /* { dg-warning ".%S. directive writing up to 6 bytes" } */
+ T ("%ls", L"12"); /* { dg-warning ".%ls. directive writing up to 12 bytes" } */
T ("%-s", "1"); /* { dg-warning ".%-s. directive writing 1 byte" } */
/* Verify that characters in the source character set appear in
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-20.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-20.c
new file mode 100644
index 0000000..5966eab
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-20.c
@@ -0,0 +1,22 @@
+/* PR tree-optimization/87034 - missing -Wformat-overflow on a sprintf
+ %s with a wide string
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wformat-overflow -ftrack-macro-expansion=0" } */
+
+typedef __WCHAR_TYPE__ wchar_t;
+
+extern int sprintf (char*, const char*, ...);
+
+struct S
+{
+ char a[1];
+ void (*pf)(void);
+};
+
+void test (struct S *p)
+{
+ const char *q = sizeof (wchar_t) == 2
+ ? (char*)L"\x4142\x4344" : (char*)L"\x41424344\x45464748";
+
+ sprintf (p->a, "%s", q); /* { dg-warning "\\\[-Wformat-overflow" "pr87034" { xfail *-*-*} } */
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/dump-3.c b/gcc/testsuite/gcc.dg/tree-ssa/dump-3.c
index 8533124..6623e70 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/dump-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/dump-3.c
@@ -263,8 +263,8 @@ int main()
return 0;
}
-/* { dg-final { scan-tree-dump "string_0 = \"\";" "optimized" } } */
-/* { dg-final { scan-tree-dump "string_4 = \"\\\\4\";" "optimized" } } */
+/* { dg-final { scan-tree-dump "string_0 = \"\\\\x00\";" "optimized" } } */
+/* { dg-final { scan-tree-dump "string_4 = \"\\\\x04\";" "optimized" } } */
/* { dg-final { scan-tree-dump "string_28 = \"\\\\x1c\";" "optimized" } } */
/* { dg-final { scan-tree-dump "string_51 = \"3\";" "optimized" } } */
/* { dg-final { scan-tree-dump "string_255 = \"\\\\xff\";" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp11.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp11.c
new file mode 100644
index 0000000..f1373bd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp11.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+extern void link_error ();
+
+void foo (int *x)
+{
+ int *p = x + 1;
+ if (p == 0)
+ link_error ();
+}
+
+void bar (char *x, int a)
+{
+ if (a != 0)
+ {
+ char *p = x + a;
+ if (p == 0)
+ link_error ();
+ }
+}
+
+/* { dg-final { scan-tree-dump-not "link_error" "evrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-8.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-8.c
index c200748..c537580 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ifc-8.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ifc-8.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-Ofast -fdump-tree-ifcvt-details-blocks -ftree-loop-if-convert-stores" } */
+/* { dg-options "-Ofast -fdump-tree-ifcvt-details-blocks" } */
/* { dg-require-visibility "" } */
#define LEN 4096
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-cd.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-cd.c
index 4932cd7..fce3b77 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ifc-cd.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ifc-cd.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O3 -fdump-tree-ifcvt-details-blocks-details -ftree-loop-if-convert-stores" } */
+/* { dg-options "-O3 -fdump-tree-ifcvt-details-blocks-details" } */
void foo (int *x1, int *x2, int *x3, int *x4, int *y)
{
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c
index 0fa5600..9162d15 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fopt-info-loop-missed -Wunsafe-loop-optimizations" } */
+/* { dg-options "-O2 -fopt-info-loop-missed" } */
extern void g(void);
void
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr45122.c b/gcc/testsuite/gcc.dg/tree-ssa/pr45122.c
index e979b76..969fe0e 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr45122.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr45122.c
@@ -2,7 +2,7 @@
/* PR tree-optimization/45122 */
/* { dg-do run } */
-/* { dg-options "-O2 -funsafe-loop-optimizations" } */
+/* { dg-options "-O2" } */
extern void abort (void);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr78154.c b/gcc/testsuite/gcc.dg/tree-ssa/pr78154.c
index d908a39..b561503 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr78154.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr78154.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-evrp-slim" } */
+/* { dg-options "-O2 -fdump-tree-evrp-slim -fdelete-null-pointer-checks" } */
void f(void *d, const void *s, __SIZE_TYPE__ n)
{
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr83648.c b/gcc/testsuite/gcc.dg/tree-ssa/pr83648.c
index 884faf8..954eb2f 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr83648.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr83648.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-local-pure-const-details" } */
+/* { dg-options "-O2 -fdump-tree-local-pure-const-details -fdelete-null-pointer-checks" } */
void *g(unsigned n)
{
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr84512.c b/gcc/testsuite/gcc.dg/tree-ssa/pr84512.c
index 5d3f41c..056d1c4 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr84512.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr84512.c
@@ -12,5 +12,5 @@ int foo()
return res;
}
-/* Target nvptx xfail due to PR84958. */
-/* { dg-final { scan-tree-dump "return 285;" "optimized" { xfail { nvptx*-*-* || { sparc*-*-* && lp64 } } } } } */
+/* Listed targets xfailed due to PR84958. */
+/* { dg-final { scan-tree-dump "return 285;" "optimized" { xfail { { alpha*-*-* nvptx*-*-* } || { sparc*-*-* && lp64 } } } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr87126.c b/gcc/testsuite/gcc.dg/tree-ssa/pr87126.c
new file mode 100644
index 0000000..37232ba
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr87126.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-fre1" } */
+
+int a, *b;
+
+void f ()
+{
+ int d = 0, e = d;
+ while (a++)
+ ;
+ if (e)
+ goto L2;
+L1:
+ d = e;
+ b = &d;
+L2:
+ if (d)
+ goto L1;
+}
+
+/* The load of d could be eliminated if we'd value-number the
+ irreducible region in RPO of the reducible result. Likewise
+ a redundant store could be removed. */
+/* { dg-final { scan-tree-dump-times "d = 0;" 1 "fre1" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-not " = d;" "fre1" { xfail *-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr87205-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr87205-2.c
new file mode 100644
index 0000000..fb1879e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr87205-2.c
@@ -0,0 +1,18 @@
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+void f(int);
+void h(unsigned i)
+{
+ switch (i) {
+ default: __builtin_unreachable();
+ case 0: f(42); break;
+ case 1: f(42); break;
+ case 2: f(42); break;
+ case 3: f(42); break;
+ case 4: f(42); break;
+ case 5: f(42); break;
+ }
+}
+
+/* { dg-final { scan-tree-dump-not "if" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "switch" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr87205.c b/gcc/testsuite/gcc.dg/tree-ssa/pr87205.c
new file mode 100644
index 0000000..129e607
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr87205.c
@@ -0,0 +1,21 @@
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+void f( int x );
+
+void h( unsigned ix )
+{
+ switch( ix )
+ {
+ case 0: f(42); break;
+ case 1: f(42); break;
+ case 2: f(42); break;
+ case 3: f(42); break;
+ case 4: f(42); break;
+ case 5: f(42); break;
+ default: __builtin_unreachable();
+ }
+}
+
+
+/* { dg-final { scan-tree-dump-not "if" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "switch" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr87287.c b/gcc/testsuite/gcc.dg/tree-ssa/pr87287.c
new file mode 100644
index 0000000..cba4f43
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr87287.c
@@ -0,0 +1,34 @@
+/* PR tree-optimization/87287 */
+/* { dg-options "-O2 -fdump-tree-cddce1" } */
+/* { dg-final { scan-tree-dump-not " % 16" "cddce1" } } */
+/* { dg-final { scan-tree-dump-times " & 15" 4 "cddce1" } } */
+
+void f0 (void);
+
+int
+f1 (int x)
+{
+ return x % 16 == 0;
+}
+
+int
+f2 (int x)
+{
+ int y = x % 16;
+ return y != 0;
+}
+
+void
+f3 (int x)
+{
+ if (x % 16 != 0)
+ f0 ();
+}
+
+void
+f4 (int x)
+{
+ int y = x % 16;
+ if (y == 0)
+ f0 ();
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-14.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-14.c
index 3955bdd..65e2d5a 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-14.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-14.c
@@ -1,8 +1,5 @@
-/* PR tree-optimization/29738. We used not to realize that "i" can never
- become nonzero. */
-
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fdump-tree-fre1 -fdump-tree-optimized" } */
int i;
@@ -16,5 +13,7 @@ void bar (void)
foo ();
}
-/* Everything except for the "i = 0" assignment should get removed. */
-/* { dg-final { scan-tree-dump-times "if" 0 "optimized" { xfail *-*-* } } } */
+/* Everything except for the "i = 0" assignment should get removed. Value
+ numbering already figures out the if in the loop is never true. */
+/* { dg-final { scan-tree-dump-times "foo" 0 "fre1" } } */
+/* { dg-final { scan-tree-dump-times "if" 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-46.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-46.c
index d6e6351..8d6eaa3 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-46.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-46.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O -fdump-tree-fre1-details" } */
+/* { dg-options "-O2 -fdump-tree-fre1-details" } */
int x[1024];
int foo (int a, int s, unsigned int k)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-67.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-67.c
new file mode 100644
index 0000000..fab1e59
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-67.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-ccp -fdump-tree-fre1-stats" } */
+
+int foo()
+{
+ int i = 0;
+ do
+ {
+ i++;
+ }
+ while (i != 1);
+ return i;
+}
+
+/* { dg-final { scan-tree-dump "RPO iteration over 3 blocks visited 3 blocks" "fre1" } } */
+/* { dg-final { scan-tree-dump "return 1;" "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-68.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-68.c
new file mode 100644
index 0000000..d9f07bd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-68.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre1" } */
+
+struct S { char a[3]; char b[5]; } s = { "abc", "defg" };
+
+__SIZE_TYPE__
+foo (struct S s, int a, int b)
+{
+ char *p = (char *) &s.a[0];
+ if (a)
+ p = (char *) &s.a;
+ else if (b)
+ p = (char *) &s;
+ return __builtin_strlen (p);
+}
+
+__SIZE_TYPE__
+bar (int a, int b)
+{
+ char *p = (char *) &s.a[0];
+ if (a)
+ p = (char *) &s.a;
+ else if (b)
+ p = (char *) &s;
+ return __builtin_strlen (p);
+}
+
+/* { dg-final { scan-tree-dump-times "strlen \\\(&s" 2 "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/switch-2.c b/gcc/testsuite/gcc.dg/tree-ssa/switch-2.c
new file mode 100644
index 0000000..710825d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/switch-2.c
@@ -0,0 +1,25 @@
+/* { dg-do compile { target { { x86_64-*-* aarch64-*-* ia64-*-* powerpc64-*-* } && lp64 } } } */
+/* { dg-options "-O2 -fdump-tree-switchlower1" } */
+
+int global;
+
+int foo (int x)
+{
+ switch (x) {
+ case 0:
+ case 10:
+ return 1;
+ case 20:
+ case 30:
+ case 62:
+ return 2;
+ case 1000:
+ case 1010:
+ case 1025 ... 1030:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* { dg-final { scan-tree-dump ";; GIMPLE switch case clusters: BT:0-62 BT:1000-1030" "switchlower1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/switch-3.c b/gcc/testsuite/gcc.dg/tree-ssa/switch-3.c
new file mode 100644
index 0000000..44981e1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/switch-3.c
@@ -0,0 +1,20 @@
+/* { dg-options "-O2 -fdump-tree-switchlower1" } */
+
+int cipher_to_alg(int cipher)
+{
+ switch (cipher)
+ {
+ case 8: return 2;
+ case 16: return 3;
+ case 32: return 4;
+ case 64: return 6;
+ case 256: return 9;
+ case 512: return 10;
+ case 2048: return 11;
+ case 4096: return 12;
+ case 8192: return 13;
+ }
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "if \\(cipher\[^\n ]*" 12 "switchlower1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp105.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp105.c
deleted file mode 100644
index 7cdd4dd..0000000
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp105.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/* PR tree-optimization/18046 */
-/* { dg-options "-O2 -fdump-tree-vrp2-details" } */
-/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "vrp2" } } */
-/* In the 2nd VRP pass (after PRE) we expect to thread the default label of the
- 1st switch straight to that of the 2nd switch. */
-
-extern void foo (void);
-extern void bar (void);
-
-extern int i;
-void
-test (void)
-{
- switch (i)
- {
- case 0:
- foo ();
- break;
- case 1:
- bar ();
- break;
- default:
- break;
- }
-
- switch (i)
- {
- case 0:
- foo ();
- break;
- case 1:
- bar ();
- break;
- default:
- break;
- }
-}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp113.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp113.c
index 5069fdf..ab8d91e 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp113.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp113.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1" } */
+/* { dg-options "-O2 -fdump-tree-vrp1 -fdisable-tree-evrp" } */
int f(int a) {
switch (a & 1) {
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp120.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp120.c
new file mode 100644
index 0000000..4dcee23
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp120.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+#include "vrp113.c"
+
+/* { dg-final { scan-tree-dump "return 3;" "evrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp92.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp92.c
index 213aa47..5a2dbf0 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp92.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp92.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-vrp1-details -fdisable-tree-ethread" } */
+/* { dg-options "-O2 -fdisable-tree-evrp -fno-tree-fre -fdump-tree-vrp1-details -fdisable-tree-ethread" } */
void bar (void);
int foo (int i, int j)
diff --git a/gcc/testsuite/gcc.dg/uninit-suppress_2.c b/gcc/testsuite/gcc.dg/uninit-suppress_2.c
index af0f192..b617609 100644
--- a/gcc/testsuite/gcc.dg/uninit-suppress_2.c
+++ b/gcc/testsuite/gcc.dg/uninit-suppress_2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-fno-tree-ccp -fno-tree-vrp -fno-tree-fre -fno-tree-pre -fno-code-hoisting -O2 -Wuninitialized -Werror=uninitialized -Wno-error=maybe-uninitialized" } */
+/* { dg-options "-fno-tree-dominator-opts -fno-tree-ccp -fno-tree-vrp -fno-tree-fre -fno-tree-pre -fno-code-hoisting -O2 -Wuninitialized -Werror=uninitialized -Wno-error=maybe-uninitialized" } */
void blah();
void bar (int);
int gflag;
diff --git a/gcc/testsuite/gcc.dg/union-duplicate-field.c b/gcc/testsuite/gcc.dg/union-duplicate-field.c
new file mode 100644
index 0000000..da9a945
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/union-duplicate-field.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+int a0;
+
+struct S
+{
+ int a1;
+ union {
+ int a0;
+ int a1; /* { dg-error "duplicate member" } */
+ int a2, a3, a4, a5, a6, a7, a8, a9;
+ int a10, a11, a12, a13, a14, a15;
+ };
+};
+
+int f()
+{
+ struct S s;
+ return s.a0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-over-widen-1.c b/gcc/testsuite/gcc.dg/vect/bb-slp-over-widen-1.c
index a54c99d..0dd163e 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-over-widen-1.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-over-widen-1.c
@@ -63,4 +63,5 @@ main (void)
/* { dg-final { scan-tree-dump "demoting int to signed short" "slp2" { target { ! vect_widen_shift } } } } */
/* { dg-final { scan-tree-dump "demoting int to unsigned short" "slp2" { target { ! vect_widen_shift } } } } */
+/* { dg-final { scan-tree-dump {\.AVG_FLOOR} "slp2" { target vect_avg_qi } } } */
/* { dg-final { scan-tree-dump-times "basic block vectorized" 2 "slp2" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-over-widen-2.c b/gcc/testsuite/gcc.dg/vect/bb-slp-over-widen-2.c
index 7e90bea..3750fb7 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-over-widen-2.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-over-widen-2.c
@@ -62,4 +62,5 @@ main (void)
/* { dg-final { scan-tree-dump "demoting int to signed short" "slp2" { target { ! vect_widen_shift } } } } */
/* { dg-final { scan-tree-dump "demoting int to unsigned short" "slp2" { target { ! vect_widen_shift } } } } */
+/* { dg-final { scan-tree-dump {\.AVG_FLOOR} "slp2" { target vect_avg_qi } } } */
/* { dg-final { scan-tree-dump-times "basic block vectorized" 2 "slp2" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pow-1.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pow-1.c
new file mode 100644
index 0000000..5a05bd4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pow-1.c
@@ -0,0 +1,28 @@
+/* { dg-additional-options "-fno-math-errno -fdisable-tree-sincos" } */
+/* { dg-require-effective-target vect_float } */
+
+void __attribute__ ((noipa))
+f (float *a)
+{
+ a[0] = a[0] * a[0];
+ a[1] = __builtin_powf (a[1], 2);
+ a[2] = a[2] * a[2];
+ a[3] = __builtin_powf (a[3], 2);
+}
+
+float a[4] = { 1, 2, 3, 4 };
+
+int
+main (void)
+{
+ f (a);
+ for (int i = 0; i < 4; ++i)
+ {
+ if (a[i] != (i + 1) * (i + 1))
+ __builtin_abort ();
+ asm volatile ("" ::: "memory");
+ }
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-1.c b/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-1.c
new file mode 100644
index 0000000..3bc63a6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-1.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O -w" } */
+
+int foo;
+int
+nr (int xe, int z)
+{
+ int oo, wo = 0;
+
+ for (oo = 0; oo < 4; ++oo)
+ {
+ int qq;
+
+ int old_wo = wo;
+ for (qq = 0; qq < 2; ++qq)
+ {
+ wo = z + qq + old_wo;
+ xe += wo;
+ }
+ }
+ foo = wo;
+ return xe;
+}
+
+/* { dg-final { scan-tree-dump-not "double reduction: wo" "vect" } } */
+/* { dg-final { scan-tree-dump-not "OUTER LOOP VECTORIZED" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-2.c b/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-2.c
new file mode 100644
index 0000000..b208c1a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-2.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O -w" } */
+
+int
+nr (int xe)
+{
+ int oo, wo = 0;
+
+ for (oo = 0; oo < 4; ++oo)
+ {
+ int qq;
+
+ for (qq = 0; qq < 2; ++qq)
+ {
+ wo += 0x80000000;
+ xe += wo;
+ }
+ }
+ return xe;
+}
+
+/* { dg-final { scan-tree-dump "reduction used in loop" "vect" { target vect_int } } } */
+/* { dg-final { scan-tree-dump-not "OUTER LOOP VECTORIZED" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-3.c b/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-3.c
new file mode 100644
index 0000000..590c744
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-3.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O -w" } */
+
+int foo;
+int
+nr (int xe)
+{
+ int oo, wo = 0;
+
+ for (oo = 0; oo < 4; ++oo)
+ {
+ int qq;
+
+ for (qq = 0; qq < 2; ++qq)
+ {
+ wo += 0x80000000;
+ xe += wo;
+ }
+ }
+ foo = wo;
+ return xe;
+}
+
+/* { dg-final { scan-tree-dump "reduction used in loop" "vect" { target vect_int } } } */
+/* { dg-final { scan-tree-dump-not "OUTER LOOP VECTORIZED" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-4.c b/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-4.c
new file mode 100644
index 0000000..d995c9b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-4.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O -w" } */
+
+int
+nr (unsigned int xe, unsigned int qqn)
+{
+ unsigned int oo, wo = 0;
+
+ for (oo = 0; oo < 4; ++oo)
+ {
+ unsigned int qq = qqn;
+ do
+ {
+ wo += 1;
+ xe += wo;
+ }
+ while (qq-- > 0);
+ }
+ return xe;
+}
+
+/* { dg-final { scan-tree-dump "reduction used in loop" "vect" { target vect_int } } } */
+/* { dg-final { scan-tree-dump-not "OUTER LOOP VECTORIZED" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-5.c b/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-5.c
new file mode 100644
index 0000000..6e7c9d8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/no-scevccp-pr86725-5.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O -w" } */
+
+unsigned int foo;
+int
+nr (unsigned int xe, unsigned int qqn)
+{
+ unsigned int oo, wo = 0;
+
+ for (oo = 0; oo < 4; ++oo)
+ {
+ unsigned int qq = qqn;
+ do
+ {
+ wo += 1;
+ xe += qq;
+ }
+ while (qq-- > 0);
+ }
+ foo = wo;
+ return xe;
+}
+
+/* { dg-final { scan-tree-dump "OUTER LOOP VECTORIZED" "vect" { target vect_int } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/no-section-anchors-vect-69.c b/gcc/testsuite/gcc.dg/vect/no-section-anchors-vect-69.c
index f7ad45b..34317cc 100644
--- a/gcc/testsuite/gcc.dg/vect/no-section-anchors-vect-69.c
+++ b/gcc/testsuite/gcc.dg/vect/no-section-anchors-vect-69.c
@@ -119,5 +119,6 @@ int main (void)
return main1 ();
}
-/* { dg-final { scan-tree-dump-times "vectorized 4 loops" 1 "vect" } } */
-/* { dg-final { scan-tree-dump-times "Alignment of access forced using versioning" 1 "vect" { target { {! vector_alignment_reachable} && {! vect_hw_misalign} } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 4 loops" 1 "vect" { target vect_hw_misalign } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { target { ! vect_hw_misalign } } } } */
+/* { dg-final { scan-tree-dump-times "Alignment of access forced using versioning" 1 "vect" { target { { ! vector_alignment_reachable } && { ! vect_hw_misalign } } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-depend-2.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-depend-2.c
index acad8fc..1880d1e 100644
--- a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-depend-2.c
+++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-depend-2.c
@@ -51,7 +51,4 @@ int main (void)
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" {xfail { vect_no_align && { ! vect_hw_misalign } } } } } */
-/* Requires reverse for variable-length SVE, which is implemented for
- by a later patch. Until then we report it twice, once for SVE and
- once for 128-bit Advanced SIMD. */
-/* { dg-final { scan-tree-dump-times "dependence distance negative" 1 "vect" { xfail { aarch64_sve && vect_variable_length } } } } */
+/* { dg-final { scan-tree-dump-times "dependence distance negative" 1 "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-depend-3.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-depend-3.c
index 1ccfc1e..e5914d9 100644
--- a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-depend-3.c
+++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-depend-3.c
@@ -183,7 +183,4 @@ int main ()
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 4 "vect" {xfail { vect_no_align && { ! vect_hw_misalign } } } } } */
-/* f4 requires reverse for SVE, which is implemented by a later patch.
- Until then we report it twice, once for SVE and once for 128-bit
- Advanced SIMD. */
-/* { dg-final { scan-tree-dump-times "dependence distance negative" 4 "vect" { xfail { aarch64_sve && vect_variable_length } } } } */
+/* { dg-final { scan-tree-dump-times "dependence distance negative" 4 "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr65947-13.c b/gcc/testsuite/gcc.dg/vect/pr65947-13.c
index ce29045..e1d3ff5 100644
--- a/gcc/testsuite/gcc.dg/vect/pr65947-13.c
+++ b/gcc/testsuite/gcc.dg/vect/pr65947-13.c
@@ -41,4 +41,5 @@ main (void)
}
/* { dg-final { scan-tree-dump-times "LOOP VECTORIZED" 2 "vect" } } */
-/* { dg-final { scan-tree-dump-times "condition expression based on integer induction." 4 "vect" } } */
+/* { dg-final { scan-tree-dump-times "condition expression based on integer induction." 4 "vect" { xfail vect_fold_extract_last } } } */
+/* { dg-final { scan-tree-dump-times "optimizing condition reduction with FOLD_EXTRACT_LAST" 4 "vect" { target vect_fold_extract_last } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr80631-2.c b/gcc/testsuite/gcc.dg/vect/pr80631-2.c
index 6bf239a..b334ca2 100644
--- a/gcc/testsuite/gcc.dg/vect/pr80631-2.c
+++ b/gcc/testsuite/gcc.dg/vect/pr80631-2.c
@@ -72,4 +72,5 @@ main ()
}
/* { dg-final { scan-tree-dump-times "LOOP VECTORIZED" 5 "vect" { target vect_condition } } } */
-/* { dg-final { scan-tree-dump-times "condition expression based on integer induction." 10 "vect" { target vect_condition } } } */
+/* { dg-final { scan-tree-dump-times "condition expression based on integer induction." 10 "vect" { target vect_condition xfail vect_fold_extract_last } } } */
+/* { dg-final { scan-tree-dump-times "optimizing condition reduction with FOLD_EXTRACT_LAST" 10 "vect" { target vect_fold_extract_last } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr86749.c b/gcc/testsuite/gcc.dg/vect/pr86749.c
new file mode 100644
index 0000000..803bcb0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr86749.c
@@ -0,0 +1,26 @@
+/* { dg-additional-options "-O3" } */
+
+#include "tree-vect.h"
+
+short a, b, f, g;
+int c = 4, d, e = -1L;
+long h = 4;
+
+int
+main ()
+{
+ check_vect ();
+
+ long i;
+ for (; d <= 55; d++)
+ {
+ g = c >= 2 ? 0 : b << c;
+ f = g - a;
+ i = (f ^ 9223372036854775807) < 0 ? f : h;
+ e &= i;
+ }
+ if (e != 4)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr86858.c b/gcc/testsuite/gcc.dg/vect/pr86858.c
new file mode 100644
index 0000000..6c3c6ec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr86858.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+
+int a, b, c, d;
+char e(char f, char g) { return f + g; }
+void h() {
+ for (; c; ++c) {
+ d = 0;
+ for (; d != 8; d = e(d, 3)) {
+ a = b && a;
+ b = c;
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr86871.c b/gcc/testsuite/gcc.dg/vect/pr86871.c
new file mode 100644
index 0000000..a181681
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr86871.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+
+extern int b[];
+extern int c[];
+void g(int f) {
+ for (; f; f++) {
+ int d = 0;
+ for (int e = -1; e <= 1; e++) {
+ int a = f + e;
+ if (a)
+ d = *(c + a);
+ }
+ *(b + f) = d;
+ }
+ }
diff --git a/gcc/testsuite/gcc.dg/vect/pr86927.c b/gcc/testsuite/gcc.dg/vect/pr86927.c
new file mode 100644
index 0000000..794092b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr86927.c
@@ -0,0 +1,15 @@
+#include "tree-vect.h"
+
+int a[28];
+int main()
+{
+ check_vect ();
+ a[4] = 1;
+ int c = 1;
+ for (int b = 0; b < 8; b++)
+ if (a[b])
+ c = 0;
+ if (c)
+ abort();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr87288-1.c b/gcc/testsuite/gcc.dg/vect/pr87288-1.c
new file mode 100644
index 0000000..0d0a70d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr87288-1.c
@@ -0,0 +1,49 @@
+#include "tree-vect.h"
+
+#define N (VECTOR_BITS / 32)
+#define MAX_COUNT 4
+
+void __attribute__ ((noipa))
+run (int *restrict a, int *restrict b, int count)
+{
+ for (int i = 0; i < count * N; ++i)
+ {
+ a[i * 2] = b[i * 2] + count;
+ a[i * 2 + 1] = count;
+ }
+}
+
+void __attribute__ ((noipa))
+check (int *restrict a, int count)
+{
+ for (int i = 0; i < count * N; ++i)
+ if (a[i * 2] != i * 41 + count || a[i * 2 + 1] != count)
+ __builtin_abort ();
+ if (a[count * 2 * N] != 999)
+ __builtin_abort ();
+}
+
+int a[N * MAX_COUNT * 2 + 1], b[N * MAX_COUNT * 2];
+
+int
+main (void)
+{
+ check_vect ();
+
+ for (int i = 0; i < N * MAX_COUNT; ++i)
+ {
+ b[i * 2] = i * 41;
+ asm volatile ("" ::: "memory");
+ }
+
+ for (int i = 0; i <= MAX_COUNT; ++i)
+ {
+ a[i * 2 * N] = 999;
+ run (a, b, i);
+ check (a, i);
+ }
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times {LOOP VECTORIZED} 1 "vect" { target { { vect_int && vect_perm } && vect_element_align } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr87288-2.c b/gcc/testsuite/gcc.dg/vect/pr87288-2.c
new file mode 100644
index 0000000..e9ff9a0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr87288-2.c
@@ -0,0 +1,64 @@
+#include "tree-vect.h"
+
+#define N (VECTOR_BITS / 32)
+#define MAX_COUNT 4
+
+#define RUN_COUNT(COUNT) \
+ void __attribute__ ((noipa)) \
+ run_##COUNT (int *restrict a, int *restrict b) \
+ { \
+ for (int i = 0; i < N * COUNT; ++i) \
+ { \
+ a[i * 2] = b[i * 2] + COUNT; \
+ a[i * 2 + 1] = COUNT; \
+ } \
+ }
+
+RUN_COUNT (1)
+RUN_COUNT (2)
+RUN_COUNT (3)
+RUN_COUNT (4)
+
+void __attribute__ ((noipa))
+check (int *restrict a, int count)
+{
+ for (int i = 0; i < count * N; ++i)
+ if (a[i * 2] != i * 41 + count || a[i * 2 + 1] != count)
+ __builtin_abort ();
+ if (a[count * 2 * N] != 999)
+ __builtin_abort ();
+}
+
+int a[N * MAX_COUNT * 2 + 1], b[N * MAX_COUNT * 2];
+
+int
+main (void)
+{
+ check_vect ();
+
+ for (int i = 0; i < N * MAX_COUNT; ++i)
+ {
+ b[i * 2] = i * 41;
+ asm volatile ("" ::: "memory");
+ }
+
+ a[N * 2] = 999;
+ run_1 (a, b);
+ check (a, 1);
+
+ a[N * 4] = 999;
+ run_2 (a, b);
+ check (a, 2);
+
+ a[N * 6] = 999;
+ run_3 (a, b);
+ check (a, 3);
+
+ a[N * 8] = 999;
+ run_4 (a, b);
+ check (a, 4);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump {LOOP VECTORIZED} "vect" { target { { vect_int && vect_perm } && vect_element_align } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr87288-3.c b/gcc/testsuite/gcc.dg/vect/pr87288-3.c
new file mode 100644
index 0000000..23f574c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr87288-3.c
@@ -0,0 +1,64 @@
+#include "tree-vect.h"
+
+#define N (VECTOR_BITS / 32)
+#define MAX_COUNT 4
+
+#define RUN_COUNT(COUNT) \
+ void __attribute__ ((noipa)) \
+ run_##COUNT (int *restrict a, int *restrict b) \
+ { \
+ for (int i = 0; i < N * COUNT + 1; ++i) \
+ { \
+ a[i * 2] = b[i * 2] + COUNT; \
+ a[i * 2 + 1] = COUNT; \
+ } \
+ }
+
+RUN_COUNT (1)
+RUN_COUNT (2)
+RUN_COUNT (3)
+RUN_COUNT (4)
+
+void __attribute__ ((noipa))
+check (int *restrict a, int count)
+{
+ for (int i = 0; i < count * N + 1; ++i)
+ if (a[i * 2] != i * 41 + count || a[i * 2 + 1] != count)
+ __builtin_abort ();
+ if (a[count * 2 * N + 2] != 999)
+ __builtin_abort ();
+}
+
+int a[N * MAX_COUNT * 2 + 3], b[N * MAX_COUNT * 2 + 2];
+
+int
+main (void)
+{
+ check_vect ();
+
+ for (int i = 0; i < N * MAX_COUNT + 1; ++i)
+ {
+ b[i * 2] = i * 41;
+ asm volatile ("" ::: "memory");
+ }
+
+ a[N * 2 + 2] = 999;
+ run_1 (a, b);
+ check (a, 1);
+
+ a[N * 4 + 2] = 999;
+ run_2 (a, b);
+ check (a, 2);
+
+ a[N * 6 + 2] = 999;
+ run_3 (a, b);
+ check (a, 3);
+
+ a[N * 8 + 2] = 999;
+ run_4 (a, b);
+ check (a, 4);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump {LOOP VECTORIZED} "vect" { target { { vect_int && vect_perm } && vect_element_align } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/slp-23.c b/gcc/testsuite/gcc.dg/vect/slp-23.c
index 3cda497..7d330c7 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-23.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-23.c
@@ -107,8 +107,8 @@ int main (void)
/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { target { vect_strided8 && { ! { vect_no_align} } } } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { ! { vect_strided8 || vect_no_align } } } } } */
-/* We fail to vectorize the second loop with variable-length SVE but
- fall back to 128-bit vectors, which does use SLP. */
/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { ! vect_perm } } } } */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target vect_perm } } } */
+/* SLP fails for the second loop with variable-length SVE because
+ the load size is greater than the minimum vector size. */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target vect_perm xfail { aarch64_sve && vect_variable_length } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/slp-37.c b/gcc/testsuite/gcc.dg/vect/slp-37.c
index b6a044d..a765cd7 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-37.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-37.c
@@ -17,8 +17,8 @@ foo1 (s1 *arr)
int i;
s1 *ptr = arr;
- /* Different constant types - not SLPable. The group size is not power of 2,
- interleaving is not supported either. */
+ /* Vectorized as a strided SLP pair of accesses to <a, b> and a single
+ strided access to c. */
for (i = 0; i < N; i++)
{
ptr->a = 6;
@@ -58,6 +58,5 @@ int main (void)
return 0;
}
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" } } */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" } } */
-
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_hw_misalign } } } */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target vect_hw_misalign } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/slp-perm-10.c b/gcc/testsuite/gcc.dg/vect/slp-perm-10.c
index 1c2a858..678152b 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-perm-10.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-perm-10.c
@@ -50,4 +50,6 @@ int main ()
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_perm } } } */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target vect_perm } } } */
+/* SLP fails for variable-length SVE because the load size is greater
+ than the minimum vector size. */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target vect_perm xfail { aarch64_sve && vect_variable_length } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/slp-perm-9.c b/gcc/testsuite/gcc.dg/vect/slp-perm-9.c
index b01d493..c54420a 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-perm-9.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-perm-9.c
@@ -59,7 +59,9 @@ int main (int argc, const char* argv[])
/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 2 "vect" { target { ! { vect_perm_short || vect_load_lanes } } } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_perm_short || vect_load_lanes } } } } */
-/* { dg-final { scan-tree-dump-times "permutation requires at least three vectors" 1 "vect" { target { vect_perm_short && { ! vect_perm3_short } } } } } */
+/* We don't try permutes with a group size of 3 for variable-length
+ vectors. */
+/* { dg-final { scan-tree-dump-times "permutation requires at least three vectors" 1 "vect" { target { vect_perm_short && { ! vect_perm3_short } } xfail vect_variable_length } } } */
/* { dg-final { scan-tree-dump-not "permutation requires at least three vectors" "vect" { target vect_perm3_short } } } */
/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target { { ! vect_perm3_short } || vect_load_lanes } } } } */
/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { vect_perm3_short && { ! vect_load_lanes } } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-avg-15.c b/gcc/testsuite/gcc.dg/vect/vect-avg-15.c
new file mode 100644
index 0000000..48d7ed7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-avg-15.c
@@ -0,0 +1,52 @@
+/* { dg-additional-options "-O3" } */
+/* { dg-require-effective-target vect_int } */
+
+#include "tree-vect.h"
+
+#define N 80
+
+void __attribute__ ((noipa))
+f (signed char *restrict a, signed char *restrict b,
+ signed char *restrict c, int n, int step)
+{
+ for (int j = 0; j < n; ++j)
+ {
+ for (int i = 0; i < 16; ++i)
+ a[i] = (b[i] + c[i]) >> 1;
+ a += step;
+ b += step;
+ c += step;
+ }
+}
+
+#define BASE1 -126
+#define BASE2 -42
+
+signed char a[N], b[N], c[N];
+
+int
+main (void)
+{
+ check_vect ();
+
+ for (int i = 0; i < N; ++i)
+ {
+ a[i] = i;
+ b[i] = BASE1 + i * 3;
+ c[i] = BASE2 + i * 2;
+ asm volatile ("" ::: "memory");
+ }
+ f (a, b, c, N / 20, 20);
+ for (int i = 0; i < N; ++i)
+ {
+ int d = (BASE1 + BASE2 + i * 5) >> 1;
+ if (a[i] != (i % 20 < 16 ? d : i))
+ __builtin_abort ();
+ }
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "vect_recog_average_pattern: detected" "vect" } } */
+/* { dg-final { scan-tree-dump {\.AVG_FLOOR} "vect" { target vect_avg_qi } } } */
+/* { dg-final { scan-tree-dump "Loop contains only SLP stmts" "vect" { target vect_avg_qi } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loop" 1 "vect" { target vect_avg_qi } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-avg-16.c b/gcc/testsuite/gcc.dg/vect/vect-avg-16.c
new file mode 100644
index 0000000..f3e3839
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-avg-16.c
@@ -0,0 +1,52 @@
+/* { dg-additional-options "-O3" } */
+/* { dg-require-effective-target vect_int } */
+
+#include "tree-vect.h"
+
+#define N 80
+
+void __attribute__ ((noipa))
+f (signed char *restrict a, signed char *restrict b,
+ signed char *restrict c, int n)
+{
+ for (int j = 0; j < n; ++j)
+ {
+ for (int i = 0; i < 16; ++i)
+ a[i] = (b[i] + c[i]) >> 1;
+ a += 20;
+ b += 20;
+ c += 20;
+ }
+}
+
+#define BASE1 -126
+#define BASE2 -42
+
+signed char a[N], b[N], c[N];
+
+int
+main (void)
+{
+ check_vect ();
+
+ for (int i = 0; i < N; ++i)
+ {
+ a[i] = i;
+ b[i] = BASE1 + i * 3;
+ c[i] = BASE2 + i * 2;
+ asm volatile ("" ::: "memory");
+ }
+ f (a, b, c, N / 20);
+ for (int i = 0; i < N; ++i)
+ {
+ int d = (BASE1 + BASE2 + i * 5) >> 1;
+ if (a[i] != (i % 20 < 16 ? d : i))
+ __builtin_abort ();
+ }
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "vect_recog_average_pattern: detected" "vect" } } */
+/* { dg-final { scan-tree-dump {\.AVG_FLOOR} "vect" { target vect_avg_qi } } } */
+/* { dg-final { scan-tree-dump "Loop contains only SLP stmts" "vect" { target vect_avg_qi } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loop" 1 "vect" { target vect_avg_qi } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8-gap4-big-array.c b/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8-gap4-big-array.c
index 28ba417..b5eb87f 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8-gap4-big-array.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8-gap4-big-array.c
@@ -55,7 +55,7 @@ main1 (s *arr)
}
ptr = arr;
- /* Not vectorizable: gap in store. */
+ /* Vectorized as a strided SLP pair. */
for (i = 0; i < N; i++)
{
res[i].a = ptr->b;
@@ -110,5 +110,4 @@ int main (void)
return 0;
}
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided8 } } } */
-
+/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { target vect_strided8 } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8-gap4.c b/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8-gap4.c
index 901b1a9..f1d05a5 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8-gap4.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8-gap4.c
@@ -53,7 +53,7 @@ main1 (s *arr)
}
ptr = arr;
- /* Not vectorizable: gap in store. */
+ /* Vectorized as a strided SLP pair. */
for (i = 0; i < N; i++)
{
res[i].a = ptr->b;
@@ -97,5 +97,4 @@ int main (void)
return 0;
}
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided8 } } } */
-
+/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { target vect_strided8 } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect.exp b/gcc/testsuite/gcc.dg/vect/vect.exp
index 369ece7..fc5c1b8 100644
--- a/gcc/testsuite/gcc.dg/vect/vect.exp
+++ b/gcc/testsuite/gcc.dg/vect/vect.exp
@@ -262,13 +262,6 @@ et-dg-runtest dg-runtest [lsort \
[glob -nocomplain $srcdir/$subdir/ggc-*.\[cS\]]] \
"" $DEFAULT_VECTCFLAGS
-# -ftree-loop-if-convert-stores
-set DEFAULT_VECTCFLAGS $SAVED_DEFAULT_VECTCFLAGS
-lappend DEFAULT_VECTCFLAGS "-ftree-loop-if-convert-stores"
-et-dg-runtest dg-runtest [lsort \
- [glob -nocomplain $srcdir/$subdir/if-cvt-stores-vect-*.\[cS\]]] \
- "" $DEFAULT_VECTCFLAGS
-
# With -O3.
# Don't allow IPA cloning, because it throws our counts out of whack.
set DEFAULT_VECTCFLAGS $SAVED_DEFAULT_VECTCFLAGS
diff --git a/gcc/testsuite/gcc.dg/warn-abs-1.c b/gcc/testsuite/gcc.dg/warn-abs-1.c
new file mode 100644
index 0000000..129a3af
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/warn-abs-1.c
@@ -0,0 +1,68 @@
+/* { dg-do compile { target float128 } } */
+/* { dg-skip-if "incomplete long double support" { { newlib } && large_long_double } } */
+/* { dg-options "-Wabsolute-value" } */
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <math.h>
+#include <complex.h>
+
+void
+tst_unsigned (unsigned *pu, unsigned long *pl, unsigned long long *pll,
+ uintmax_t *pm)
+{
+ *pu = abs (*pu); /* { dg-warning "taking the absolute value of unsigned type" } */
+ *pl = labs (*pl); /* { dg-warning "taking the absolute value of unsigned type" } */
+ *pll = llabs (*pll); /* { dg-warning "taking the absolute value of unsigned type" } */
+ *pm = imaxabs (*pm); /* { dg-warning "taking the absolute value of unsigned type" } */
+}
+
+void
+test_int_size (long long *pll)
+{
+ *pll = abs (*pll); /* { dg-warning "may cause truncation of value" } */
+ *pll = abs ((int) *pll);
+}
+
+void
+tst_notint (float *pf, double *pd, _Complex double *pc)
+{
+ *pf = abs (*pf); /* { dg-warning "using integer absolute value function" } */
+ *pd = labs (*pd); /* { dg-warning "using integer absolute value function" } */
+ *pc = abs (*pc); /* { dg-warning "using integer absolute value function" } */
+}
+
+void
+tst_notfloat (int *pi, long *pl, complex double *pc)
+{
+ *pi = fabsf (*pi); /* { dg-warning "using floating point absolute value function" } */
+ *pl = fabs (*pl); /* { dg-warning "using floating point absolute value function" } */
+ *pc = fabs (*pc); /* { dg-warning "using floating point absolute value function" } */
+}
+
+void
+tst_float_size (double *pd, long double *pld, _Float128 *pf128)
+{
+ *pd = fabsf (*pd); /* { dg-warning "may cause truncation of value" } */
+ *pld = fabs (*pld); /* { dg-warning "may cause truncation of value" } */
+ *pld = fabs ((double) *pld);
+ *pf128 = fabsl (*pf128); /* { dg-warning "may cause truncation of value" } */
+}
+
+void tst_notcomplex (int *pi, long *pl, long double *pld)
+{
+ *pi = cabs (*pi); /* { dg-warning "using complex absolute value function" } */
+ *pl = cabs (*pl); /* { dg-warning "using complex absolute value function" } */
+ *pld = cabsl (*pld);/* { dg-warning "using complex absolute value function" } */
+}
+
+void tst_cplx_size (complex double *pcd, complex long double *pcld)
+{
+ *pcd = cabsf (*pcd); /* { dg-warning "may cause truncation of value" } */
+ *pcld = cabs (*pcld); /* { dg-warning "may cause truncation of value" } */
+ *pcld = cabs ((complex double) *pcld);
+}
+
+
+
+
diff --git a/gcc/testsuite/gcc.dg/warn-stpcpy-no-nul.c b/gcc/testsuite/gcc.dg/warn-stpcpy-no-nul.c
new file mode 100644
index 0000000..78c4a7f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/warn-stpcpy-no-nul.c
@@ -0,0 +1,324 @@
+/* PR tree-optimization/86552 - missing warning for reading past the end
+ of non-string arrays
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */
+
+extern char* stpcpy (char*, const char*);
+
+const char a[5] = "12345"; /* { dg-message "declared here" } */
+
+int v0 = 0;
+int v1 = 1;
+int v2 = 1;
+int v3 = 1;
+
+void sink (char*, ...);
+
+#define T(str) sink (stpcpy (d, str))
+
+void test_one_dim_array (char *d)
+{
+ T (a); /* { dg-warning "argument missing terminating nul" } */
+ T (&a[0]); /* { dg-warning "nul" } */
+ T (&a[0] + 1); /* { dg-warning "nul" } */
+ T (&a[1]); /* { dg-warning "nul" } */
+
+ int i0 = 0;
+ int i1 = i0 + 1;
+
+ T (&a[i0]); /* { dg-warning "nul" } */
+ T (&a[i0] + 1); /* { dg-warning "nul" } */
+ T (&a[i1]); /* { dg-warning "nul" } */
+
+ T (&a[v0]); /* { dg-warning "nul" } */
+ T (&a[v0] + 1); /* { dg-warning "nul" } */
+ T (&a[v0] + v1); /* { dg-warning "nul" } */
+}
+
+const char b[][5] = { /* { dg-message "declared here" } */
+ "12", "123", "1234", "54321"
+};
+
+void test_two_dim_array (char *d)
+{
+ int i0 = 0;
+ int i1 = i0 + 1;
+ int i2 = i1 + 1;
+ int i3 = i2 + 1;
+
+ T (b[0]);
+ T (b[1]);
+ T (b[2]);
+ T (b[3]); /* { dg-warning "nul" } */
+ T (b[i0]);
+ T (b[i1]);
+ T (b[i2]);
+ T (b[i3]); /* { dg-warning "nul" } */
+ T (b[v0]);
+ T (b[v3]);
+
+ T (&b[2][1]);
+ T (&b[2][1] + 1);
+ T (&b[2][v0]);
+ T (&b[2][1] + v0);
+
+ T (&b[i2][i1]);
+ T (&b[i2][i1] + i1);
+ T (&b[i2][v0]);
+ T (&b[i2][i1] + v0);
+
+ T (&b[3][1]); /* { dg-warning "nul" } */
+ T (&b[3][1] + 1); /* { dg-warning "nul" } */
+ T (&b[3][v0]); /* { dg-warning "nul" } */
+ T (&b[3][1] + v0); /* { dg-warning "nul" } */
+ T (&b[3][v0] + v1); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+
+ T (&b[i3][i1]); /* { dg-warning "nul" } */
+ T (&b[i3][i1] + i1); /* { dg-warning "nul" } */
+ T (&b[i3][v0]); /* { dg-warning "nul" } */
+ T (&b[i3][i1] + v0); /* { dg-warning "nul" } */
+ T (&b[i3][v0] + v1); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+
+ T (v0 ? "" : b[0]);
+ T (v0 ? "" : b[1]);
+ T (v0 ? "" : b[2]);
+ T (v0 ? "" : b[3]); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+ T (v0 ? b[0] : "");
+ T (v0 ? b[1] : "");
+ T (v0 ? b[2] : "");
+ T (v0 ? b[3] : ""); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+
+ T (v0 ? "1234" : b[3]); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+ T (v0 ? b[3] : "1234"); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+
+ T (v0 ? a : b[3]); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+ T (v0 ? b[0] : b[2]);
+ T (v0 ? b[2] : b[3]); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+ T (v0 ? b[3] : b[2]); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+
+ T (v0 ? b[0] : &b[3][0] + 1); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+ T (v0 ? b[1] : &b[3][1] + v0); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+
+ /* It's possible to detect the missing nul in the following two
+ expressions but GCC doesn't do it yet. */
+ T (v0 ? &b[3][1] + v0 : b[2]); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+ T (v0 ? &b[3][v0] : &b[3][v1]); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+}
+
+struct A { char a[5], b[5]; };
+
+const struct A s = { "1234", "12345" };
+
+void test_struct_member (char *d)
+{
+ int i0 = 0;
+ int i1 = i0 + 1;
+
+ T (s.a);
+ T (&s.a[0]);
+ T (&s.a[0] + 1);
+ T (&s.a[0] + i0);
+ T (&s.a[1]);
+ T (&s.a[1] + 1);
+ T (&s.a[1] + i0);
+
+ T (&s.a[i0]);
+ T (&s.a[i0] + 1);
+ T (&s.a[i0] + v0);
+ T (&s.a[i1]);
+ T (&s.a[i1] + 1);
+ T (&s.a[i1] + v0);
+
+ T (s.a);
+ T (&s.a[0]);
+ T (&s.a[0] + 1);
+ T (&s.a[0] + v0);
+ T (&s.a[1]);
+ T (&s.a[1] + 1);
+ T (&s.a[1] + v0);
+
+ T (&s.a[i0]);
+ T (&s.a[i0] + 1);
+ T (&s.a[i0] + v0);
+ T (&s.a[i1]);
+ T (&s.a[i1] + 1);
+ T (&s.a[i1] + v0);
+
+ T (&s.a[v0]);
+ T (&s.a[v0] + 1);
+ T (&s.a[v0] + v0);
+ T (&s.a[v1]);
+ T (&s.a[v1] + 1);
+ T (&s.a[v1] + v0);
+
+ T (s.b); /* { dg-warning "nul" } */
+ T (&s.b[0]); /* { dg-warning "nul" } */
+ T (&s.b[0] + 1); /* { dg-warning "nul" } */
+ T (&s.b[0] + i0); /* { dg-warning "nul" } */
+ T (&s.b[1]); /* { dg-warning "nul" } */
+ T (&s.b[1] + 1); /* { dg-warning "nul" } */
+ T (&s.b[1] + i0); /* { dg-warning "nul" } */
+
+ T (s.b); /* { dg-warning "nul" } */
+ T (&s.b[0]); /* { dg-warning "nul" } */
+ T (&s.b[0] + 1); /* { dg-warning "nul" } */
+ T (&s.b[0] + v0); /* { dg-warning "nul" } */
+ T (&s.b[1]); /* { dg-warning "nul" } */
+ T (&s.b[1] + 1); /* { dg-warning "nul" } */
+ T (&s.b[1] + v0); /* { dg-warning "nul" } */
+
+ T (s.b); /* { dg-warning "nul" } */
+ T (&s.b[v0]); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+ T (&s.b[v0] + 1); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+ T (&s.b[v0] + v0); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+ T (&s.b[v1]); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+ T (&s.b[v1] + 1); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+ T (&s.b[v1] + v0); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+}
+
+struct B { struct A a[2]; };
+
+const struct B ba[] = {
+ { { { "123", "12345" }, { "12345", "123" } } },
+ { { { "12345", "123" }, { "123", "12345" } } },
+ { { { "1", "12" }, { "123", "1234" } } },
+ { { { "123", "1234" }, { "12345", "12" } } }
+};
+
+void test_array_of_structs (char *d)
+{
+ T (ba[0].a[0].a);
+ T (&ba[0].a[0].a[0]);
+ T (&ba[0].a[0].a[0] + 1);
+ T (&ba[0].a[0].a[0] + v0);
+ T (&ba[0].a[0].a[1]);
+ T (&ba[0].a[0].a[1] + 1);
+ T (&ba[0].a[0].a[1] + v0);
+
+ T (ba[0].a[0].b); /* { dg-warning "nul" } */
+ T (&ba[0].a[0].b[0]); /* { dg-warning "nul" } */
+ T (&ba[0].a[0].b[0] + 1); /* { dg-warning "nul" } */
+ T (&ba[0].a[0].b[0] + v0); /* { dg-warning "nul" } */
+ T (&ba[0].a[0].b[1]); /* { dg-warning "nul" } */
+ T (&ba[0].a[0].b[1] + 1); /* { dg-warning "nul" } */
+ T (&ba[0].a[0].b[1] + v0); /* { dg-warning "nul" } */
+
+ T (ba[0].a[1].a); /* { dg-warning "nul" } */
+ T (&ba[0].a[1].a[0]); /* { dg-warning "nul" } */
+ T (&ba[0].a[1].a[0] + 1); /* { dg-warning "nul" } */
+ T (&ba[0].a[1].a[0] + v0); /* { dg-warning "nul" } */
+ T (&ba[0].a[1].a[1]); /* { dg-warning "nul" } */
+ T (&ba[0].a[1].a[1] + 1); /* { dg-warning "nul" } */
+ T (&ba[0].a[1].a[1] + v0); /* { dg-warning "nul" } */
+
+ T (ba[0].a[1].b);
+ T (&ba[0].a[1].b[0]);
+ T (&ba[0].a[1].b[0] + 1);
+ T (&ba[0].a[1].b[0] + v0);
+ T (&ba[0].a[1].b[1]);
+ T (&ba[0].a[1].b[1] + 1);
+ T (&ba[0].a[1].b[1] + v0);
+
+
+ T (ba[1].a[0].a); /* { dg-warning "nul" } */
+ T (&ba[1].a[0].a[0]); /* { dg-warning "nul" } */
+ T (&ba[1].a[0].a[0] + 1); /* { dg-warning "nul" } */
+ T (&ba[1].a[0].a[0] + v0); /* { dg-warning "nul" } */
+ T (&ba[1].a[0].a[1]); /* { dg-warning "nul" } */
+ T (&ba[1].a[0].a[1] + 1); /* { dg-warning "nul" } */
+ T (&ba[1].a[0].a[1] + v0); /* { dg-warning "nul" } */
+
+ T (ba[1].a[0].b);
+ T (&ba[1].a[0].b[0]);
+ T (&ba[1].a[0].b[0] + 1);
+ T (&ba[1].a[0].b[0] + v0);
+ T (&ba[1].a[0].b[1]);
+ T (&ba[1].a[0].b[1] + 1);
+ T (&ba[1].a[0].b[1] + v0);
+
+ T (ba[1].a[1].a);
+ T (&ba[1].a[1].a[0]);
+ T (&ba[1].a[1].a[0] + 1);
+ T (&ba[1].a[1].a[0] + v0);
+ T (&ba[1].a[1].a[1]);
+ T (&ba[1].a[1].a[1] + 1);
+ T (&ba[1].a[1].a[1] + v0);
+
+ T (ba[1].a[1].b); /* { dg-warning "nul" } */
+ T (&ba[1].a[1].b[0]); /* { dg-warning "nul" } */
+ T (&ba[1].a[1].b[0] + 1); /* { dg-warning "nul" } */
+ T (&ba[1].a[1].b[0] + v0); /* { dg-warning "nul" } */
+ T (&ba[1].a[1].b[1]); /* { dg-warning "nul" } */
+ T (&ba[1].a[1].b[1] + 1); /* { dg-warning "nul" } */
+ T (&ba[1].a[1].b[1] + v0); /* { dg-warning "nul" } */
+
+
+ T (ba[2].a[0].a);
+ T (&ba[2].a[0].a[0]);
+ T (&ba[2].a[0].a[0] + 1);
+ T (&ba[2].a[0].a[0] + v0);
+ T (&ba[2].a[0].a[1]);
+ T (&ba[2].a[0].a[1] + 1);
+ T (&ba[2].a[0].a[1] + v0);
+
+ T (ba[2].a[0].b);
+ T (&ba[2].a[0].b[0]);
+ T (&ba[2].a[0].b[0] + 1);
+ T (&ba[2].a[0].b[0] + v0);
+ T (&ba[2].a[0].b[1]);
+ T (&ba[2].a[0].b[1] + 1);
+ T (&ba[2].a[0].b[1] + v0);
+
+ T (ba[2].a[1].a);
+ T (&ba[2].a[1].a[0]);
+ T (&ba[2].a[1].a[0] + 1);
+ T (&ba[2].a[1].a[0] + v0);
+ T (&ba[2].a[1].a[1]);
+ T (&ba[2].a[1].a[1] + 1);
+ T (&ba[2].a[1].a[1] + v0);
+
+
+ T (ba[3].a[0].a);
+ T (&ba[3].a[0].a[0]);
+ T (&ba[3].a[0].a[0] + 1);
+ T (&ba[3].a[0].a[0] + v0);
+ T (&ba[3].a[0].a[1]);
+ T (&ba[3].a[0].a[1] + 1);
+ T (&ba[3].a[0].a[1] + v0);
+
+ T (ba[3].a[0].b);
+ T (&ba[3].a[0].b[0]);
+ T (&ba[3].a[0].b[0] + 1);
+ T (&ba[3].a[0].b[0] + v0);
+ T (&ba[3].a[0].b[1]);
+ T (&ba[3].a[0].b[1] + 1);
+ T (&ba[3].a[0].b[1] + v0);
+
+ T (ba[3].a[1].a); /* { dg-warning "nul" } */
+ T (&ba[3].a[1].a[0]); /* { dg-warning "nul" } */
+ T (&ba[3].a[1].a[0] + 1); /* { dg-warning "nul" } */
+ T (&ba[3].a[1].a[0] + v0); /* { dg-warning "nul" } */
+ T (&ba[3].a[1].a[1]); /* { dg-warning "nul" } */
+ T (&ba[3].a[1].a[1] + 1); /* { dg-warning "nul" } */
+ T (&ba[3].a[1].a[1] + v0); /* { dg-warning "nul" } */
+
+ T (ba[3].a[1].b);
+ T (&ba[3].a[1].b[0]);
+ T (&ba[3].a[1].b[0] + 1);
+ T (&ba[3].a[1].b[0] + v0);
+ T (&ba[3].a[1].b[1]);
+ T (&ba[3].a[1].b[1] + 1);
+ T (&ba[3].a[1].b[1] + v0);
+
+
+ T (v0 ? ba[0].a[0].a : ba[0].a[0].b); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+ T (v0 ? ba[0].a[0].a : ba[0].a[0].b); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+
+ T (v0 ? &ba[0].a[0].a[0] : &ba[3].a[1].a[0]); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+ T (v0 ? &ba[3].a[1].a[1] : ba[0].a[0].a); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+
+ T (v0 ? ba[0].a[0].a : ba[0].a[1].b);
+ T (v0 ? ba[0].a[1].b : ba[0].a[0].a);
+}
+
+/* { dg-prune-output " reading \[1-9\]\[0-9\]? bytes from a region " } */
diff --git a/gcc/testsuite/gcc.dg/warn-strcpy-no-nul.c b/gcc/testsuite/gcc.dg/warn-strcpy-no-nul.c
new file mode 100644
index 0000000..b5ed21d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/warn-strcpy-no-nul.c
@@ -0,0 +1,324 @@
+/* PR tree-optimization/86552 - missing warning for reading past the end
+ of non-string arrays
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */
+
+extern char* strcpy (char*, const char*);
+
+const char a[5] = "12345"; /* { dg-message "declared here" } */
+
+int v0 = 0;
+int v1 = 1;
+int v2 = 1;
+int v3 = 1;
+
+void sink (char*, ...);
+
+#define T(str) sink (strcpy (d, str))
+
+void test_one_dim_array (char *d)
+{
+ T (a); /* { dg-warning "argument missing terminating nul" } */
+ T (&a[0]); /* { dg-warning "nul" } */
+ T (&a[0] + 1); /* { dg-warning "nul" } */
+ T (&a[1]); /* { dg-warning "nul" } */
+
+ int i0 = 0;
+ int i1 = i0 + 1;
+
+ T (&a[i0]); /* { dg-warning "nul" } */
+ T (&a[i0] + 1); /* { dg-warning "nul" } */
+ T (&a[i1]); /* { dg-warning "nul" } */
+
+ T (&a[v0]); /* { dg-warning "nul" } */
+ T (&a[v0] + 1); /* { dg-warning "nul" } */
+ T (&a[v0] + v1); /* { dg-warning "nul" } */
+}
+
+const char b[][5] = { /* { dg-message "declared here" } */
+ "12", "123", "1234", "54321"
+};
+
+void test_two_dim_array (char *d)
+{
+ int i0 = 0;
+ int i1 = i0 + 1;
+ int i2 = i1 + 1;
+ int i3 = i2 + 1;
+
+ T (b[0]);
+ T (b[1]);
+ T (b[2]);
+ T (b[3]); /* { dg-warning "nul" } */
+ T (b[i0]);
+ T (b[i1]);
+ T (b[i2]);
+ T (b[i3]); /* { dg-warning "nul" } */
+ T (b[v0]);
+ T (b[v3]);
+
+ T (&b[2][1]);
+ T (&b[2][1] + 1);
+ T (&b[2][v0]);
+ T (&b[2][1] + v0);
+
+ T (&b[i2][i1]);
+ T (&b[i2][i1] + i1);
+ T (&b[i2][v0]);
+ T (&b[i2][i1] + v0);
+
+ T (&b[3][1]); /* { dg-warning "nul" } */
+ T (&b[3][1] + 1); /* { dg-warning "nul" } */
+ T (&b[3][v0]); /* { dg-warning "nul" } */
+ T (&b[3][1] + v0); /* { dg-warning "nul" } */
+ T (&b[3][v0] + v1); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+
+ T (&b[i3][i1]); /* { dg-warning "nul" } */
+ T (&b[i3][i1] + i1); /* { dg-warning "nul" } */
+ T (&b[i3][v0]); /* { dg-warning "nul" } */
+ T (&b[i3][i1] + v0); /* { dg-warning "nul" } */
+ T (&b[i3][v0] + v1); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+
+ T (v0 ? "" : b[0]);
+ T (v0 ? "" : b[1]);
+ T (v0 ? "" : b[2]);
+ T (v0 ? "" : b[3]); /* { dg-warning "nul" } */
+ T (v0 ? b[0] : "");
+ T (v0 ? b[1] : "");
+ T (v0 ? b[2] : "");
+ T (v0 ? b[3] : ""); /* { dg-warning "nul" } */
+
+ T (v0 ? "1234" : b[3]); /* { dg-warning "nul" } */
+ T (v0 ? b[3] : "1234"); /* { dg-warning "nul" } */
+
+ T (v0 ? a : b[3]); /* { dg-warning "nul" } */
+ T (v0 ? b[0] : b[2]);
+ T (v0 ? b[2] : b[3]); /* { dg-warning "nul" } */
+ T (v0 ? b[3] : b[2]); /* { dg-warning "nul" } */
+
+ T (v0 ? b[0] : &b[3][0] + 1); /* { dg-warning "nul" } */
+ T (v0 ? b[1] : &b[3][1] + v0); /* { dg-warning "nul" } */
+
+ /* It's possible to detect the missing nul in the following
+ expression but GCC doesn't do it yet. */
+ T (v0 ? &b[3][1] + v0 : b[2]); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+ T (v0 ? &b[3][v0] : &b[3][v1]); /* { dg-warning "nul" } */
+}
+
+struct A { char a[5], b[5]; };
+
+const struct A s = { "1234", "12345" };
+
+void test_struct_member (char *d)
+{
+ int i0 = 0;
+ int i1 = i0 + 1;
+
+ T (s.a);
+ T (&s.a[0]);
+ T (&s.a[0] + 1);
+ T (&s.a[0] + i0);
+ T (&s.a[1]);
+ T (&s.a[1] + 1);
+ T (&s.a[1] + i0);
+
+ T (&s.a[i0]);
+ T (&s.a[i0] + 1);
+ T (&s.a[i0] + v0);
+ T (&s.a[i1]);
+ T (&s.a[i1] + 1);
+ T (&s.a[i1] + v0);
+
+ T (s.a);
+ T (&s.a[0]);
+ T (&s.a[0] + 1);
+ T (&s.a[0] + v0);
+ T (&s.a[1]);
+ T (&s.a[1] + 1);
+ T (&s.a[1] + v0);
+
+ T (&s.a[i0]);
+ T (&s.a[i0] + 1);
+ T (&s.a[i0] + v0);
+ T (&s.a[i1]);
+ T (&s.a[i1] + 1);
+ T (&s.a[i1] + v0);
+
+ T (&s.a[v0]);
+ T (&s.a[v0] + 1);
+ T (&s.a[v0] + v0);
+ T (&s.a[v1]);
+ T (&s.a[v1] + 1);
+ T (&s.a[v1] + v0);
+
+ T (s.b); /* { dg-warning "nul" } */
+ T (&s.b[0]); /* { dg-warning "nul" } */
+ T (&s.b[0] + 1); /* { dg-warning "nul" } */
+ T (&s.b[0] + i0); /* { dg-warning "nul" } */
+ T (&s.b[1]); /* { dg-warning "nul" } */
+ T (&s.b[1] + 1); /* { dg-warning "nul" } */
+ T (&s.b[1] + i0); /* { dg-warning "nul" } */
+
+ T (s.b); /* { dg-warning "nul" } */
+ T (&s.b[0]); /* { dg-warning "nul" } */
+ T (&s.b[0] + 1); /* { dg-warning "nul" } */
+ T (&s.b[0] + v0); /* { dg-warning "nul" } */
+ T (&s.b[1]); /* { dg-warning "nul" } */
+ T (&s.b[1] + 1); /* { dg-warning "nul" } */
+ T (&s.b[1] + v0); /* { dg-warning "nul" } */
+
+ T (s.b); /* { dg-warning "nul" } */
+ T (&s.b[v0]); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+ T (&s.b[v0] + 1); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+ T (&s.b[v0] + v0); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+ T (&s.b[v1]); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+ T (&s.b[v1] + 1); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+ T (&s.b[v1] + v0); /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+}
+
+struct B { struct A a[2]; };
+
+const struct B ba[] = {
+ { { { "123", "12345" }, { "12345", "123" } } },
+ { { { "12345", "123" }, { "123", "12345" } } },
+ { { { "1", "12" }, { "123", "1234" } } },
+ { { { "123", "1234" }, { "12345", "12" } } }
+};
+
+void test_array_of_structs (char *d)
+{
+ T (ba[0].a[0].a);
+ T (&ba[0].a[0].a[0]);
+ T (&ba[0].a[0].a[0] + 1);
+ T (&ba[0].a[0].a[0] + v0);
+ T (&ba[0].a[0].a[1]);
+ T (&ba[0].a[0].a[1] + 1);
+ T (&ba[0].a[0].a[1] + v0);
+
+ T (ba[0].a[0].b); /* { dg-warning "nul" } */
+ T (&ba[0].a[0].b[0]); /* { dg-warning "nul" } */
+ T (&ba[0].a[0].b[0] + 1); /* { dg-warning "nul" } */
+ T (&ba[0].a[0].b[0] + v0); /* { dg-warning "nul" } */
+ T (&ba[0].a[0].b[1]); /* { dg-warning "nul" } */
+ T (&ba[0].a[0].b[1] + 1); /* { dg-warning "nul" } */
+ T (&ba[0].a[0].b[1] + v0); /* { dg-warning "nul" } */
+
+ T (ba[0].a[1].a); /* { dg-warning "nul" } */
+ T (&ba[0].a[1].a[0]); /* { dg-warning "nul" } */
+ T (&ba[0].a[1].a[0] + 1); /* { dg-warning "nul" } */
+ T (&ba[0].a[1].a[0] + v0); /* { dg-warning "nul" } */
+ T (&ba[0].a[1].a[1]); /* { dg-warning "nul" } */
+ T (&ba[0].a[1].a[1] + 1); /* { dg-warning "nul" } */
+ T (&ba[0].a[1].a[1] + v0); /* { dg-warning "nul" } */
+
+ T (ba[0].a[1].b);
+ T (&ba[0].a[1].b[0]);
+ T (&ba[0].a[1].b[0] + 1);
+ T (&ba[0].a[1].b[0] + v0);
+ T (&ba[0].a[1].b[1]);
+ T (&ba[0].a[1].b[1] + 1);
+ T (&ba[0].a[1].b[1] + v0);
+
+
+ T (ba[1].a[0].a); /* { dg-warning "nul" } */
+ T (&ba[1].a[0].a[0]); /* { dg-warning "nul" } */
+ T (&ba[1].a[0].a[0] + 1); /* { dg-warning "nul" } */
+ T (&ba[1].a[0].a[0] + v0); /* { dg-warning "nul" } */
+ T (&ba[1].a[0].a[1]); /* { dg-warning "nul" } */
+ T (&ba[1].a[0].a[1] + 1); /* { dg-warning "nul" } */
+ T (&ba[1].a[0].a[1] + v0); /* { dg-warning "nul" } */
+
+ T (ba[1].a[0].b);
+ T (&ba[1].a[0].b[0]);
+ T (&ba[1].a[0].b[0] + 1);
+ T (&ba[1].a[0].b[0] + v0);
+ T (&ba[1].a[0].b[1]);
+ T (&ba[1].a[0].b[1] + 1);
+ T (&ba[1].a[0].b[1] + v0);
+
+ T (ba[1].a[1].a);
+ T (&ba[1].a[1].a[0]);
+ T (&ba[1].a[1].a[0] + 1);
+ T (&ba[1].a[1].a[0] + v0);
+ T (&ba[1].a[1].a[1]);
+ T (&ba[1].a[1].a[1] + 1);
+ T (&ba[1].a[1].a[1] + v0);
+
+ T (ba[1].a[1].b); /* { dg-warning "nul" } */
+ T (&ba[1].a[1].b[0]); /* { dg-warning "nul" } */
+ T (&ba[1].a[1].b[0] + 1); /* { dg-warning "nul" } */
+ T (&ba[1].a[1].b[0] + v0); /* { dg-warning "nul" } */
+ T (&ba[1].a[1].b[1]); /* { dg-warning "nul" } */
+ T (&ba[1].a[1].b[1] + 1); /* { dg-warning "nul" } */
+ T (&ba[1].a[1].b[1] + v0); /* { dg-warning "nul" } */
+
+
+ T (ba[2].a[0].a);
+ T (&ba[2].a[0].a[0]);
+ T (&ba[2].a[0].a[0] + 1);
+ T (&ba[2].a[0].a[0] + v0);
+ T (&ba[2].a[0].a[1]);
+ T (&ba[2].a[0].a[1] + 1);
+ T (&ba[2].a[0].a[1] + v0);
+
+ T (ba[2].a[0].b);
+ T (&ba[2].a[0].b[0]);
+ T (&ba[2].a[0].b[0] + 1);
+ T (&ba[2].a[0].b[0] + v0);
+ T (&ba[2].a[0].b[1]);
+ T (&ba[2].a[0].b[1] + 1);
+ T (&ba[2].a[0].b[1] + v0);
+
+ T (ba[2].a[1].a);
+ T (&ba[2].a[1].a[0]);
+ T (&ba[2].a[1].a[0] + 1);
+ T (&ba[2].a[1].a[0] + v0);
+ T (&ba[2].a[1].a[1]);
+ T (&ba[2].a[1].a[1] + 1);
+ T (&ba[2].a[1].a[1] + v0);
+
+
+ T (ba[3].a[0].a);
+ T (&ba[3].a[0].a[0]);
+ T (&ba[3].a[0].a[0] + 1);
+ T (&ba[3].a[0].a[0] + v0);
+ T (&ba[3].a[0].a[1]);
+ T (&ba[3].a[0].a[1] + 1);
+ T (&ba[3].a[0].a[1] + v0);
+
+ T (ba[3].a[0].b);
+ T (&ba[3].a[0].b[0]);
+ T (&ba[3].a[0].b[0] + 1);
+ T (&ba[3].a[0].b[0] + v0);
+ T (&ba[3].a[0].b[1]);
+ T (&ba[3].a[0].b[1] + 1);
+ T (&ba[3].a[0].b[1] + v0);
+
+ T (ba[3].a[1].a); /* { dg-warning "nul" } */
+ T (&ba[3].a[1].a[0]); /* { dg-warning "nul" } */
+ T (&ba[3].a[1].a[0] + 1); /* { dg-warning "nul" } */
+ T (&ba[3].a[1].a[0] + v0); /* { dg-warning "nul" } */
+ T (&ba[3].a[1].a[1]); /* { dg-warning "nul" } */
+ T (&ba[3].a[1].a[1] + 1); /* { dg-warning "nul" } */
+ T (&ba[3].a[1].a[1] + v0); /* { dg-warning "nul" } */
+
+ T (ba[3].a[1].b);
+ T (&ba[3].a[1].b[0]);
+ T (&ba[3].a[1].b[0] + 1);
+ T (&ba[3].a[1].b[0] + v0);
+ T (&ba[3].a[1].b[1]);
+ T (&ba[3].a[1].b[1] + 1);
+ T (&ba[3].a[1].b[1] + v0);
+
+
+ T (v0 ? ba[0].a[0].a : ba[0].a[0].b); /* { dg-warning "nul" "bug ???" } */
+ T (v0 ? ba[0].a[0].a : ba[0].a[0].b); /* { dg-warning "nul" "bug ???" } */
+
+ T (v0 ? &ba[0].a[0].a[0] : &ba[3].a[1].a[0]); /* { dg-warning "nul" "bug ???" } */
+ T (v0 ? &ba[3].a[1].a[1] : ba[0].a[0].a); /* { dg-warning "nul" "bug ???" } */
+
+ T (v0 ? ba[0].a[0].a : ba[0].a[1].b);
+ T (v0 ? ba[0].a[1].b : ba[0].a[0].a);
+}
+
+/* { dg-prune-output " reading \[1-9\]\[0-9\]? bytes from a region " } */
diff --git a/gcc/testsuite/gcc.dg/warn-strlen-no-nul.c b/gcc/testsuite/gcc.dg/warn-strlen-no-nul.c
new file mode 100644
index 0000000..997dfc3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/warn-strlen-no-nul.c
@@ -0,0 +1,304 @@
+/* PR tree-optimization/86552 - missing warning for reading past the end
+ of non-string arrays
+ { dg-do compile }
+ { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */
+
+extern __SIZE_TYPE__ strlen (const char*);
+
+const char a[5] = "12345"; /* { dg-message "declared here" } */
+
+int v0 = 0;
+int v1 = 1;
+volatile int v2;
+
+void sink (int, ...);
+
+#define CONCAT(a, b) a ## b
+#define CAT(a, b) CONCAT(a, b)
+
+#define T(str) \
+ __attribute__ ((noipa)) \
+ void CAT (test_, __LINE__) (void) { \
+ int i0 = 0, i1 = i0 + 1, i2 = i1 + 1, i3 = i2 + 1; \
+ sink (strlen (str), i0, i1, i2, i3); \
+ } typedef void dummy_type
+
+T (a); /* { dg-warning "argument missing terminating nul" } */
+T (&a[0]); /* { dg-warning "nul" } */
+T (&a[0] + 1); /* { dg-warning "nul" } */
+T (&a[1]); /* { dg-warning "nul" } */
+T (&a[v0]); /* { dg-warning "nul" } */
+T (&a[v0] + 1); /* { dg-warning "nul" } */
+
+
+const char b[][5] = { /* { dg-message "declared here" } */
+ "12", "123", "1234", "54321"
+};
+
+T (b[0]);
+T (b[1]);
+T (b[2]);
+T (b[3]); /* { dg-warning "nul" } */
+
+T (b[i0]);
+T (b[i1]);
+T (b[i2]);
+T (b[i3]); /* { dg-warning "nul" } */
+
+T (b[v0]);
+
+T (&b[i2][i1]);
+T (&b[i2][i1] + i1);
+T (&b[i2][v0]);
+T (&b[i2][i1] + v0);
+
+T (&b[2][1]);
+T (&b[2][1] + i1);
+T (&b[2][i0]);
+T (&b[2][1] + i0);
+
+T (&b[2][1]);
+T (&b[2][1] + v0);
+T (&b[2][v0]);
+
+T (&b[3][1]); /* { dg-warning "nul" } */
+T (&b[3][1] + 1); /* { dg-warning "nul" } */
+T (&b[3][1] + i1); /* { dg-warning "nul" } */
+T (&b[3][v0]); /* { dg-warning "nul" } */
+T (&b[3][1] + v0); /* { dg-warning "nul" } */
+T (&b[3][v0] + v1); /* { dg-warning "nul" } */
+
+T (&b[i3][i1]); /* { dg-warning "nul" } */
+T (&b[i3][i1] + 1); /* { dg-warning "nul" } */
+T (&b[i3][i1] + i1); /* { dg-warning "nul" } */
+T (&b[i3][v0]); /* { dg-warning "nul" "pr86919" { xfail *-*-* } } */
+T (&b[i3][i1] + v0); /* { dg-warning "nul" "pr86919" { xfail *-*-* } } */
+T (&b[i3][v0] + v1); /* { dg-warning "nul" "pr86919" { xfail *-*-* } } */
+
+T (v0 ? "" : b[0]);
+T (v0 ? "" : b[1]);
+T (v0 ? "" : b[2]);
+T (v0 ? "" : b[3]); /* { dg-warning "nul" } */
+T (v0 ? b[0] : "");
+T (v0 ? b[1] : "");
+T (v0 ? b[2] : "");
+T (v0 ? b[3] : ""); /* { dg-warning "nul" } */
+
+T (v0 ? "" : b[i0]);
+T (v0 ? "" : b[i1]);
+T (v0 ? "" : b[i2]);
+/* The following is diagnosed but the warning location is wrong
+ (the PRE pass loses it). */
+T (v0 ? "" : b[i3]); /* { dg-warning "nul" } */
+T (v0 ? b[i0] : "");
+T (v0 ? b[i1] : "");
+T (v0 ? b[i2] : "");
+T (v0 ? b[i3] : ""); /* { dg-warning "nul" } */
+
+T (v0 ? "1234" : b[3]); /* { dg-warning "nul" } */
+T (v0 ? "1234" : b[i3]); /* { dg-warning "nul" } */
+T (v0 ? b[3] : "1234"); /* { dg-warning "nul" } */
+T (v0 ? b[i3] : "1234"); /* { dg-warning "nul" } */
+
+T (v0 ? a : b[3]); /* { dg-warning "nul" } */
+T (v0 ? b[0] : b[2]);
+T (v0 ? b[2] : b[3]); /* { dg-warning "nul" } */
+T (v0 ? b[3] : b[2]); /* { dg-warning "nul" } */
+
+T (v0 ? a : b[i3]); /* { dg-warning "nul" } */
+T (v0 ? b[i0] : b[i2]);
+T (v0 ? b[i2] : b[i3]); /* { dg-warning "nul" } */
+T (v0 ? b[i3] : b[i2]); /* { dg-warning "nul" } */
+
+T (v0 ? b[0] : &b[3][0] + 1); /* { dg-warning "nul" } */
+T (v0 ? b[0] : &b[3][0] + i1); /* { dg-warning "nul" } */
+T (v0 ? b[1] : &b[3][1] + v0); /* { dg-warning "nul" } */
+
+T (v0 ? b[i0] : &b[i3][i0] + i1); /* { dg-warning "nul" } */
+T (v0 ? b[i0] : &b[i3][i0] + i1); /* { dg-warning "nul" } */
+T (v0 ? b[i1] : &b[i3][i1] + v0); /* { dg-warning "nul" } */
+
+T (v0 ? &b[3][1] + v0 : b[2]); /* { dg-warning "nul" } */
+T (v0 ? &b[3][v0] : &b[3][v1]); /* { dg-warning "nul" } */
+
+
+struct A { char a[5], b[5]; };
+
+const struct A s = { "1234", "12345" };
+
+T (s.a);
+T (&s.a[0]);
+T (&s.a[0] + 1);
+T (&s.a[0] + v0);
+T (&s.a[1]);
+T (&s.a[1] + 1);
+T (&s.a[1] + v0);
+
+T (&s.a[i0]);
+T (&s.a[i0] + i1);
+T (&s.a[i0] + v0);
+T (&s.a[i1]);
+T (&s.a[i1] + i1);
+T (&s.a[i1] + v0);
+
+T (s.b); /* { dg-warning "nul" } */
+T (&s.b[0]); /* { dg-warning "nul" } */
+T (&s.b[0] + 1); /* { dg-warning "nul" } */
+T (&s.b[0] + v0); /* { dg-warning "nul" } */
+T (&s.b[1]); /* { dg-warning "nul" } */
+T (&s.b[1] + 1); /* { dg-warning "nul" } */
+T (&s.b[1] + i0); /* { dg-warning "nul" } */
+T (&s.b[1] + v0); /* { dg-warning "nul" } */
+
+T (&s.b[i0]); /* { dg-warning "nul" } */
+T (&s.b[i0] + i1); /* { dg-warning "nul" } */
+T (&s.b[i0] + v0); /* { dg-warning "nul" "pr86919" { xfail *-*-* } } */
+T (&s.b[i1]); /* { dg-warning "nul" } */
+T (&s.b[i1] + i1); /* { dg-warning "nul" } */
+T (&s.b[i1] + v0); /* { dg-warning "nul" "pr86919" { xfail *-*-* } } */
+
+struct B { struct A a[2]; };
+
+const struct B ba[] = {
+ { { { "123", "12345" }, { "12345", "123" } } },
+ { { { "12345", "123" }, { "123", "12345" } } },
+ { { { "1", "12" }, { "123", "1234" } } },
+ { { { "123", "1234" }, { "12345", "12" } } }
+};
+
+T (ba[0].a[0].a);
+T (&ba[0].a[0].a[0]);
+T (&ba[0].a[0].a[0] + 1);
+T (&ba[0].a[0].a[0] + v0);
+T (&ba[0].a[0].a[1]);
+T (&ba[0].a[0].a[1] + 1);
+T (&ba[0].a[0].a[1] + v0);
+
+T (ba[0].a[0].b); /* { dg-warning "nul" } */
+T (&ba[0].a[0].b[0]); /* { dg-warning "nul" } */
+T (&ba[0].a[0].b[0] + 1); /* { dg-warning "nul" } */
+T (&ba[0].a[0].b[0] + v0); /* { dg-warning "nul" } */
+T (&ba[0].a[0].b[1]); /* { dg-warning "nul" } */
+T (&ba[0].a[0].b[1] + 1); /* { dg-warning "nul" } */
+T (&ba[0].a[0].b[1] + v0); /* { dg-warning "nul" } */
+
+T (ba[0].a[1].a); /* { dg-warning "nul" } */
+T (&ba[0].a[1].a[0]); /* { dg-warning "nul" } */
+T (&ba[0].a[1].a[0] + 1); /* { dg-warning "nul" } */
+T (&ba[0].a[1].a[0] + v0); /* { dg-warning "nul" } */
+T (&ba[0].a[1].a[1]); /* { dg-warning "nul" } */
+T (&ba[0].a[1].a[1] + 1); /* { dg-warning "nul" } */
+T (&ba[0].a[1].a[1] + v0); /* { dg-warning "nul" } */
+
+T (ba[0].a[1].b);
+T (&ba[0].a[1].b[0]);
+T (&ba[0].a[1].b[0] + 1);
+T (&ba[0].a[1].b[0] + v0);
+T (&ba[0].a[1].b[1]);
+T (&ba[0].a[1].b[1] + 1);
+T (&ba[0].a[1].b[1] + v0);
+
+
+T (ba[1].a[0].a); /* { dg-warning "nul" } */
+T (&ba[1].a[0].a[0]); /* { dg-warning "nul" } */
+T (&ba[1].a[0].a[0] + 1); /* { dg-warning "nul" } */
+T (&ba[1].a[0].a[0] + v0); /* { dg-warning "nul" } */
+T (&ba[1].a[0].a[1]); /* { dg-warning "nul" } */
+T (&ba[1].a[0].a[1] + 1); /* { dg-warning "nul" } */
+T (&ba[1].a[0].a[1] + v0); /* { dg-warning "nul" } */
+
+T (ba[1].a[0].b);
+T (&ba[1].a[0].b[0]);
+T (&ba[1].a[0].b[0] + 1);
+T (&ba[1].a[0].b[0] + v0);
+T (&ba[1].a[0].b[1]);
+T (&ba[1].a[0].b[1] + 1);
+T (&ba[1].a[0].b[1] + v0);
+
+T (ba[1].a[1].a);
+T (&ba[1].a[1].a[0]);
+T (&ba[1].a[1].a[0] + 1);
+T (&ba[1].a[1].a[0] + v0);
+T (&ba[1].a[1].a[1]);
+T (&ba[1].a[1].a[1] + 1);
+T (&ba[1].a[1].a[1] + v0);
+
+T (ba[1].a[1].b); /* { dg-warning "nul" } */
+T (&ba[1].a[1].b[0]); /* { dg-warning "nul" } */
+T (&ba[1].a[1].b[0] + 1); /* { dg-warning "nul" } */
+T (&ba[1].a[1].b[0] + v0); /* { dg-warning "nul" } */
+T (&ba[1].a[1].b[1]); /* { dg-warning "nul" } */
+T (&ba[1].a[1].b[1] + 1); /* { dg-warning "nul" } */
+T (&ba[1].a[1].b[1] + v0); /* { dg-warning "nul" } */
+
+
+T (ba[2].a[0].a);
+T (&ba[2].a[0].a[0]);
+T (&ba[2].a[0].a[0] + 1);
+T (&ba[2].a[0].a[0] + v0);
+T (&ba[2].a[0].a[1]);
+T (&ba[2].a[0].a[1] + 1);
+T (&ba[2].a[0].a[1] + v0);
+
+T (ba[2].a[0].b);
+T (&ba[2].a[0].b[0]);
+T (&ba[2].a[0].b[0] + 1);
+T (&ba[2].a[0].b[0] + v0);
+T (&ba[2].a[0].b[1]);
+T (&ba[2].a[0].b[1] + 1);
+T (&ba[2].a[0].b[1] + v0);
+
+T (ba[2].a[1].a);
+T (&ba[2].a[1].a[0]);
+T (&ba[2].a[1].a[0] + 1);
+T (&ba[2].a[1].a[0] + v0);
+T (&ba[2].a[1].a[1]);
+T (&ba[2].a[1].a[1] + 1);
+T (&ba[2].a[1].a[1] + v0);
+
+
+T (ba[3].a[0].a);
+T (&ba[3].a[0].a[0]);
+T (&ba[3].a[0].a[0] + 1);
+T (&ba[3].a[0].a[0] + v0);
+T (&ba[3].a[0].a[1]);
+T (&ba[3].a[0].a[1] + 1);
+T (&ba[3].a[0].a[1] + v0);
+
+T (ba[3].a[0].b);
+T (&ba[3].a[0].b[0]);
+T (&ba[3].a[0].b[0] + 1);
+T (&ba[3].a[0].b[0] + v0);
+T (&ba[3].a[0].b[1]);
+T (&ba[3].a[0].b[1] + 1);
+T (&ba[3].a[0].b[1] + v0);
+
+T (ba[3].a[1].a); /* { dg-warning "nul" } */
+T (&ba[3].a[1].a[0]); /* { dg-warning "nul" } */
+T (&ba[3].a[1].a[0] + 1); /* { dg-warning "nul" } */
+T (&ba[3].a[1].a[0] + v0); /* { dg-warning "nul" } */
+T (&ba[3].a[1].a[1]); /* { dg-warning "nul" } */
+T (&ba[3].a[1].a[1] + 1); /* { dg-warning "nul" } */
+T (&ba[3].a[1].a[1] + v0); /* { dg-warning "nul" } */
+
+T (ba[3].a[1].b);
+T (&ba[3].a[1].b[0]);
+T (&ba[3].a[1].b[0] + 1);
+T (&ba[3].a[1].b[0] + v0);
+T (&ba[3].a[1].b[1]);
+T (&ba[3].a[1].b[1] + 1);
+T (&ba[3].a[1].b[1] + v0);
+
+
+T (v0 ? ba[0].a[0].a : ba[0].a[0].b); /* { dg-warning "nul" } */
+T (v0 ? ba[0].a[0].a : ba[0].a[0].b); /* { dg-warning "nul" } */
+
+T (v0 ? &ba[0].a[0].a[0] : &ba[3].a[1].a[0]); /* { dg-warning "nul" } */
+T (v0 ? &ba[3].a[1].a[1] : ba[0].a[0].a); /* { dg-warning "nul" } */
+
+T (v0 ? ba[0].a[0].a : ba[0].a[1].b);
+T (v0 ? ba[0].a[1].b : ba[0].a[0].a);
+
+T (v2 ? b[1] : &b[3][1] + v2); /* { dg-warning "nul" } */
+T (v2 ? &b[3][1] + v2 : b[2]); /* { dg-warning "nul" } */
+T (v2 ? &b[3][v2] : &b[2][v2]); /* { dg-warning "nul" } */
diff --git a/gcc/testsuite/gcc.dg/wmain.c b/gcc/testsuite/gcc.dg/wmain.c
new file mode 100644
index 0000000..06fc26f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/wmain.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+int main; /* { dg-warning "'main' is usually a function" } */
+
+int foo()
+{
+ int main = 1; /* { dg-bogus "'main' is usually a function" } */
+ return main;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-store.c b/gcc/testsuite/gcc.target/aarch64/atomic-store.c
new file mode 100644
index 0000000..8cabc05
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/atomic-store.c
@@ -0,0 +1,75 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8.4-a -O2" } */
+
+#include <stdatomic.h>
+
+typedef __INT8_TYPE__ int8_t;
+typedef __INT16_TYPE__ int16_t;
+typedef __INT32_TYPE__ int32_t;
+typedef __INT64_TYPE__ int64_t;
+
+#define STORE_TESTS(size) \
+ void \
+ foo##size (int##size##_t *atomic_vals) \
+{ \
+ atomic_store_explicit (atomic_vals, 2, memory_order_relaxed); \
+ atomic_store_explicit (atomic_vals, 2, memory_order_release); \
+ atomic_store_explicit ((atomic_vals + 1), 2, memory_order_release); \
+ atomic_store ((atomic_vals + 2), 2); \
+ atomic_store_explicit ((atomic_vals + 3), 2, memory_order_relaxed); \
+}
+
+STORE_TESTS (8);
+/* { dg-final { scan-assembler-times "strb\tw\[0-9\]+, \\\[x\[0-9\]+\\\]" 1 } } */
+/* { dg-final { scan-assembler-times "stlrb\tw\[0-9\]+, \\\[x\[0-9\]+\\\]" 1 { target { ! ilp32 } } } } */
+/* { dg-final { scan-assembler-times "stlrb\tw\[0-9\]+, \\\[x\[0-9\]+\\\]" 2 { target { ilp32 } } } } */
+/* { dg-final { scan-assembler-times "stlurb\tw\[0-9\]+, \\\[x\[0-9\]+, 1\\\]" 1 } } */
+/* { dg-final { scan-assembler-times "stlurb\tw\[0-9\]+, \\\[x\[0-9\]+, 2\\\]" 1 } } */
+/* { dg-final { scan-assembler-times "strb\tw\[0-9\]+, \\\[x\[0-9\]+, 3\\\]" 1 } } */
+
+STORE_TESTS (16);
+/* { dg-final { scan-assembler-times "strh\tw\[0-9\]+, \\\[x\[0-9\]+\\\]" 1 } } */
+/* { dg-final { scan-assembler-times "stlrh\tw\[0-9\]+, \\\[x\[0-9\]+\\\]" 1 } } */
+/* { dg-final { scan-assembler-times "stlurh\tw\[0-9\]+, \\\[x\[0-9\]+, 2\\\]" 1 } } */
+/* { dg-final { scan-assembler-times "stlurh\tw\[0-9\]+, \\\[x\[0-9\]+, 4\\\]" 1 } } */
+/* { dg-final { scan-assembler-times "strh\tw\[0-9\]+, \\\[x\[0-9\]+, 6\\\]" 1 } } */
+
+STORE_TESTS (32);
+/* { dg-final { scan-assembler-times "str\tw\[0-9\]+, \\\[x\[0-9\]+\\\]" 1 } } */
+/* { dg-final { scan-assembler-times "stlr\tw\[0-9\]+, \\\[x\[0-9\]+\\\]" 1 } } */
+/* { dg-final { scan-assembler-times "stlur\tw\[0-9\]+, \\\[x\[0-9\]+, 4\\\]" 1 } } */
+/* { dg-final { scan-assembler-times "stlur\tw\[0-9\]+, \\\[x\[0-9\]+, 8\\\]" 1 } } */
+/* { dg-final { scan-assembler-times "str\tw\[0-9\]+, \\\[x\[0-9\]+, 12\\\]" 1 } } */
+
+STORE_TESTS (64);
+/* { dg-final { scan-assembler-times "str\tx\[0-9\]+, \\\[x\[0-9\]+\\\]" 1 } } */
+/* { dg-final { scan-assembler-times "stlur\tx\[0-9\]+, \\\[x\[0-9\]+, 8\\\]" 1 } } */
+/* { dg-final { scan-assembler-times "stlur\tx\[0-9\]+, \\\[x\[0-9\]+, 16\\\]" 1 } } */
+/* { dg-final { scan-assembler-times "str\tx\[0-9\]+, \\\[x\[0-9\]+, 24\\\]" 1 } } */
+
+void
+foo_toolarge_offset (int64_t *atomic_vals)
+{
+ /* 9bit signed unscaled immediate =>
+ largest representable value +255.
+ smallest representable value -256. */
+ atomic_store_explicit (atomic_vals + 32, 2, memory_order_release);
+ atomic_store_explicit (atomic_vals - 33, 2, memory_order_release);
+}
+
+void
+foo_negative (int8_t *atomic_vals)
+{
+ atomic_store_explicit (atomic_vals - 2, 2, memory_order_release);
+}
+/* { dg-final { scan-assembler-times "stlurb\tw\[0-9\]+, \\\[x\[0-9\]+, -2\\\]" 1 { target { ! ilp32 } } } } */
+
+#pragma GCC target ("arch=armv8.3-a")
+void
+foo_older_arch (int64_t *atomic_vals)
+{
+ atomic_store_explicit (atomic_vals + 2, 2, memory_order_release);
+}
+
+/* Three times, one for each of the three above functions. */
+/* { dg-final { scan-assembler-times "stlr\tx\[0-9\]+, \\\[x\[0-9\]+\\\]" 4 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/combine_bfi_1.c b/gcc/testsuite/gcc.target/aarch64/combine_bfi_1.c
index 9cc3bdb..cee42cc 100644
--- a/gcc/testsuite/gcc.target/aarch64/combine_bfi_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/combine_bfi_1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-rtl-combine" } */
+/* { dg-options "-O2" } */
int
f1 (int x, int y)
@@ -31,4 +31,4 @@ f5 (long long x, long long y)
return (x & ~0xffffffffull) | (y & 0xffffffff);
}
-/* { dg-final { scan-rtl-dump-times "\\*aarch64_bfi" 5 "combine" } } */
+/* { dg-final { scan-assembler-times {\tbfi\t} 5 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/combine_bfxil.c b/gcc/testsuite/gcc.target/aarch64/combine_bfxil.c
new file mode 100644
index 0000000..84e5377
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/combine_bfxil.c
@@ -0,0 +1,117 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+
+extern void abort (void);
+
+unsigned long long
+combine_zero_extended_int (unsigned int a, unsigned int b)
+{
+ /* { dg-final { scan-assembler-not "uxtw\\t" } } */
+ return (a & 0xffff0000ll) | (b & 0x0000ffffll);
+}
+
+unsigned long long
+combine_balanced (unsigned long long a, unsigned long long b)
+{
+ return (a & 0xffffffff00000000ll) | (b & 0x00000000ffffffffll);
+}
+
+unsigned long long
+combine_minimal (unsigned long long a, unsigned long long b)
+{
+ return (a & 0xfffffffffffffffell) | (b & 0x0000000000000001ll);
+}
+
+unsigned long long
+combine_unbalanced (unsigned long long a, unsigned long long b)
+{
+ return (a & 0xffffffffff000000ll) | (b & 0x0000000000ffffffll);
+}
+
+unsigned int
+combine_balanced_int (unsigned int a, unsigned int b)
+{
+ return (a & 0xffff0000ll) | (b & 0x0000ffffll);
+}
+
+unsigned int
+combine_unbalanced_int (unsigned int a, unsigned int b)
+{
+ return (a & 0xffffff00ll) | (b & 0x000000ffll);
+}
+
+unsigned long long c, d;
+
+__attribute__ ((noinline)) void
+foo (unsigned long long a, unsigned long long b)
+{
+ c = combine_minimal (a, b);
+ d = combine_minimal (b, a);
+}
+
+__attribute__ ((noinline)) void
+foo2 (unsigned long long a, unsigned long long b)
+{
+ c = combine_balanced (a, b);
+ d = combine_balanced (b, a);
+}
+
+__attribute__ ((noinline)) void
+foo3 (unsigned long long a, unsigned long long b)
+{
+ c = combine_unbalanced (a, b);
+ d = combine_unbalanced (b, a);
+}
+
+unsigned int ic, id;
+
+void
+foo4 (unsigned int a, unsigned int b)
+{
+ ic = combine_balanced_int (a, b);
+ id = combine_balanced_int (b, a);
+}
+
+void
+foo5 (unsigned int a, unsigned int b)
+{
+ ic = combine_unbalanced_int (a, b);
+ id = combine_unbalanced_int (b, a);
+}
+
+void
+foo6 (unsigned int a, unsigned int b)
+{
+ c = combine_zero_extended_int(a, b);
+ d = combine_zero_extended_int(b, a);
+}
+
+int
+main (void)
+{
+ unsigned long long a = 0x0123456789ABCDEF, b = 0xFEDCBA9876543210;
+ foo3 (a, b);
+ if (c != 0x0123456789543210) abort ();
+ if (d != 0xfedcba9876abcdef) abort ();
+ foo2 (a, b);
+ if (c != 0x0123456776543210) abort ();
+ if (d != 0xfedcba9889abcdef) abort ();
+ foo (a, b);
+ if (c != 0x0123456789abcdee) abort ();
+ if (d != 0xfedcba9876543211) abort ();
+
+ unsigned int a2 = 0x01234567, b2 = 0xFEDCBA98;
+ foo4 (a2, b2);
+ if (ic != 0x0123ba98) abort ();
+ if (id != 0xfedc4567) abort ();
+ foo5 (a2, b2);
+ if (ic != 0x01234598) abort ();
+ if (id != 0xfedcba67) abort ();
+
+ foo6 (a2, b2);
+ if (c != 0x0123ba98) abort ();
+ if (d != 0xfedc4567) abort ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "bfxil\\t" 13 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/combine_bfxil_2.c b/gcc/testsuite/gcc.target/aarch64/combine_bfxil_2.c
new file mode 100644
index 0000000..0fc1404
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/combine_bfxil_2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned long long
+combine_non_consecutive (unsigned long long a, unsigned long long b)
+{
+ return (a & 0xfffffff200f00000ll) | (b & 0x00001000ffffffffll);
+}
+
+void
+foo4 (unsigned long long a, unsigned long long b, unsigned long long *c,
+ unsigned long long *d) {
+ /* { dg-final { scan-assembler-not "bfxil\\t" } } */
+ *c = combine_non_consecutive (a, b);
+ *d = combine_non_consecutive (b, a);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/extract_zero_extend.c b/gcc/testsuite/gcc.target/aarch64/extract_zero_extend.c
new file mode 100644
index 0000000..0209305
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/extract_zero_extend.c
@@ -0,0 +1,81 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-rtl-final" } */
+
+/* Tests div16qi. */
+typedef unsigned char div16qi __attribute__ ((vector_size (16)));
+/* Tests div8qi. */
+typedef unsigned char div8qi __attribute__ ((vector_size (8)));
+/* Tests div8hi. */
+typedef unsigned short div8hi __attribute__ ((vector_size (16)));
+/* Tests div4hi. */
+typedef unsigned short div4hi __attribute__ ((vector_size (8)));
+
+/* Tests siv16qi. */
+typedef unsigned char siv16qi __attribute__ ((vector_size (16)));
+/* Tests siv8qi. */
+typedef unsigned char siv8qi __attribute__ ((vector_size (8)));
+/* Tests siv8hi. */
+typedef unsigned short siv8hi __attribute__ ((vector_size (16)));
+/* Tests siv4hi. */
+typedef unsigned short siv4hi __attribute__ ((vector_size (8)));
+
+
+unsigned long long
+foo_div16qi (div16qi a)
+{
+ return a[0];
+}
+
+unsigned long long
+foo_div8qi (div8qi a)
+{
+ return a[0];
+}
+
+unsigned long long
+foo_div8hi (div8hi a)
+{
+ return a[0];
+}
+
+unsigned long long
+foo_div4hi (div4hi a)
+{
+ return a[0];
+}
+
+unsigned int
+foo_siv16qi (siv16qi a)
+{
+ return a[0];
+}
+
+unsigned int
+foo_siv8qi (siv8qi a)
+{
+ return a[0];
+}
+
+unsigned int
+foo_siv8hi (siv8hi a)
+{
+ return a[0];
+}
+
+unsigned int
+foo_siv4hi (siv4hi a)
+{
+ return a[0];
+}
+
+/* { dg-final { scan-assembler-times "umov\\t" 8 } } */
+/* { dg-final { scan-assembler-not "and\\t" } } */
+
+/* { dg-final { scan-rtl-dump "aarch64_get_lane_zero_extenddiv16qi" "final" } } */
+/* { dg-final { scan-rtl-dump "aarch64_get_lane_zero_extenddiv8qi" "final" } } */
+/* { dg-final { scan-rtl-dump "aarch64_get_lane_zero_extenddiv8hi" "final" } } */
+/* { dg-final { scan-rtl-dump "aarch64_get_lane_zero_extenddiv4hi" "final" } } */
+/* { dg-final { scan-rtl-dump "aarch64_get_lane_zero_extendsiv16qi" "final" } } */
+/* { dg-final { scan-rtl-dump "aarch64_get_lane_zero_extendsiv8qi" "final" } } */
+/* { dg-final { scan-rtl-dump "aarch64_get_lane_zero_extendsiv8hi" "final" } } */
+/* { dg-final { scan-rtl-dump "aarch64_get_lane_zero_extendsiv4hi" "final" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_1.c b/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_1.c
index 3d22d22..4411ecf 100644
--- a/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_1.c
@@ -44,6 +44,6 @@ __fp16 f5 ()
return a;
}
-/* { dg-final { scan-assembler-times "mov\tw\[0-9\]+, #?19520" 3 } } */
-/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.4h, 0xbc, lsl 8" 1 } } */
-/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.4h, 0x4c, lsl 8" 1 } } */
+/* { dg-final { scan-assembler-times {fmov\th[0-9]+, #?1\.7e\+1} 3 } } */
+/* { dg-final { scan-assembler-times {fmov\th[0-9]+, #?-1\.0e\+0} 1 } } */
+/* { dg-final { scan-assembler-times {fmov\th[0-9]+, #?1\.6e\+1} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_2.c b/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_2.c
index 81ebd58..53c4324 100644
--- a/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_2.c
+++ b/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_2.c
@@ -40,6 +40,4 @@ float16_t f3(void)
/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.4h, 0x5c, lsl 8" 1 } } */
/* { dg-final { scan-assembler-times "movi\tv\[0-9\]+\\\.4h, 0x7c, lsl 8" 1 } } */
-/* { dg-final { scan-assembler-times "mov\tw\[0-9\]+, 19520" 1 } } */
-/* { dg-final { scan-assembler-times "fmov\th\[0-9\], w\[0-9\]+" 1 } } */
-
+/* { dg-final { scan-assembler-times {fmov\th[0-9]+, #?1.7e\+1} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_3.c b/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_3.c
index 66218e3..63d950a 100644
--- a/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_3.c
+++ b/gcc/testsuite/gcc.target/aarch64/f16_mov_immediate_3.c
@@ -1,6 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
+#pragma GCC target "+nofp16"
+
__fp16 f4 ()
{
__fp16 a = 0.1;
diff --git a/gcc/testsuite/gcc.target/aarch64/frecpe_1.c b/gcc/testsuite/gcc.target/aarch64/frecpe_1.c
new file mode 100644
index 0000000..e79f80d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/frecpe_1.c
@@ -0,0 +1,18 @@
+/* { dg-options "-Ofast -mlow-precision-div" } */
+/* { dg-do compile } */
+
+float
+f1 (float x)
+{
+ return 1 / x;
+}
+
+/* { dg-final { scan-assembler {\tfrecpe\t(s[0-9]+), s0\n\tfrecps\t(s[0-9]+), \1, s0\n\tfmul\ts0, \1, \2\n} } } */
+
+double
+f2 (double x)
+{
+ return 1 / x;
+}
+
+/* { dg-final { scan-assembler {\tfrecpe\t(d[0-9]+), d0\n\tfrecps\t(d[0-9]+), \1, d0\n\tfmul\t\1, \1, \2\n\tfrecps\t\2, \1, d0\n\tfmul\td0, \1, \2\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/frecpe_2.c b/gcc/testsuite/gcc.target/aarch64/frecpe_2.c
new file mode 100644
index 0000000..233817c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/frecpe_2.c
@@ -0,0 +1,18 @@
+/* { dg-options "-Ofast -mlow-precision-div" } */
+/* { dg-do compile } */
+
+float
+f1 (float x, float y)
+{
+ return y / x;
+}
+
+/* { dg-final { scan-assembler {\tfrecpe\t(s[0-9]+), s0\n\tfrecps\t(s[0-9]+), \1, s0\n\tfmul\t\1, \1, s1\n\tfmul\ts0, \1, \2\n} } } */
+
+double
+f2 (double x, double y)
+{
+ return y / x;
+}
+
+/* { dg-final { scan-assembler {\tfrecpe\t(d[0-9]+), d0\n\tfrecps\t(d[0-9]+), \1, d0\n\tfmul\t\1, \1, \2\n\tfrecps\t\2, \1, d0\n\tfmul\t\1, \1, d1\n\tfmul\td0, \1, \2\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/imm_choice_comparison.c b/gcc/testsuite/gcc.target/aarch64/imm_choice_comparison.c
new file mode 100644
index 0000000..ebc44d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/imm_choice_comparison.c
@@ -0,0 +1,54 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* Go from four moves to two. */
+
+int
+foo (long long x)
+{
+ return x <= 0x1999999999999998;
+}
+
+int
+GT (unsigned int x)
+{
+ return x > 0xfefffffe;
+}
+
+int
+LE (unsigned int x)
+{
+ return x <= 0xfefffffe;
+}
+
+int
+GE (long long x)
+{
+ return x >= 0xff000000;
+}
+
+int
+LT (int x)
+{
+ return x < 0xff000000;
+}
+
+/* Optimize the immediate in conditionals. */
+
+int
+check (int x, int y)
+{
+ if (x > y && GT (x))
+ return 100;
+
+ return x;
+}
+
+int
+tern (int x)
+{
+ return x >= 0xff000000 ? 5 : -3;
+}
+
+/* baz produces one movk instruction. */
+/* { dg-final { scan-assembler-times "movk" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/large_struct_copy.c b/gcc/testsuite/gcc.target/aarch64/large_struct_copy.c
new file mode 100644
index 0000000..2b5e780
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/large_struct_copy.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef unsigned __attribute__((mode(DI))) uint64_t;
+
+struct S0 {
+ uint64_t f1;
+ uint64_t f2;
+ uint64_t f3;
+ uint64_t f4;
+ uint64_t f5;
+} a;
+struct S2 {
+ uint64_t f0;
+ uint64_t f2;
+ struct S0 f3;
+};
+
+void fn1 () {
+ struct S2 b = {0, 1, 7, 4073709551611, 4, 8, 7};
+ a = b.f3;
+}
+
diff --git a/gcc/testsuite/gcc.target/aarch64/large_struct_copy_2.c b/gcc/testsuite/gcc.target/aarch64/large_struct_copy_2.c
new file mode 100644
index 0000000..5654342
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/large_struct_copy_2.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef unsigned __attribute__((mode(DI))) uint64_t;
+
+struct S0 {
+ uint64_t f1;
+ uint64_t f2;
+ uint64_t f3;
+ uint64_t f4;
+ uint64_t f5;
+} a;
+struct S2 {
+ uint64_t f0;
+ uint64_t f2;
+ struct S0 f3;
+};
+
+void fn1 () {
+ struct S2 b = {0, 1, 7, 4073709551611, 4, 8, 7};
+ a = b.f3;
+}
+
+/* { dg-final { scan-assembler-times {ldp\s+x[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {stp\s+x[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-not {ld[1-3]} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_13.c b/gcc/testsuite/gcc.target/aarch64/ldp_stp_13.c
new file mode 100644
index 0000000..9cc3942
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_13.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mabi=ilp32" } */
+
+long long
+load_long (long long int *arr)
+{
+ return arr[400] << 1 + arr[401] << 1 + arr[403] << 1 + arr[404] << 1;
+}
+
+/* { dg-final { scan-assembler-times "ldp\tx\[0-9\]+, x\[0-9\]+, " 2 } } */
+
+int
+load (int *arr)
+{
+ return arr[527] << 1 + arr[400] << 1 + arr[401] << 1 + arr[528] << 1;
+}
+
+/* { dg-final { scan-assembler-times "ldp\tw\[0-9\]+, w\[0-9\]+, " 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c b/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c
index ea29066..d943989 100644
--- a/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c
+++ b/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c
@@ -627,6 +627,14 @@ test_vqabss_s32 (int32_t a)
return vqabss_s32 (a);
}
+/* { dg-final { scan-assembler-times "\\tneg\\tx\[0-9\]+" 1 } } */
+
+int64_t
+test_vnegd_s64 (int64_t a)
+{
+ return vnegd_s64 (a);
+}
+
/* { dg-final { scan-assembler-times "\\tsqneg\\tb\[0-9\]+" 1 } } */
int8_t
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/vect_su_add_sub.c b/gcc/testsuite/gcc.target/aarch64/simd/vect_su_add_sub.c
index 338da54..921c5f1 100644
--- a/gcc/testsuite/gcc.target/aarch64/simd/vect_su_add_sub.c
+++ b/gcc/testsuite/gcc.target/aarch64/simd/vect_su_add_sub.c
@@ -1,21 +1,27 @@
/* { dg-do compile } */
/* { dg-options "-O3" } */
+typedef int __attribute__ ((mode (SI))) int32_t;
+typedef int __attribute__ ((mode (DI))) int64_t;
+typedef unsigned __attribute__ ((mode (SI))) size_t;
+typedef unsigned __attribute__ ((mode (SI))) uint32_t;
+typedef unsigned __attribute__ ((mode (DI))) uint64_t;
+
/* Ensure we use the signed/unsigned extend vectorized add and sub
instructions. */
#define N 1024
-int a[N];
-long c[N];
-long d[N];
-unsigned int ua[N];
-unsigned long uc[N];
-unsigned long ud[N];
+int32_t a[N];
+int64_t c[N];
+int64_t d[N];
+uint32_t ua[N];
+uint64_t uc[N];
+uint64_t ud[N];
void
add ()
{
- for (int i = 0; i < N; i++)
+ for (size_t i = 0; i < N; i++)
d[i] = a[i] + c[i];
}
/* { dg-final { scan-assembler-times "\[ \t\]saddw2\[ \t\]+" 1 } } */
@@ -24,7 +30,7 @@ add ()
void
subtract ()
{
- for (int i = 0; i < N; i++)
+ for (size_t i = 0; i < N; i++)
d[i] = c[i] - a[i];
}
/* { dg-final { scan-assembler-times "\[ \t\]ssubw2\[ \t\]+" 1 } } */
@@ -33,7 +39,7 @@ subtract ()
void
uadd ()
{
- for (int i = 0; i < N; i++)
+ for (size_t i = 0; i < N; i++)
ud[i] = ua[i] + uc[i];
}
/* { dg-final { scan-assembler-times "\[ \t\]uaddw2\[ \t\]+" 1 } } */
@@ -42,7 +48,7 @@ uadd ()
void
usubtract ()
{
- for (int i = 0; i < N; i++)
+ for (size_t i = 0; i < N; i++)
ud[i] = uc[i] - ua[i];
}
/* { dg-final { scan-assembler-times "\[ \t\]usubw2\[ \t\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/spellcheck_1.c b/gcc/testsuite/gcc.target/aarch64/spellcheck_1.c
index f57e0c5..a0795c1c 100644
--- a/gcc/testsuite/gcc.target/aarch64/spellcheck_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/spellcheck_1.c
@@ -3,7 +3,7 @@
__attribute__((target ("arch=armv8-a-typo"))) void
foo ()
{
- /* { dg-message "valid arguments are: \[^\n\r]*; did you mean 'armv8-a'?" "" { target *-*-* } .-1 } */
+ /* { dg-message "valid arguments are: \[^\n\r]*(; did you mean 'armv*'?)?" "" { target *-*-* } .-1 } */
/* { dg-error "invalid name \\(\"armv8-a-typo\"\\) in 'target\\(\"arch=\"\\)' pragma or attribute" "" { target *-*-* } .-2 } */
/* { dg-error "pragma or attribute 'target\\(\"arch=armv8-a-typo\"\\)' is not valid" "" { target *-*-* } .-3 } */
}
diff --git a/gcc/testsuite/gcc.target/aarch64/spellcheck_4.c b/gcc/testsuite/gcc.target/aarch64/spellcheck_4.c
index 6f66fdc..37c9d3c 100644
--- a/gcc/testsuite/gcc.target/aarch64/spellcheck_4.c
+++ b/gcc/testsuite/gcc.target/aarch64/spellcheck_4.c
@@ -8,4 +8,4 @@ foo ()
}
/* { dg-error "unknown value 'armv8-a-typo' for -march" "" { target *-*-* } 0 } */
-/* { dg-message "valid arguments are: \[^\n\r]*; did you mean 'armv8-a'?" "" { target *-*-* } 0 } */
+/* { dg-message "valid arguments are: \[^\n\r]*(; did you mean 'armv*'?)?" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/strcmpopt_6.c b/gcc/testsuite/gcc.target/aarch64/strcmpopt_6.c
index 964b9e4..4c6de02 100644
--- a/gcc/testsuite/gcc.dg/strcmpopt_6.c
+++ b/gcc/testsuite/gcc.target/aarch64/strcmpopt_6.c
@@ -1,7 +1,7 @@
/* When the specified length exceeds one of the arguments of the call to memcmp,
the call to memcmp should NOT be inlined. */
-/* { dg-do run } */
-/* { dg-options "-O2 -fdump-rtl-expand -Wno-stringop-overflow" } */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-stringop-overflow" } */
typedef struct { char s[8]; int x; } S;
@@ -33,4 +33,4 @@ int main (void)
}
-/* { dg-final { scan-rtl-dump-times "__builtin_memcmp" 6 "expand" } } */
+/* { dg-final { scan-assembler-times "memcmp" 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/bswap_1.c b/gcc/testsuite/gcc.target/aarch64/sve/bswap_1.c
new file mode 100644
index 0000000..aa4c033
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/bswap_1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include <stdint.h>
+
+void
+f (uint16_t *a, uint16_t *b)
+{
+ for (int i = 0; i < 100; ++i)
+ a[i] = __builtin_bswap16 (b[i]);
+}
+
+/* { dg-final { scan-assembler-times {\trevb\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 1 { xfail aarch64_big_endian } } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/bswap_2.c b/gcc/testsuite/gcc.target/aarch64/sve/bswap_2.c
new file mode 100644
index 0000000..442c65e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/bswap_2.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include <stdint.h>
+
+void
+f (uint32_t *a, uint32_t *b)
+{
+ for (int i = 0; i < 100; ++i)
+ a[i] = __builtin_bswap32 (b[i]);
+}
+
+/* { dg-final { scan-assembler-times {\trevb\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 { xfail aarch64_big_endian } } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/bswap_3.c b/gcc/testsuite/gcc.target/aarch64/sve/bswap_3.c
new file mode 100644
index 0000000..75acc64
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/bswap_3.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include <stdint.h>
+
+void
+f (uint64_t *a, uint64_t *b)
+{
+ for (int i = 0; i < 100; ++i)
+ a[i] = __builtin_bswap64 (b[i]);
+}
+
+/* { dg-final { scan-assembler-times {\trevb\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d\n} 1 { xfail aarch64_big_endian } } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/reduc_8.c b/gcc/testsuite/gcc.target/aarch64/sve/reduc_8.c
new file mode 100644
index 0000000..3913b88
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/reduc_8.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+int
+reduc (int *restrict a, int *restrict b, int *restrict c)
+{
+ for (int i = 0; i < 100; ++i)
+ {
+ int res = 0;
+ for (int j = 0; j < 100; ++j)
+ if (b[i + j] != 0)
+ res = c[i + j];
+ a[i] = res;
+ }
+}
+
+/* { dg-final { scan-assembler-times {\tcmpne\tp[0-9]+\.s, } 1 } } */
+/* We ought to use the CMPNE result for the SEL too. */
+/* { dg-final { scan-assembler-not {\tcmpeq\tp[0-9]+\.s, } { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tsel\tz[0-9]+\.s, } 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/single_1.c b/gcc/testsuite/gcc.target/aarch64/sve/single_1.c
index a5dd5eb..11b88ae 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/single_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/single_1.c
@@ -36,7 +36,7 @@ TEST_LOOP (double, 3.0)
/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.s, #6\n} 1 } } */
/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.d, #7\n} 1 } } */
/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.d, #8\n} 1 } } */
-/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.h, #15360\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.h, #1\.0e\+0\n} 1 } } */
/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.s, #2\.0e\+0\n} 1 } } */
/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.d, #3\.0e\+0\n} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/single_2.c b/gcc/testsuite/gcc.target/aarch64/sve/single_2.c
index 1ef72b6..1fbf489 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/single_2.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/single_2.c
@@ -12,7 +12,7 @@
/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.s, #6\n} 1 } } */
/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.d, #7\n} 1 } } */
/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.d, #8\n} 1 } } */
-/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.h, #15360\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.h, #1\.0e\+0\n} 1 } } */
/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.s, #2\.0e\+0\n} 1 } } */
/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.d, #3\.0e\+0\n} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/single_3.c b/gcc/testsuite/gcc.target/aarch64/sve/single_3.c
index fefbfbf..a3688b6 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/single_3.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/single_3.c
@@ -12,7 +12,7 @@
/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.s, #6\n} 1 } } */
/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.d, #7\n} 1 } } */
/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.d, #8\n} 1 } } */
-/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.h, #15360\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.h, #1\.0e\+0\n} 1 } } */
/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.s, #2\.0e\+0\n} 1 } } */
/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.d, #3\.0e\+0\n} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/single_4.c b/gcc/testsuite/gcc.target/aarch64/sve/single_4.c
index c1b1af6..08965d3 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/single_4.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/single_4.c
@@ -12,7 +12,7 @@
/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.s, #6\n} 1 } } */
/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.d, #7\n} 1 } } */
/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.d, #8\n} 1 } } */
-/* { dg-final { scan-assembler-times {\tmov\tz[0-9]+\.h, #15360\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.h, #1\.0e\+0\n} 1 } } */
/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.s, #2\.0e\+0\n} 1 } } */
/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.d, #3\.0e\+0\n} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_1.c b/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_1.c
new file mode 100644
index 0000000..0d4892e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_1.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include <stdint.h>
+
+void
+f (uint8_t *restrict a, uint8_t *restrict b)
+{
+ for (int i = 0; i < 100; ++i)
+ {
+ a[i * 8] = b[i * 8 + 7] + 1;
+ a[i * 8 + 1] = b[i * 8 + 6] + 2;
+ a[i * 8 + 2] = b[i * 8 + 5] + 3;
+ a[i * 8 + 3] = b[i * 8 + 4] + 4;
+ a[i * 8 + 4] = b[i * 8 + 3] + 5;
+ a[i * 8 + 5] = b[i * 8 + 2] + 6;
+ a[i * 8 + 6] = b[i * 8 + 1] + 7;
+ a[i * 8 + 7] = b[i * 8 + 0] + 8;
+ }
+}
+
+/* { dg-final { scan-assembler-times {\trevb\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d\n} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_2.c b/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_2.c
new file mode 100644
index 0000000..86ace58
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_2.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include <stdint.h>
+
+void
+f (uint8_t *restrict a, uint8_t *restrict b)
+{
+ for (int i = 0; i < 100; ++i)
+ {
+ a[i * 8] = b[i * 8 + 3] + 1;
+ a[i * 8 + 1] = b[i * 8 + 2] + 2;
+ a[i * 8 + 2] = b[i * 8 + 1] + 3;
+ a[i * 8 + 3] = b[i * 8 + 0] + 4;
+ a[i * 8 + 4] = b[i * 8 + 7] + 5;
+ a[i * 8 + 5] = b[i * 8 + 6] + 6;
+ a[i * 8 + 6] = b[i * 8 + 5] + 7;
+ a[i * 8 + 7] = b[i * 8 + 4] + 8;
+ }
+}
+
+/* { dg-final { scan-assembler-times {\trevb\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_3.c b/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_3.c
new file mode 100644
index 0000000..d15215f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_3.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include <stdint.h>
+
+void
+f (uint8_t *restrict a, uint8_t *restrict b)
+{
+ for (int i = 0; i < 100; ++i)
+ {
+ a[i * 8] = b[i * 8 + 1] + 1;
+ a[i * 8 + 1] = b[i * 8 + 0] + 2;
+ a[i * 8 + 2] = b[i * 8 + 3] + 3;
+ a[i * 8 + 3] = b[i * 8 + 2] + 4;
+ a[i * 8 + 4] = b[i * 8 + 5] + 5;
+ a[i * 8 + 5] = b[i * 8 + 4] + 6;
+ a[i * 8 + 6] = b[i * 8 + 7] + 7;
+ a[i * 8 + 7] = b[i * 8 + 6] + 8;
+ }
+}
+
+/* { dg-final { scan-assembler-times {\trevb\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_4.c b/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_4.c
new file mode 100644
index 0000000..dc5262a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_4.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include <stdint.h>
+
+void
+f (uint8_t *restrict a, uint8_t *restrict b, uint8_t *restrict c)
+{
+ for (int i = 0; i < 100; ++i)
+ {
+ a[i * 8] = b[i * 8] + c[i * 8];
+ a[i * 8 + 1] = b[i * 8] + c[i * 8 + 1];
+ a[i * 8 + 2] = b[i * 8 + 2] + c[i * 8 + 2];
+ a[i * 8 + 3] = b[i * 8 + 2] + c[i * 8 + 3];
+ a[i * 8 + 4] = b[i * 8 + 4] + c[i * 8 + 4];
+ a[i * 8 + 5] = b[i * 8 + 4] + c[i * 8 + 5];
+ a[i * 8 + 6] = b[i * 8 + 6] + c[i * 8 + 6];
+ a[i * 8 + 7] = b[i * 8 + 6] + c[i * 8 + 7];
+ }
+}
+
+/* { dg-final { scan-assembler {\ttrn1\tz[0-9]+\.b, z[0-9]+\.b, z[0-9]+\.b\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_5.c b/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_5.c
new file mode 100644
index 0000000..d5a48af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_5.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include <stdint.h>
+
+void
+f (uint8_t *restrict a, uint8_t *restrict b,
+ uint8_t *restrict c, uint8_t *restrict d)
+{
+ for (int i = 0; i < 100; ++i)
+ {
+ a[i * 8] = c[i * 8] + d[i * 8];
+ a[i * 8 + 1] = c[i * 8] + d[i * 8 + 1];
+ a[i * 8 + 2] = c[i * 8 + 2] + d[i * 8 + 2];
+ a[i * 8 + 3] = c[i * 8 + 2] + d[i * 8 + 3];
+ a[i * 8 + 4] = c[i * 8 + 4] + d[i * 8 + 4];
+ a[i * 8 + 5] = c[i * 8 + 4] + d[i * 8 + 5];
+ a[i * 8 + 6] = c[i * 8 + 6] + d[i * 8 + 6];
+ a[i * 8 + 7] = c[i * 8 + 6] + d[i * 8 + 7];
+ b[i * 8] = c[i * 8 + 1] + d[i * 8];
+ b[i * 8 + 1] = c[i * 8 + 1] + d[i * 8 + 1];
+ b[i * 8 + 2] = c[i * 8 + 3] + d[i * 8 + 2];
+ b[i * 8 + 3] = c[i * 8 + 3] + d[i * 8 + 3];
+ b[i * 8 + 4] = c[i * 8 + 5] + d[i * 8 + 4];
+ b[i * 8 + 5] = c[i * 8 + 5] + d[i * 8 + 5];
+ b[i * 8 + 6] = c[i * 8 + 7] + d[i * 8 + 6];
+ b[i * 8 + 7] = c[i * 8 + 7] + d[i * 8 + 7];
+ }
+}
+
+/* { dg-final { scan-assembler {\ttrn1\tz[0-9]+\.b, z[0-9]+\.b, z[0-9]+\.b\n} } } */
+/* { dg-final { scan-assembler {\ttrn2\tz[0-9]+\.b, z[0-9]+\.b, z[0-9]+\.b\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_6.c b/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_6.c
new file mode 100644
index 0000000..2882461
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_6.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include <stdint.h>
+
+void
+f (uint8_t *restrict a, uint8_t *restrict b)
+{
+ for (int i = 0; i < 100; ++i)
+ {
+ a[i * 8] = b[i * 8 + 3] + 1;
+ a[i * 8 + 1] = b[i * 8 + 6] + 1;
+ a[i * 8 + 2] = b[i * 8 + 0] + 1;
+ a[i * 8 + 3] = b[i * 8 + 2] + 1;
+ a[i * 8 + 4] = b[i * 8 + 1] + 1;
+ a[i * 8 + 5] = b[i * 8 + 7] + 1;
+ a[i * 8 + 6] = b[i * 8 + 5] + 1;
+ a[i * 8 + 7] = b[i * 8 + 4] + 1;
+ }
+}
+
+/* { dg-final { scan-assembler-times {\ttbl\tz[0-9]+\.b, z[0-9]+\.b, z[0-9]+\.b\n} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_7.c b/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_7.c
new file mode 100644
index 0000000..da9e0a2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/slp_perm_7.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include <stdint.h>
+
+void
+f (uint8_t *restrict a, uint8_t *restrict b)
+{
+ for (int i = 0; i < 100; ++i)
+ {
+ a[i * 8] = b[i * 8 + 1] + 1;
+ a[i * 8 + 1] = b[i * 8 + 7] + 2;
+ a[i * 8 + 2] = b[i * 8 + 1] + 3;
+ a[i * 8 + 3] = b[i * 8 + 7] + 4;
+ a[i * 8 + 4] = b[i * 8 + 1] + 5;
+ a[i * 8 + 5] = b[i * 8 + 7] + 6;
+ a[i * 8 + 6] = b[i * 8 + 1] + 7;
+ a[i * 8 + 7] = b[i * 8 + 7] + 8;
+ }
+}
+
+/* { dg-final { scan-assembler {\ttbl\tz[0-9]+\.b, z[0-9]+\.b, z[0-9]+\.b\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/tls_preserve_1.c b/gcc/testsuite/gcc.target/aarch64/sve/tls_preserve_1.c
new file mode 100644
index 0000000..c9ee14d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/tls_preserve_1.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fpic" } */
+
+/* Clobber highs do not need to be spilled around tls usage. */
+
+typedef float v4si __attribute__ ((vector_size (16)));
+
+__thread v4si tx;
+
+v4si foo (v4si a, v4si b, v4si c)
+{
+ v4si y;
+
+ y = a + tx + b + c;
+
+ return y + 7;
+}
+
+/* { dg-final { scan-assembler-not {\tst[rp]\t[dqv]} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/tls_preserve_2.c b/gcc/testsuite/gcc.target/aarch64/sve/tls_preserve_2.c
new file mode 100644
index 0000000..37bd470
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/tls_preserve_2.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fpic -msve-vector-bits=256 -fno-schedule-insns" } */
+
+/* Clobber highs must be spilled around tls usage. */
+
+typedef float v8si __attribute__ ((vector_size (32)));
+
+__thread v8si tx;
+
+v8si foo (v8si a, v8si b, v8si c)
+{
+ v8si y;
+
+ /* There is nothing stopping the compiler from making the tls call before
+ loading the input variables off the stack. However, there appears to
+ be no way in C of enforcing this. Thankfully the compiler doesn't
+ do this reordering. */
+
+ y = a + tx + b + c;
+
+ return y + 7;
+}
+
+/* { dg-final { scan-assembler-times {\tstr\tz[0-9]+,} 3 } } */ \ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/tls_preserve_3.c b/gcc/testsuite/gcc.target/aarch64/sve/tls_preserve_3.c
new file mode 100644
index 0000000..162ece6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/tls_preserve_3.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fpic -msve-vector-bits=512 -fno-schedule-insns" } */
+
+/* Clobber highs must be spilled around tls usage. */
+
+typedef float v16si __attribute__ ((vector_size (64)));
+
+__thread v16si tx;
+
+v16si foo (v16si a, v16si b, v16si c)
+{
+ v16si y;
+
+ /* There is nothing stopping the compiler from making the tls call before
+ loading the input variables off the stack. However, there appears to
+ be no way in C of enforcing this. Thankfully the compiler doesn't
+ do this reordering. */
+
+ y = a + tx + b + c;
+
+ return y + 7;
+}
+
+/* { dg-final { scan-assembler-times {\tstr\tz[0-9]+,} 3 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/var_stride_2.c b/gcc/testsuite/gcc.target/aarch64/sve/var_stride_2.c
index 112e84f..30f6d26 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/var_stride_2.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/var_stride_2.c
@@ -16,7 +16,8 @@ f (TYPE *x, TYPE *y, unsigned short n, unsigned short m)
/* { dg-final { scan-assembler {\tldr\tw[0-9]+} } } */
/* { dg-final { scan-assembler {\tstr\tw[0-9]+} } } */
/* Should multiply by (257-1)*4 rather than (VF-1)*4. */
-/* { dg-final { scan-assembler-times {\tadd\tx[0-9]+, x[0-9]+, x[0-9]+, lsl 10\n} 2 } } */
+/* { dg-final { scan-assembler-times {\tubfiz\tx[0-9]+, x2, 10, 16\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tubfiz\tx[0-9]+, x3, 10, 16\n} 1 } } */
/* { dg-final { scan-assembler-not {\tcmp\tx[0-9]+, 0} } } */
/* { dg-final { scan-assembler-not {\tcmp\tw[0-9]+, 0} } } */
/* { dg-final { scan-assembler-not {\tcsel\tx[0-9]+} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/var_stride_4.c b/gcc/testsuite/gcc.target/aarch64/sve/var_stride_4.c
index 4bcdb5d..d2e74f9 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/var_stride_4.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/var_stride_4.c
@@ -16,7 +16,8 @@ f (TYPE *x, TYPE *y, int n, int m)
/* { dg-final { scan-assembler {\tldr\tw[0-9]+} } } */
/* { dg-final { scan-assembler {\tstr\tw[0-9]+} } } */
/* Should multiply by (257-1)*4 rather than (VF-1)*4. */
-/* { dg-final { scan-assembler-times {\tlsl\tx[0-9]+, x[0-9]+, 10\n} 2 } } */
+/* { dg-final { scan-assembler-times {\tsbfiz\tx[0-9]+, x2, 10, 32\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tsbfiz\tx[0-9]+, x3, 10, 32\n} 1 } } */
/* { dg-final { scan-assembler {\tcmp\tw2, 0} } } */
/* { dg-final { scan-assembler {\tcmp\tw3, 0} } } */
/* { dg-final { scan-assembler-times {\tcsel\tx[0-9]+} 4 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vcond_4.c b/gcc/testsuite/gcc.target/aarch64/sve/vcond_4.c
index 230a6c9..00d8476 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/vcond_4.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/vcond_4.c
@@ -88,52 +88,54 @@ TEST_CMP (nule)
TEST_CMP (nuge)
TEST_CMP (nugt)
-/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0\n} 5 } } */
-/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 10 } } */
+/* See PR 86753 for the reason behind the XFAILs. */
+
+/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0\n} 5 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 10 { xfail *-*-* } } } */
/* 5 for ne, 5 for ueq and 5 for nueq. */
-/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0\n} 15 } } */
-/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 30 } } */
+/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0\n} 15 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 30 { xfail *-*-* } } } */
/* 5 for lt, 5 for ult and 5 for nult. */
-/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0\n} 15 } } */
-/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 30 } } */
+/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0\n} 15 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 30 { xfail *-*-* } } } */
/* 5 for le, 5 for ule and 5 for nule. */
-/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0\n} 15 } } */
-/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 30 } } */
+/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0\n} 15 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 30 { xfail *-*-* } } } */
/* 5 for gt, 5 for ugt and 5 for nugt. */
-/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0\n} 15 } } */
-/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 30 } } */
+/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0\n} 15 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 30 { xfail *-*-* } } } */
/* 5 for ge, 5 for uge and 5 for nuge. */
-/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0\n} 15 } } */
-/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 30 } } */
+/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0\n} 15 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 30 { xfail *-*-* } } } */
/* { dg-final { scan-assembler-not {\tfcmuo\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0\n} } } */
/* 3 loops * 5 invocations for all 12 unordered comparisons. */
-/* { dg-final { scan-assembler-times {\tfcmuo\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 180 } } */
+/* { dg-final { scan-assembler-times {\tfcmuo\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 180 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0\n} 7 } } */
-/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d\n} 14 } } */
+/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0\n} 7 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d\n} 14 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0\n} 21 } } */
-/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d\n} 42 } } */
+/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0\n} 21 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d\n} 42 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0\n} 21 } } */
-/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d\n} 42 } } */
+/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0\n} 21 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d\n} 42 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0\n} 21 } } */
-/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d\n} 42 } } */
+/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0\n} 21 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d\n} 42 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0\n} 21 } } */
-/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d\n} 42 } } */
+/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0\n} 21 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d\n} 42 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0\n} 21 } } */
-/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d\n} 42 } } */
+/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0\n} 21 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d\n} 42 { xfail *-*-* } } } */
/* { dg-final { scan-assembler-not {\tfcmuo\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0\n} } } */
/* 3 loops * 5 invocations, with 2 invocations having ncopies == 2,
for all 12 unordered comparisons. */
-/* { dg-final { scan-assembler-times {\tfcmuo\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d\n} 252 } } */
+/* { dg-final { scan-assembler-times {\tfcmuo\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d\n} 252 { xfail *-*-* } } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vcond_5.c b/gcc/testsuite/gcc.target/aarch64/sve/vcond_5.c
index 37c6b62..23bfb7b 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/vcond_5.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/vcond_5.c
@@ -5,52 +5,54 @@
#include "vcond_4.c"
+/* See PR 86753 for the reason behind the XFAILs. */
+
/* 5 for eqand 5 for ueq. */
-/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0} 10 } } */
-/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s} 20 } } */
+/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0} 10 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s} 20 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0} 5 } } */
-/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s} 10 } } */
+/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0} 5 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s} 10 { xfail *-*-* } } } */
/* 5 for lt, 5 for ult, 5 for nueq and 5 for nult. */
-/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0} 20 } } */
-/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s} 40 } } */
+/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0} 20 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s} 40 { xfail *-*-* } } } */
/* 5 for le, 5 for ule and 5 for nule. */
-/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0} 15 } } */
-/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s} 30 } } */
+/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0} 15 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s} 30 { xfail *-*-* } } } */
/* 5 for gt, 5 for ugt, 5 for nueq and 5 for nugt. */
-/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0} 20 } } */
-/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s} 40 } } */
+/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0} 20 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s} 40 { xfail *-*-* } } } */
/* 5 for ge, 5 for uge and 5 for nuge. */
-/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0} 15 } } */
-/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s} 30 } } */
+/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0} 15 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s} 30 { xfail *-*-* } } } */
/* { dg-final { scan-assembler-not {\tfcmuo\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0\.0} } } */
/* 3 loops * 5 invocations for ordered, unordered amd ueq. */
-/* { dg-final { scan-assembler-times {\tfcmuo\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s} 45 } } */
+/* { dg-final { scan-assembler-times {\tfcmuo\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s} 45 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0} 14 } } */
-/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d} 28 } } */
+/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0} 14 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d} 28 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0} 7 } } */
-/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d} 14 } } */
+/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0} 7 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d} 14 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0} 28 } } */
-/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d} 56 } } */
+/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0} 28 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d} 56 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0} 21 } } */
-/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d} 42 } } */
+/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0} 21 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d} 42 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0} 28 } } */
-/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d} 56 } } */
+/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0} 28 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d} 56 { xfail *-*-* } } } */
-/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0} 21 } } */
-/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d} 42 } } */
+/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0} 21 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d} 42 { xfail *-*-* } } } */
/* { dg-final { scan-assembler-not {\tfcmuo\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, #0\.0} } } */
/* 3 loops * 5 invocations, with 2 invocations having ncopies == 2,
for ordered, unordered and ueq. */
-/* { dg-final { scan-assembler-times {\tfcmuo\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d} 63 } } */
+/* { dg-final { scan-assembler-times {\tfcmuo\tp[0-9]+\.d, p[0-7]/z, z[0-9]+\.d, z[0-9]+\.d} 63 { xfail *-*-* } } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/vabs_intrinsic_3.c b/gcc/testsuite/gcc.target/aarch64/vabs_intrinsic_3.c
new file mode 100644
index 0000000..cf4e7ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vabs_intrinsic_3.c
@@ -0,0 +1,39 @@
+/* Test the vabsd_s64 intrinsic. */
+
+/* { dg-do run } */
+/* { dg-options "--save-temps -O2" } */
+
+#include <arm_neon.h>
+#include <limits.h>
+
+extern void abort (void);
+
+#define force_simd(V1) asm volatile ("mov %d0, %1.d[0]" \
+ : "=w"(V1) \
+ : "w"(V1) \
+ : /* No clobbers */);
+
+#define RUN_TEST(test, answ) \
+{ \
+ force_simd (test); \
+ force_simd (answ); \
+ int64_t res = vabsd_s64 (test); \
+ force_simd (res); \
+ if (res != answ) \
+ abort (); \
+}
+
+int64_t input[] = {INT64_MAX, 10, 0, -10, INT64_MIN + 1, INT64_MIN};
+int64_t expected[] = {INT64_MAX, 10, 0, 10, INT64_MAX, INT64_MIN};
+
+int main (void)
+{
+ RUN_TEST (input[0], expected[0]);
+ RUN_TEST (input[1], expected[1]);
+ RUN_TEST (input[2], expected[2]);
+ RUN_TEST (input[3], expected[3]);
+ RUN_TEST (input[4], expected[4]);
+ RUN_TEST (input[5], expected[5]);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/vabsd_s64.c b/gcc/testsuite/gcc.target/aarch64/vabsd_s64.c
new file mode 100644
index 0000000..a0f88ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vabsd_s64.c
@@ -0,0 +1,34 @@
+/* Check that the compiler does not optimise the vabsd_s64 call out.
+ We need to check for this because there is a mismatch in semantics
+ between the ACLE, which states that he absolute value of the minimum
+ (signed) value is itself, and C, where this is undefined behaviour. */
+
+/* { dg-do run } */
+/* { dg-options "--save-temps -fno-inline -O2" } */
+
+#include <arm_neon.h>
+#include <limits.h>
+
+extern void abort (void);
+
+int
+bar (int64_t x)
+{
+ if (x < (int64_t) 0)
+ return vabsd_s64 (x) < (int64_t) 0;
+ else
+ return -1;
+}
+
+int
+main (void)
+{
+ int ans = 1;
+ int res_abs = bar (INT64_MIN);
+
+ if (res_abs != ans)
+ abort ();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/aarch64/vneg_s.c b/gcc/testsuite/gcc.target/aarch64/vneg_s.c
index 9110540..e7f20f2 100644
--- a/gcc/testsuite/gcc.target/aarch64/vneg_s.c
+++ b/gcc/testsuite/gcc.target/aarch64/vneg_s.c
@@ -75,6 +75,18 @@ extern void abort (void);
} \
}
+#define RUN_TEST_SCALAR(test_val, answ_val, a, b) \
+ { \
+ int64_t res; \
+ INHIB_OPTIMIZATION; \
+ a = test_val; \
+ b = answ_val; \
+ force_simd (b); \
+ force_simd (a); \
+ res = vnegd_s64 (a); \
+ force_simd (res); \
+ }
+
int
test_vneg_s8 ()
{
@@ -177,7 +189,24 @@ test_vneg_s64 ()
return 0;
}
-/* { dg-final { scan-assembler-times "neg\\td\[0-9\]+, d\[0-9\]+" 8 } } */
+int
+test_vnegd_s64 ()
+{
+ int64_t a, b;
+
+ RUN_TEST_SCALAR (TEST0, ANSW0, a, b);
+ RUN_TEST_SCALAR (TEST1, ANSW1, a, b);
+ RUN_TEST_SCALAR (TEST2, ANSW2, a, b);
+ RUN_TEST_SCALAR (TEST3, ANSW3, a, b);
+ RUN_TEST_SCALAR (TEST4, ANSW4, a, b);
+ RUN_TEST_SCALAR (TEST5, ANSW5, a, b);
+ RUN_TEST_SCALAR (LLONG_MAX, LLONG_MIN + 1, a, b);
+ RUN_TEST_SCALAR (LLONG_MIN, LLONG_MIN, a, b);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "neg\\td\[0-9\]+, d\[0-9\]+" 16 } } */
int
test_vnegq_s8 ()
@@ -283,6 +312,9 @@ main (int argc, char **argv)
if (test_vneg_s64 ())
abort ();
+ if (test_vnegd_s64 ())
+ abort ();
+
if (test_vnegq_s8 ())
abort ();
diff --git a/gcc/testsuite/gcc.target/aarch64/vnegd_s64.c b/gcc/testsuite/gcc.target/aarch64/vnegd_s64.c
new file mode 100644
index 0000000..73d478f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vnegd_s64.c
@@ -0,0 +1,36 @@
+/* Check that the compiler does not optimise the negation out.
+ We need to check for this because there is a mismatch in semantics
+ between the ACLE, which states that he negative of the minimum
+ (signed) value is itself and C, where this is undefined behaviour. */
+
+/* { dg-do run } */
+/* { dg-options "--save-temps -O2" } */
+
+#include <arm_neon.h>
+#include <limits.h>
+
+extern void abort (void);
+
+int
+foo (int64_t x)
+{
+ if (x < (int64_t) 0)
+ return vnegd_s64 (x) < (int64_t) 0;
+ else
+ return -1;
+}
+
+/* { dg-final { scan-assembler-times {neg\tx[0-9]+, x[0-9]+} 1 } } */
+
+int
+main (void)
+{
+ int ans = 1;
+ int res = foo (INT64_MIN);
+
+ if (res != ans)
+ abort ();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/alpha/pr86984.c b/gcc/testsuite/gcc.target/alpha/pr86984.c
new file mode 100644
index 0000000..f6a98d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/alpha/pr86984.c
@@ -0,0 +1,96 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wall -Wwrite-strings -Werror -fmerge-all-constants -fno-stack-protector -mieee -fdump-rtl-expand" } */
+
+struct expression {
+ unsigned long int num;
+};
+union YYSTYPE {
+ unsigned long int num;
+ struct expression *exp;
+};
+
+typedef union YYSTYPE YYSTYPE;
+
+struct expression * new_exp_0 (int);
+
+union yyalloc {
+ short yyss_alloc;
+};
+
+static const signed char yypact[] = {
+ -9, -9, -10, -10, -9, 8, 36, -10, 13, -10, -9, -9, -9, -9, -9, -9, -9, -10, 26, 41, 45, 18, -2, 14, -10, -9, 36 };
+static const unsigned char yydefact[] = {
+ 0, 0, 12, 11, 0, 0, 2, 10, 0, 1, 0, 0, 0, 0, 0, 0, 0, 13, 0, 4, 5, 6, 7, 8, 9, 0, 3 };
+
+static const signed char yypgoto[3] = "\366\366\377";
+static const signed char yydefgoto[3] = "\377\005\006";
+
+static const unsigned char yytable[] = {
+ 7, 1, 2, 8, 3, 4, 15, 16, 9, 18, 19, 20, 21, 22, 23, 24, 10, 11, 12, 13, 14, 15, 16, 16, 26, 14, 15, 16, 17, 10, 11, 12, 13, 14, 15, 16, 0, 0, 25, 10, 11, 12, 13, 14, 15, 16, 12, 13, 14, 15, 16, 13, 14, 15, 16 };
+
+static const signed char yycheck[] = {
+ 1, 10, 11, 4, 13, 14, 8, 9, 0, 10, 11, 12, 13, 14, 15, 16, 3, 4, 5, 6, 7, 8, 9, 9, 25, 7, 8, 9, 15, 3, 4, 5, 6, 7, 8, 9, -1, -1, 12, 3, 4, 5, 6, 7, 8, 9, 5, 6, 7, 8, 9, 6, 7, 8, 9 };
+
+static const unsigned char yyr1[] = {
+ 0, 16, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18 };
+
+static const unsigned char yyr2[] = {
+ 0, 2, 1, 5, 3, 3, 3, 3, 3, 3, 2, 1, 1, 3 };
+
+int __gettextparse (void)
+{
+ int yystate = 0;
+ short yyssa[200];
+ short *yyss = yyss;
+ short *yyssp = yyssa;
+ YYSTYPE yyvsa[200];
+ YYSTYPE *yyvsp = yyvsa;
+ enum { yystacksize = 200 };
+ int yylen = 0;
+ goto yysetstate;
+ yynewstate: yyssp++;
+ yysetstate: *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ long unsigned int yysize = yyssp - yyss + 1;
+ {
+ short *yyss1 = yyss;
+ union yyalloc *yyptr = (union yyalloc *) __builtin_malloc ((yystacksize * (sizeof (short) + sizeof (YYSTYPE)) + (sizeof (union yyalloc) - 1)));
+ if (!yyptr) return 0;
+ __builtin_memcpy (&yyptr->yyss_alloc, yyss, yysize * sizeof *(yyss));
+ yyss = &yyptr->yyss_alloc;
+ if (yyss1 != yyssa) __builtin_free (yyss1);
+ }
+ if (yyss + yystacksize - 1 <= yyssp)
+ return 0;
+ }
+
+ int yyn = yypact[yystate];
+ if (yyn == -10)
+ goto yydefault;
+
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ goto yyreduce;
+
+ yydefault: yyn = yydefact[yystate];
+ yyreduce: yylen = yyr2[yyn];
+
+ YYSTYPE yyval;
+ if (yyn == 12 && (yyval.exp = new_exp_0 (0)) != 0)
+ (yyval.exp)->num = (yyvsp[0].num);
+
+ (yyvsp -= yylen, yyssp -= yylen);
+ yyn = yyr1[yyn];
+ yystate = yypgoto[yyn - 16] + *yyssp;
+ if (0 <= yystate && yystate <= 54 && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - 16];
+
+ goto yynewstate;
+}
+
+/* { dg-final { scan-rtl-dump-not "const_int 230584300921" "expand" } } */
+/* { dg-final { scan-assembler-not "yypgoto\\+230584300921" } } */
diff --git a/gcc/testsuite/gcc.target/csky/and1.c b/gcc/testsuite/gcc.target/csky/and1.c
new file mode 100644
index 0000000..14ce11a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/csky/and1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-csky-options "-O1" } */
+
+/* Test special code generation patterns for bit operators. */
+
+int and1 (int x)
+{
+ return x & 0xfff7ffff;
+}
+
+/* { dg-final { scan-assembler "bclri" } } */
+
diff --git a/gcc/testsuite/gcc.target/csky/and2.c b/gcc/testsuite/gcc.target/csky/and2.c
new file mode 100644
index 0000000..c661199
--- /dev/null
+++ b/gcc/testsuite/gcc.target/csky/and2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-csky-options "-O1" } */
+
+/* Test special code generation patterns for bit operators. */
+
+int and2 (int x)
+{
+ return x & 0xfff00000;
+}
+
+/* { dg-final { scan-assembler "lsri" } } */
+/* { dg-final { scan-assembler "lsli" } } */
diff --git a/gcc/testsuite/gcc.target/csky/and3a.c b/gcc/testsuite/gcc.target/csky/and3a.c
new file mode 100644
index 0000000..3d706f6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/csky/and3a.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-csky-options "-mcpu=ck801 -O1" } */
+
+/* Test special code generation patterns for bit operators. */
+
+int and3 (int x)
+{
+ return x & 0x000fffff;
+}
+
+/* { dg-final { scan-assembler "lsli" } } */
+/* { dg-final { scan-assembler "lsri" } } */
diff --git a/gcc/testsuite/gcc.target/csky/and3b.c b/gcc/testsuite/gcc.target/csky/and3b.c
new file mode 100644
index 0000000..127207d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/csky/and3b.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-csky-options "-mcpu=ck810f -O1" } */
+
+/* Test special code generation patterns for bit operators. */
+
+int and3 (int x)
+{
+ return x & 0x000fffff;
+}
+
+/* { dg-final { scan-assembler "zext" } } */
diff --git a/gcc/testsuite/gcc.target/csky/ck801-branch.c b/gcc/testsuite/gcc.target/csky/ck801-branch.c
new file mode 100644
index 0000000..95e6962
--- /dev/null
+++ b/gcc/testsuite/gcc.target/csky/ck801-branch.c
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-csky-options "-mcpu=ck801 -O1 -fno-reorder-blocks" } */
+
+/* Test branch generation on CK801, which cannot rely on assembler
+ branch relaxation because long branches clobber lr. */
+
+#define nop8 asm ("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop")
+#define nop64 nop8; nop8; nop8; nop8; nop8; nop8; nop8; nop8
+#define nop512 nop64; nop64; nop64; nop64; nop64; nop64; nop64; nop64
+#define nop4k nop512; nop512; nop512; nop512; nop512; nop512; nop512; nop512
+#define nop32k nop4k; nop4k; nop4k; nop4k; nop4k; nop4k; nop4k; nop4k
+
+extern void g (int);
+int f (int x, int y, int z)
+{
+ if (x == 0) // cmpnei; jbt
+ {
+ nop64;
+ x = y;
+ }
+ if (y == 0) // cmpnei; jbf; jbr
+ {
+ nop512;
+ y = z;
+ }
+ if (z == 0) // cmpnei; jbf; bsr
+ {
+ nop32k;
+ z = x;
+ }
+ return x + y + z;
+}
+
+/* { dg-final { scan-assembler "push.*lr" } } */
+/* { dg-final { scan-assembler "pop.*lr" } } */
+/* { dg-final { scan-assembler-times "cmpnei" 3 } } */
+/* { dg-final { scan-assembler-times "jbt" 1 } } */
+/* { dg-final { scan-assembler-times "jbf" 2 } } */
+/* { dg-final { scan-assembler-times "jbr" 1 } } */
+/* { dg-final { scan-assembler-times "bsr" 1 } } */
diff --git a/gcc/testsuite/gcc.target/csky/constpool-1.c b/gcc/testsuite/gcc.target/csky/constpool-1.c
new file mode 100644
index 0000000..5c7cfdc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/csky/constpool-1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-csky-options "-mcpu=ck801 -O1" } */
+
+/* Make sure that constant pools are emitted by the compiler for ck801.
+ If this is deferred to the assembler, the compiler will compute
+ incorrect branch offsets. */
+
+void f (unsigned int *u, long long int *l, float *f, double *d)
+{
+ *u = 0xdeadbeef;
+ *l = 0xcafef00dc0ffeeULL;
+ *f = 3.14159F;
+ *d = 2.718281828459;
+}
+
+/* { dg-final { scan-assembler-times "\\.long" 6 } } */
diff --git a/gcc/testsuite/gcc.target/csky/constpool-2.c b/gcc/testsuite/gcc.target/csky/constpool-2.c
new file mode 100644
index 0000000..d654420
--- /dev/null
+++ b/gcc/testsuite/gcc.target/csky/constpool-2.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-csky-options "-mcpu=ck810f -O1 -mconstpool" } */
+
+/* Make sure that constant pools are emitted by the compiler when
+ -mconstpool is provided. */
+
+void f (unsigned int *u, long long int *l, float *f, double *d)
+{
+ *u = 0xdeadbeef;
+ *l = 0xcafef00dc0ffeeULL;
+ *f = 3.14159F;
+ *d = 2.718281828459;
+}
+
+/* { dg-final { scan-assembler-times "\\.long" 6 } } */
diff --git a/gcc/testsuite/gcc.target/csky/constpool-3.c b/gcc/testsuite/gcc.target/csky/constpool-3.c
new file mode 100644
index 0000000..e3a6e09
--- /dev/null
+++ b/gcc/testsuite/gcc.target/csky/constpool-3.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-csky-options "-mcpu=ck810f -O1 -mno-constpool" } */
+
+/* Make sure that constant pools are not emitted by the compiler when
+ -mno-constpool is provided. */
+
+void f (unsigned int *u, long long int *l, float *f, double *d)
+{
+ *u = 0xdeadbeef;
+ *l = 0xcafef00dc0ffeeULL;
+ *f = 3.14159F;
+ *d = 2.718281828459;
+}
+
+/* { dg-final { scan-assembler-not "\\.long" } } */
diff --git a/gcc/testsuite/gcc.target/csky/cse-cc.c b/gcc/testsuite/gcc.target/csky/cse-cc.c
new file mode 100644
index 0000000..b97a16e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/csky/cse-cc.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-csky-options "-O2" } */
+
+/* Test that the two comparisons are combined. This was formerly handled
+ by a no-longer-present target-specific pass and is now supposed to
+ be handled by generic CSE. */
+
+int e1, e2;
+
+void func (int a, int b, int c, int d, int f, int g)
+{
+ e1 = a > b ? f : g;
+ e2 = a > b ? c : d;
+
+ return;
+}
+
+/* { dg-final { scan-assembler-times "cmp" 1 } } */
+
diff --git a/gcc/testsuite/gcc.target/csky/csky.exp b/gcc/testsuite/gcc.target/csky/csky.exp
new file mode 100644
index 0000000..9569490
--- /dev/null
+++ b/gcc/testsuite/gcc.target/csky/csky.exp
@@ -0,0 +1,79 @@
+# GCC testsuite for C-SKY targets.
+# Copyright (C) 2012-2018 Free Software Foundation, Inc.
+# Contributed by C-SKY Microsystems and Mentor Graphics.
+#
+# 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/>.
+
+# Exit immediately if this isn't a C-SKY target.
+if ![istarget csky*-*-*] then {
+ return
+}
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# Like dg-options, but treats certain C-SKY-specific options specially:
+#
+# -mcpu=*
+# Select the target cpu. Skip the test if the multilib flags force
+# a different cpu.
+proc dg-csky-options {args} {
+ upvar dg-extra-tool-flags extra_tool_flags
+ upvar dg-do-what do_what
+
+ set multilib_cpu ""
+ set multilib_hf ""
+ set cpu ""
+
+ foreach flag [target_info multilib_flags] {
+ regexp "^-mcpu=(.*)" $flag dummy multilib_cpu
+ regexp "^-mhard-float" $flag multilib_hf
+ }
+
+ set flags [lindex $args 1]
+
+ foreach flag $flags {
+ regexp "^-mcpu=(.*)" $flag dummy cpu
+ }
+
+ if {$cpu == ""} then {
+ set extra_tool_flags $flags
+ } elseif {$multilib_cpu == "" || $multilib_cpu == $cpu} then {
+ if { ($cpu == "ck801" || $cpu == "ck802")
+ && $multilib_hf != "" } then {
+ set do_what [list [lindex $do_what 0] "N" "P"]
+ } else {
+ set extra_tool_flags $flags
+ }
+ } else {
+ set do_what [list [lindex $do_what 0] "N" "P"]
+ }
+}
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CFLAGS
+if ![info exists DEFAULT_CFLAGS] then {
+ set DEFAULT_CFLAGS " -ansi -pedantic-errors"
+}
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
+ "" $DEFAULT_CFLAGS
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gcc.target/csky/fnargs-1.c b/gcc/testsuite/gcc.target/csky/fnargs-1.c
new file mode 100644
index 0000000..5cc85b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/csky/fnargs-1.c
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+
+/* Check that a structure argument passed partially in registers and
+ partially on the stack works. */
+
+#include <stdlib.h>
+#include <string.h>
+
+struct s {
+ unsigned int i;
+ double d;
+ char s[16];
+};
+
+/* Note specifically that, since there are 4 argument registers, the
+ value of ss.d is split between the last argument register and the
+ stack. */
+void
+f (struct s *sp, int j, struct s ss, int k)
+{
+ if (sp->i != ss.i
+ || sp->d != ss.d
+ || strcmp (sp->s, ss.s))
+ abort ();
+ if (j != -k)
+ abort ();
+}
+
+int
+main (void)
+{
+ struct s ss;
+ ss.i = 0xdeadbeef;
+ ss.d = 2.71828;
+ strcpy (ss.s, "shazam!");
+ f (&ss, 42, ss, -42);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/csky/fnargs-2.c b/gcc/testsuite/gcc.target/csky/fnargs-2.c
new file mode 100644
index 0000000..d4e1b71
--- /dev/null
+++ b/gcc/testsuite/gcc.target/csky/fnargs-2.c
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+
+/* Check that varargs passed partially in registers and
+ partially on the stack works. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+struct s {
+ unsigned int i;
+ double d;
+ char s[16];
+};
+
+/* Note specifically that, as there are 4 argument registers,
+ the value of ss.d is split between the last argument register
+ and the stack. */
+void
+f (struct s *sp, ...)
+{
+ int j, k;
+ unsigned int i;
+ double d;
+ char *s;
+ va_list ap;
+ va_start (ap, sp);
+ j = va_arg (ap, int);
+ i = va_arg (ap, unsigned int);
+ d = va_arg (ap, double);
+ s = va_arg (ap, char *);
+ k = va_arg (ap, int);
+ va_end (ap);
+
+ if (sp->i != i
+ || sp->d != d
+ || strcmp (sp->s, s))
+ abort ();
+ if (j != -k)
+ abort ();
+}
+
+int
+main (void)
+{
+ struct s ss;
+ ss.i = 0xdeadbeef;
+ ss.d = 2.71828;
+ strcpy (ss.s, "shazam!");
+ f (&ss, 42, ss.i, ss.d, ss.s, -42);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/csky/fnargs-3.c b/gcc/testsuite/gcc.target/csky/fnargs-3.c
new file mode 100644
index 0000000..8cf3e5c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/csky/fnargs-3.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+
+/* Check that sub-word sized elements of structures passed in in
+ registers are handled correctly with respect to the current endianness. */
+
+#include <stdlib.h>
+#include <string.h>
+
+struct s {
+ short h;
+ char s[8];
+};
+
+void
+f (struct s *sp, struct s ss)
+{
+ if (sp->h != ss.h
+ || strcmp (sp->s, ss.s))
+ abort ();
+}
+
+int
+main (void)
+{
+ struct s ss;
+ ss.h = 42;
+ strcpy (ss.s, "shazam!");
+ f (&ss, ss);
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/csky/land1.c b/gcc/testsuite/gcc.target/csky/land1.c
new file mode 100644
index 0000000..e5ca51c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/csky/land1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-csky-options "-O1" } */
+
+/* Test special code generation patterns for bit operators. */
+
+long long int land1 (long long int x)
+{
+ return x & 0xffffffff00000000LL;
+}
+
+/* { dg-final { scan-assembler "movi.*, 0" } } */
diff --git a/gcc/testsuite/gcc.target/csky/land2.c b/gcc/testsuite/gcc.target/csky/land2.c
new file mode 100644
index 0000000..b45e7b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/csky/land2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-csky-options "-O1" } */
+
+/* Test special code generation patterns for bit operators. */
+
+long long int land2 (long long int x)
+{
+ return x & 0x00000000ffffffffLL;
+}
+
+/* { dg-final { scan-assembler "movi.*, 0" } } */
diff --git a/gcc/testsuite/gcc.target/csky/naked.c b/gcc/testsuite/gcc.target/csky/naked.c
new file mode 100644
index 0000000..f81984c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/csky/naked.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-final { scan-assembler-not "push" } } */
+/* { dg-final { scan-assembler-not "pop" } } */
+
+/* Check that there is no prologue/epilogue code emitted for a function
+ with the naked attribute. Without the attribute, this function would
+ push/pop lr. */
+
+extern void g (int);
+
+int __attribute__((naked))
+f (int x)
+{
+ g (x);
+ return 42;
+}
diff --git a/gcc/testsuite/gcc.target/csky/or1.c b/gcc/testsuite/gcc.target/csky/or1.c
new file mode 100644
index 0000000..24918bc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/csky/or1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-csky-options "-O1" } */
+
+/* Test special code generation patterns for bit operators. */
+
+int or1 (int x)
+{
+ return x | 0x00100000;
+}
+
+/* { dg-final { scan-assembler "bseti" } } */
diff --git a/gcc/testsuite/gcc.target/i386/addr-sel-1.c b/gcc/testsuite/gcc.target/i386/addr-sel-1.c
index 8b1b4d4..27623ff 100644
--- a/gcc/testsuite/gcc.target/i386/addr-sel-1.c
+++ b/gcc/testsuite/gcc.target/i386/addr-sel-1.c
@@ -14,4 +14,4 @@ int f(int i)
}
/* { dg-final { scan-assembler "a\\+1" } } */
-/* { dg-final { scan-assembler "b\\+1" { xfail *-*-* } } } */
+/* { dg-final { scan-assembler "b\\+1" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx-cvt-2.c b/gcc/testsuite/gcc.target/i386/avx-cvt-2.c
index 1fbcf6e..672ce06 100644
--- a/gcc/testsuite/gcc.target/i386/avx-cvt-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx-cvt-2.c
@@ -4,9 +4,9 @@
#include "avx-cvt-1.c"
/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 6 "vect" } } */
-/* { dg-final { scan-assembler "vcvttpd2dq(y\[^\n\r\]*%xmm|\[^\n\r\]*xmm\[^\n\r\]*YMMWORD PTR)" } } */
-/* { dg-final { scan-assembler "vcvtdq2ps\[^\n\r\]*ymm" } } */
-/* { dg-final { scan-assembler "vcvtps2pd\[^\n\r\]*(%xmm\[^\n\r\]*%ymm|ymm\[^\n\r\]*xmm)" } } */
-/* { dg-final { scan-assembler "vcvttps2dq\[^\n\r\]*ymm" } } */
-/* { dg-final { scan-assembler "vcvtdq2pd\[^\n\r\]*(%xmm\[^\n\r\]*%ymm|ymm\[^\n\r\]*xmm)" } } */
-/* { dg-final { scan-assembler "vcvtpd2ps(y\[^\n\r\]*%xmm|\[^\n\r\]*xmm\[^\n\r\]*YMMWORD PTR)" } } */
+/* { dg-final { scan-assembler "vcvttpd2dq" } } */
+/* { dg-final { scan-assembler "vcvtdq2ps" } } */
+/* { dg-final { scan-assembler "vcvtps2pd" } } */
+/* { dg-final { scan-assembler "vcvttps2dq" } } */
+/* { dg-final { scan-assembler "vcvtdq2pd" } } */
+/* { dg-final { scan-assembler "vcvtpd2ps" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-cvt-2.c b/gcc/testsuite/gcc.target/i386/avx2-cvt-2.c
index d37809d..633a1cd 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-cvt-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-cvt-2.c
@@ -4,9 +4,9 @@
#include "avx2-cvt-1.c"
/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 6 "vect" } } */
-/* { dg-final { scan-assembler "vcvttpd2dq(y\[^\n\r\]*%xmm|\[^\n\r\]*xmm\[^\n\r\]*YMMWORD PTR)" } } */
-/* { dg-final { scan-assembler "vcvtdq2ps\[^\n\r\]*ymm" } } */
-/* { dg-final { scan-assembler "vcvtps2pd\[^\n\r\]*(%xmm\[^\n\r\]*%ymm|ymm\[^\n\r\]*xmm)" } } */
-/* { dg-final { scan-assembler "vcvttps2dq\[^\n\r\]*ymm" } } */
-/* { dg-final { scan-assembler "vcvtdq2pd\[^\n\r\]*(%xmm\[^\n\r\]*%ymm|ymm\[^\n\r\]*xmm)" } } */
-/* { dg-final { scan-assembler "vcvtpd2ps(y\[^\n\r\]*%xmm|\[^\n\r\]*xmm\[^\n\r\]*YMMWORD PTR)" } } */
+/* { dg-final { scan-assembler "vcvttpd2dq" } } */
+/* { dg-final { scan-assembler "vcvtdq2ps" } } */
+/* { dg-final { scan-assembler "vcvtps2pd" } } */
+/* { dg-final { scan-assembler "vcvttps2dq" } } */
+/* { dg-final { scan-assembler "vcvtdq2pd" } } */
+/* { dg-final { scan-assembler "vcvtpd2ps" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-pr87138.c b/gcc/testsuite/gcc.target/i386/avx512bw-pr87138.c
new file mode 100644
index 0000000..46cecb9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-pr87138.c
@@ -0,0 +1,29 @@
+/* PR middle-end/87138 */
+/* { dg-do run { target int128 } } */
+/* { dg-options "-O -fno-tree-fre -mavx512bw -mtune=k8" } */
+/* { dg-require-effective-target avx512bw } */
+
+#include "avx512bw-check.h"
+
+typedef int U __attribute__ ((vector_size (64)));
+typedef __int128 V __attribute__ ((vector_size (64)));
+V g, i;
+
+static inline void
+foo (unsigned h, V j, U k, V n)
+{
+ k /= h;
+ __builtin_memmove (&h, &n, 1);
+ n[j[1]] *= 0x7FFFFFFFFFFFFFFF;
+ j[k[5]] = 0;
+ g = n;
+ i = h + j + n;
+}
+
+void
+avx512bw_test ()
+{
+ foo (~0, (V) { }, (U) { 5 }, (V) { 3 });
+ if (g[0] != (__int128) 3 * 0x7FFFFFFFFFFFFFFF)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
index 7d396a3..0cf8dae 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
@@ -19,4 +19,3 @@ male_indirect_jump (long offset)
/* { dg-final { scan-assembler-not "push(?:l|q)\[ \t\]*_?dispatch" } } */
/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
/* { dg-final { scan-assembler-not "__x86_indirect_thunk\n" } } */
-/* { dg-final { scan-assembler-not "__x86_indirect_thunk_bnd\n" } } */
diff --git a/gcc/testsuite/gcc.target/i386/mpx.c b/gcc/testsuite/gcc.target/i386/mpx.c
index f152ae9..2be96d4 100644
--- a/gcc/testsuite/gcc.target/i386/mpx.c
+++ b/gcc/testsuite/gcc.target/i386/mpx.c
@@ -1,3 +1,3 @@
/* { dg-do compile } */
// { dg-options "-mmpx" }
-// { dg-warning "deprecated command line option .-mmpx." "" { target *-*-* } 0 }
+// { dg-warning "switch .-mmpx. is no longer supported" "" { target *-*-* } 0 }
diff --git a/gcc/testsuite/gcc.target/i386/pr45352-2.c b/gcc/testsuite/gcc.target/i386/pr45352-2.c
index 47e428c..216c506 100644
--- a/gcc/testsuite/gcc.target/i386/pr45352-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr45352-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O1 -mtune=amdfam10 -fexpensive-optimizations -fgcse -foptimize-register-move -freorder-blocks -fschedule-insns2 -funswitch-loops -fgcse-las -fselective-scheduling2 -fsel-sched-pipelining -funroll-all-loops" } */
+/* { dg-options "-O1 -mtune=amdfam10 -fexpensive-optimizations -fgcse -freorder-blocks -fschedule-insns2 -funswitch-loops -fgcse-las -fselective-scheduling2 -fsel-sched-pipelining -funroll-all-loops" } */
typedef char uint8_t;
typedef int uint32_t;
diff --git a/gcc/testsuite/gcc.target/i386/pr82418.c b/gcc/testsuite/gcc.target/i386/pr82418.c
new file mode 100644
index 0000000..95a506d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82418.c
@@ -0,0 +1,10 @@
+/* PR target/82418 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "imul\[^\n\r]*1374389535" } } */
+
+unsigned
+f1(unsigned x)
+{
+ return x / 100;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr82699-1.c b/gcc/testsuite/gcc.target/i386/pr82699-1.c
new file mode 100644
index 0000000..272d079
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82699-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fno-pic -fcf-protection -pg -fasynchronous-unwind-tables" } */
+/* { dg-final { scan-assembler-times {\t\.cfi_startproc\n\tendbr} 1 } } */
+
+extern int bar (int);
+
+int
+foo (int i)
+{
+ return bar (i);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr82699-2.c b/gcc/testsuite/gcc.target/i386/pr82699-2.c
new file mode 100644
index 0000000..07a4ccb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82699-2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fno-pic -fcf-protection -pg -mfentry -fasynchronous-unwind-tables" } */
+/* { dg-final { scan-assembler-times {\t\.cfi_startproc\n\tendbr} 1 } } */
+
+extern int bar (int);
+
+int
+foo (int i)
+{
+ return bar (i);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr82699-3.c b/gcc/testsuite/gcc.target/i386/pr82699-3.c
new file mode 100644
index 0000000..08fa0e7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82699-3.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fcf-protection -pg -fasynchronous-unwind-tables" } */
+/* { dg-final { scan-assembler-times {\t\.cfi_startproc\n\tendbr} 1 } } */
+
+extern int bar (int);
+
+int
+foo (int i)
+{
+ return bar (i);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr82699-4.c b/gcc/testsuite/gcc.target/i386/pr82699-4.c
new file mode 100644
index 0000000..3cc03db
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82699-4.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
+/* { dg-options "-O2 -fpic -fcf-protection -pg -mfentry -fasynchronous-unwind-tables" } */
+/* { dg-final { scan-assembler-times {\t\.cfi_startproc\n\tendbr} 1 } } */
+
+extern int bar (int);
+
+int
+foo (int i)
+{
+ return bar (i);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr82699-5.c b/gcc/testsuite/gcc.target/i386/pr82699-5.c
new file mode 100644
index 0000000..e0fe018
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82699-5.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fcf-protection -mfentry -fasynchronous-unwind-tables" } */
+/* { dg-final { scan-assembler-times {\t\.cfi_startproc\n\tendbr} 1 } } */
+
+extern int bar (int);
+
+int
+foo (int i)
+{
+ return bar (i);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr82699-6.c b/gcc/testsuite/gcc.target/i386/pr82699-6.c
new file mode 100644
index 0000000..cacf0ab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82699-6.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fcf-protection -pg -mfentry -mrecord-mcount -mnop-mcount -fasynchronous-unwind-tables" } */
+/* { dg-final { scan-assembler-times {\t\.cfi_startproc\n\tendbr} 1 } } */
+
+extern int bar (int);
+
+int
+foo (int i)
+{
+ return bar (i);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr82853-1.c b/gcc/testsuite/gcc.target/i386/pr82853-1.c
new file mode 100644
index 0000000..822fe77
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82853-1.c
@@ -0,0 +1,15 @@
+/* PR middle-end/82853 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-bmi2 -mtune=generic" } */
+/* { dg-final { scan-assembler-times "mul\[lq]\t" 7 } } */
+/* { dg-final { scan-assembler-not "div\[lq]\t" } } */
+/* { dg-final { scan-assembler-not "lea\[lq]\t\[^\n\r]*,\[^\n\r]*,2\\)" } } */
+
+unsigned f1 (unsigned x) { return (x % 679U) == 0; }
+unsigned f2 (unsigned x) { return (x % 1738U) == 0; }
+void bar (void);
+void f3 (unsigned x) { if (x % 3 == 0) bar (); }
+void f4 (unsigned x) { if (x % 3 == 1) bar (); }
+void f5 (unsigned x) { if (x % 3 == 2) bar (); }
+int f6 (int x) { return x % 3 == 0; }
+int f7 (int x) { return x % 6 == 0; }
diff --git a/gcc/testsuite/gcc.target/i386/pr82853-2.c b/gcc/testsuite/gcc.target/i386/pr82853-2.c
new file mode 100644
index 0000000..0c19e9d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82853-2.c
@@ -0,0 +1,7 @@
+/* PR middle-end/82853 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-bmi2 -mtune=generic" } */
+/* { dg-final { scan-assembler-times "mul\[lq]\t" 2 } } */
+/* { dg-final { scan-assembler-not "div\[lq]\t" } } */
+
+unsigned f1 (unsigned x, unsigned *y) { *y = x / 679U; return (x % 679U) == 0; }
diff --git a/gcc/testsuite/gcc.target/i386/pr83554.c b/gcc/testsuite/gcc.target/i386/pr83554.c
index 63ab366..6159715 100644
--- a/gcc/testsuite/gcc.target/i386/pr83554.c
+++ b/gcc/testsuite/gcc.target/i386/pr83554.c
@@ -1,6 +1,6 @@
/* PR target/83554 */
/* { dg-do compile { target int128 } } */
-/* { dg-options "-Os -mmitigate-rop" } */
+/* { dg-options "-Os" } */
unsigned a;
unsigned __int128
diff --git a/gcc/testsuite/gcc.target/i386/pr86386.c b/gcc/testsuite/gcc.target/i386/pr86386.c
new file mode 100644
index 0000000..a67cf45
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr86386.c
@@ -0,0 +1,26 @@
+/* PR target/86386 */
+/* { dg-do run { target { avx_runtime && int128 } } } */
+/* { dg-options "-Os -fno-tree-dce -mstringop-strategy=vector_loop -mavx" } */
+
+unsigned c, d, e, f;
+
+unsigned __attribute__((noipa))
+foo (unsigned char g, unsigned short h, unsigned i, unsigned long long j,
+ unsigned char k, unsigned short l, unsigned m, unsigned __int128 n)
+{
+ __builtin_memset (&e, 0, 3);
+ n <<= m;
+ __builtin_memcpy (&m, 2 + (char *) &n, 1);
+ m >>= 0;
+ d ^= __builtin_mul_overflow (l, n, &m);
+ return m;
+}
+
+int
+main ()
+{
+ unsigned __int128 x = foo (0, 0, 0, 0, 0, 4, 1, 3);
+ if (x != 24)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr87065.c b/gcc/testsuite/gcc.target/i386/pr87065.c
new file mode 100644
index 0000000..7ee0f0f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr87065.c
@@ -0,0 +1,22 @@
+/* PR rtl-optimization/87065 */
+/* { dg-do compile } */
+/* { dg-options "-O3 -mxop -mprefer-vector-width=128" } */
+
+int a, c, d, e;
+short *b;
+
+void
+foo (void)
+{
+ short *g = b;
+ int h = 1;
+ unsigned i;
+ for (; h <= 1; h++)
+ g = (short *) &c;
+ for (; c; c++)
+ {
+ for (; i <= 1; i++)
+ ;
+ a ^= (a > 0 <= i) + ((e += d) == 0 ?: (*g = 8));
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr87198.c b/gcc/testsuite/gcc.target/i386/pr87198.c
new file mode 100644
index 0000000..7a52e7c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr87198.c
@@ -0,0 +1,13 @@
+/* PR target/87198 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mxsavec -mno-xsave" } */
+
+#include <x86intrin.h>
+
+void
+test_xsavec (void *__A, long long __B)
+{
+ _xsavec (__A, __B);
+}
+
+/* { dg-error "target specific option mismatch" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/i386/pr87290.c b/gcc/testsuite/gcc.target/i386/pr87290.c
new file mode 100644
index 0000000..c61fe81
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr87290.c
@@ -0,0 +1,34 @@
+/* PR middle-end/87290 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -masm=att" } */
+/* { dg-final { scan-assembler-times "and\[^\n\r]*-2147483633" 4 } } */
+/* { dg-final { scan-assembler-times "\t\\\$13," 2 } } */
+/* { dg-final { scan-assembler-times "\t\\\$-2147483645," 2 } } */
+
+void f0 (void);
+
+int
+f1 (int x)
+{
+ return x % 16 == 13;
+}
+
+int
+f2 (int x)
+{
+ return x % 16 == -13;
+}
+
+void
+f3 (int x)
+{
+ if (x % 16 == 13)
+ f0 ();
+}
+
+void
+f4 (int x)
+{
+ if (x % 16 == -13)
+ f0 ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/rop1.c b/gcc/testsuite/gcc.target/i386/rop1.c
deleted file mode 100644
index 0b37267..0000000
--- a/gcc/testsuite/gcc.target/i386/rop1.c
+++ /dev/null
@@ -1,7 +0,0 @@
-/* { dg-do compile } */
-/* { dg-require-effective-target lp64 } */
-/* { dg-options "-mcmodel=medium -mmitigate-rop" } */
-void
-foo (void)
-{
-}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-movs.c b/gcc/testsuite/gcc.target/i386/sse2-movs.c
new file mode 100644
index 0000000..79f486c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-movs.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2" } */
+/* { dg-require-effective-target sse2 } */
+/* { dg-final { scan-assembler "movss" } } */
+/* { dg-final { scan-assembler "movsd" } } */
+/* { dg-final { scan-assembler-not "unpcklps" } } */
+/* { dg-final { scan-assembler-not "shufps" } } */
+/* { dg-final { scan-assembler-not "shufpd" } } */
+
+typedef float v4sf __attribute__ ((vector_size (16)));
+typedef double v2df __attribute__ ((vector_size (16)));
+
+v4sf movss(v4sf a, v4sf b)
+{
+ return (v4sf){b[0],a[1],a[2],a[3]};
+}
+
+v2df movsd(v2df a, v2df b)
+{
+ return (v2df){b[0],a[1]};
+}
diff --git a/gcc/testsuite/gcc.target/i386/strcmpopt_6.c b/gcc/testsuite/gcc.target/i386/strcmpopt_6.c
new file mode 100644
index 0000000..4c6de02
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/strcmpopt_6.c
@@ -0,0 +1,36 @@
+/* When the specified length exceeds one of the arguments of the call to memcmp,
+ the call to memcmp should NOT be inlined. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-stringop-overflow" } */
+
+typedef struct { char s[8]; int x; } S;
+
+__attribute__ ((noinline)) int
+f1 (S * s)
+{
+ int result = 0;
+ result += __builtin_memcmp (s->s, "a", 3);
+ return result;
+}
+
+__attribute__ ((noinline)) int
+f2 (char *p)
+{
+ int result = 0;
+ result += __builtin_memcmp (p, "a", 3);
+ return result;
+}
+
+int main (void)
+{
+ S ss = {{'a','b','c'}, 2};
+ char *s = "abcd";
+
+ if (f1 (&ss) < 0 || f2 (s) < 0)
+ __builtin_abort ();
+
+ return 0;
+
+}
+
+/* { dg-final { scan-assembler-times "memcmp" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/zee.c b/gcc/testsuite/gcc.target/i386/zee.c
index 920e056..608f7c9 100644
--- a/gcc/testsuite/gcc.target/i386/zee.c
+++ b/gcc/testsuite/gcc.target/i386/zee.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target { ! ia32 } } } */
-/* { dg-options "-O2 -fzee" } */
+/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-not "mov\[\\t \]+\(%\[\^,\]+\),\[\\t \]*\\1" } } */
int mask[100];
int foo(unsigned x)
diff --git a/gcc/testsuite/gcc.target/m68k/tls-dimode.c b/gcc/testsuite/gcc.target/m68k/tls-dimode.c
new file mode 100644
index 0000000..0bc59cd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/m68k/tls-dimode.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { ! *-linux-* } } */
+/* { dg-options "-w -O2" } */
+
+__thread long long ti;
+
+void f (void)
+{
+ ti++;
+}
+
+void g (long long x)
+{
+ ti = x;
+}
diff --git a/gcc/testsuite/gcc.target/msp430/pr86662.c b/gcc/testsuite/gcc.target/msp430/pr86662.c
new file mode 100644
index 0000000..1144b3e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/pr86662.c
@@ -0,0 +1,13 @@
+/* PR/86662 */
+
+/* { dg-do link } */
+/* -nostdlib prevents link errors due to mismatched code models for
+ libgloss objects. */
+/* { dg-options "-mlarge -flto -nostdlib" } */
+/* { dg-skip-if "" { *-*-* } { "-mcpu=msp430" } } */
+
+int main(void)
+{
+ __int20 n = 5;
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/nvptx/atomic_fetch-1.c b/gcc/testsuite/gcc.target/nvptx/atomic_fetch-1.c
new file mode 100644
index 0000000..c637caa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/atomic_fetch-1.c
@@ -0,0 +1,24 @@
+/* Test the nvptx atomic instructions for __atomic_fetch_OP for SM_35
+ targets. */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -misa=sm_35" } */
+
+int
+main()
+{
+ unsigned long long a = ~0;
+ unsigned b = 0xa;
+
+ __atomic_fetch_add (&a, b, 0);
+ __atomic_fetch_and (&a, b, 0);
+ __atomic_fetch_or (&a, b, 0);
+ __atomic_fetch_xor (&a, b, 0);
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "atom.add.u64" } } */
+/* { dg-final { scan-assembler "atom.b64.and" } } */
+/* { dg-final { scan-assembler "atom.b64.or" } } */
+/* { dg-final { scan-assembler "atom.b64.xor" } } */
diff --git a/gcc/testsuite/gcc.target/nvptx/atomic_fetch-2.c b/gcc/testsuite/gcc.target/nvptx/atomic_fetch-2.c
new file mode 100644
index 0000000..1d35a17
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/atomic_fetch-2.c
@@ -0,0 +1,24 @@
+/* Test the nvptx atomic instructions for __atomic_fetch_OP for SM_30
+ targets. */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -misa=sm_30" } */
+
+int
+main()
+{
+ unsigned long long a = ~0;
+ unsigned b = 0xa;
+
+ __atomic_fetch_add (&a, b, 0);
+ __atomic_fetch_and (&a, b, 0);
+ __atomic_fetch_or (&a, b, 0);
+ __atomic_fetch_xor (&a, b, 0);
+
+ return a;
+}
+
+/* { dg-final { scan-assembler-not "atom.b64.add" } } */
+/* { dg-final { scan-assembler-not "atom.b64.and" } } */
+/* { dg-final { scan-assembler-not "atom.b64.or" } } */
+/* { dg-final { scan-assembler-not "atom.b64.xor" } } */
diff --git a/gcc/testsuite/gcc.target/nvptx/atomic_fetch-3.c b/gcc/testsuite/gcc.target/nvptx/atomic_fetch-3.c
new file mode 100644
index 0000000..36a83eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/atomic_fetch-3.c
@@ -0,0 +1,24 @@
+/* Test the nvptx atomic instructions for __atomic_fetch_OP for
+ SImode arguments. */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -m32" } */
+
+int
+main()
+{
+ unsigned long a = ~0;
+ unsigned b = 0xa;
+
+ __atomic_fetch_add (&a, b, 0);
+ __atomic_fetch_and (&a, b, 0);
+ __atomic_fetch_or (&a, b, 0);
+ __atomic_fetch_xor (&a, b, 0);
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "atom.add.u32" } } */
+/* { dg-final { scan-assembler "atom.b32.and" } } */
+/* { dg-final { scan-assembler "atom.b32.or" } } */
+/* { dg-final { scan-assembler "atom.b32.xor" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-char.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-char.c
new file mode 100644
index 0000000..d50d073
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-char.c
@@ -0,0 +1,55 @@
+/* Verify that overloaded built-ins for vec_splat with char
+ inputs produce the right code. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-maltivec -O2" } */
+
+#include <altivec.h>
+
+vector bool char testb_0 (vector bool char x) { return vec_splat (x, 0b00000); }
+vector bool char testb_1 (vector bool char x) { return vec_splat (x, 0b00001); }
+vector bool char testb_2 (vector bool char x) { return vec_splat (x, 0b00010); }
+vector bool char testb_4 (vector bool char x) { return vec_splat (x, 0b00100); }
+vector bool char testb_8 (vector bool char x) { return vec_splat (x, 0b01000); }
+vector bool char testb_10 (vector bool char x) { return vec_splat (x, 0b10000); }
+vector bool char testb_1e (vector bool char x) { return vec_splat (x, 0b11110); }
+vector bool char testb_1f (vector bool char x) { return vec_splat (x, 0b11111); }
+
+vector signed char tests_0 (vector signed char x) { return vec_splat (x, 0b00000); }
+vector signed char tests_1 (vector signed char x) { return vec_splat (x, 0b00001); }
+vector signed char tests_2 (vector signed char x) { return vec_splat (x, 0b00010); }
+vector signed char tests_4 (vector signed char x) { return vec_splat (x, 0b00100); }
+vector signed char tests_8 (vector signed char x) { return vec_splat (x, 0b01000); }
+vector signed char tests_10 (vector signed char x) { return vec_splat (x, 0b10000); }
+vector signed char tests_1e (vector signed char x) { return vec_splat (x, 0b11110); }
+vector signed char tests_1f (vector signed char x) { return vec_splat (x, 0b11111); }
+
+vector unsigned char testu_0 (vector unsigned char x) { return vec_splat (x, 0b00000); }
+vector unsigned char testu_1 (vector unsigned char x) { return vec_splat (x, 0b00001); }
+vector unsigned char testu_2 (vector unsigned char x) { return vec_splat (x, 0b00010); }
+vector unsigned char testu_4 (vector unsigned char x) { return vec_splat (x, 0b00100); }
+vector unsigned char testu_8 (vector unsigned char x) { return vec_splat (x, 0b01000); }
+vector unsigned char testu_10 (vector unsigned char x) { return vec_splat (x, 0b10000); }
+vector unsigned char testu_1e (vector unsigned char x) { return vec_splat (x, 0b11110); }
+vector unsigned char testu_1f (vector unsigned char x) { return vec_splat (x, 0b11111); }
+
+/* Similar tests as above, but the source vector is a known constant. */
+const vector bool char by = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p'};
+const vector signed char sy = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p'};
+const vector unsigned char uy = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p'};
+
+vector bool char test_bc (vector bool char x) { return vec_splat (by, 0b00010); }
+vector signed char test_sc (vector signed char x) { return vec_splat (sy, 0b00011); }
+vector unsigned char test_uc (vector unsigned char x) { return vec_splat (uy, 0b00110); }
+
+/* Similar tests as above, mask is greater than number of elements in the
+ source vector. */
+vector bool char test_obc (vector bool char x) { return vec_splat (by, 0b10010); }
+vector signed char test_osc (vector signed char x) { return vec_splat (sy, 0b10011); }
+vector unsigned char test_ouc (vector unsigned char x) { return vec_splat (uy, 0b10110); }
+
+// vec_splat() using variable vectors should generate the vspltb instruction.
+/* { dg-final { scan-assembler-times "vspltb" 24 } } */
+// vec_splat() using a constant vector should generate a load.
+/* { dg-final { scan-assembler-times {\mlvx\M|\mlxvw4x\M} 6 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-floatdouble.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-floatdouble.c
new file mode 100644
index 0000000..fd74002
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-floatdouble.c
@@ -0,0 +1,46 @@
+/* Verify that overloaded built-ins for vec_splat with float and
+ double inputs produce the right code. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-mvsx -O2" } */
+
+#include <altivec.h>
+
+vector float testf_00 (vector float x) { return vec_splat (x, 0b00000); }
+vector float testf_01 (vector float x) { return vec_splat (x, 0b00001); }
+vector float testf_02 (vector float x) { return vec_splat (x, 0b00010); }
+vector float testf_04 (vector float x) { return vec_splat (x, 0b00100); }
+vector float testf_08 (vector float x) { return vec_splat (x, 0b01000); }
+vector float testf_0f (vector float x) { return vec_splat (x, 0b01111); }
+vector float testf_10 (vector float x) { return vec_splat (x, 0b10000); }
+vector float testf_1e (vector float x) { return vec_splat (x, 0b11110); }
+vector float testf_1f (vector float x) { return vec_splat (x, 0b11111); }
+
+vector double testd_00 (vector double x) { return vec_splat (x, 0b00000); }
+vector double testd_01 (vector double x) { return vec_splat (x, 0b00001); }
+vector double testd_02 (vector double x) { return vec_splat (x, 0b00010); }
+vector double testd_04 (vector double x) { return vec_splat (x, 0b00100); }
+vector double testd_08 (vector double x) { return vec_splat (x, 0b01000); }
+vector double testd_0f (vector double x) { return vec_splat (x, 0b01111); }
+vector double testd_10 (vector double x) { return vec_splat (x, 0b10000); }
+vector double testd_1e (vector double x) { return vec_splat (x, 0b11110); }
+vector double testd_1f (vector double x) { return vec_splat (x, 0b11111); }
+
+/* Similar tests as above, but the source vector is a known constant. */
+vector float test_fc () { const vector float y = { 7.1, 8.2, 9.3, 10.4}; return vec_splat (y, 0b00010); }
+vector double test_dc () { const vector double y = { 3.0, 5.0 }; return vec_splat (y, 0b00010); }
+
+/* Similar tests as above, mask is greater than number of elements in the
+ source vector. */
+vector float test_ofc () { const vector float y = { 7.1, 8.2, 9.3, 10.4}; return vec_splat (y, 0b10010); }
+vector double test_odc () { const vector double y = { 3.0, 5.0 }; return vec_splat (y, 0b10010); }
+
+/* lvx or lxvd2x for loading of the constants. */
+/* vspltw or xxspltw for non-constants with the float type. */
+/* xxpermdi for non-constants with the double type. */
+
+/* { dg-final { scan-assembler-times {\mlvx\M|\mlxvd2x\M} 4 } } */
+/* { dg-final { scan-assembler-times "vspltw|xxspltw" 9 } } */
+/* { dg-final { scan-assembler-times "xxpermdi" 9 } } */
+
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-int.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-int.c
new file mode 100644
index 0000000..7697853
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-int.c
@@ -0,0 +1,50 @@
+/* Verify that overloaded built-ins for vec_splat with int
+ inputs produce the right code. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-maltivec -O2" } */
+
+#include <altivec.h>
+
+vector bool int testb_0 (vector bool int x) { return vec_splat (x, 0b00000); }
+vector bool int testb_1 (vector bool int x) { return vec_splat (x, 0b00001); }
+vector bool int testb_2 (vector bool int x) { return vec_splat (x, 0b00010); }
+vector bool int testb_4 (vector bool int x) { return vec_splat (x, 0b00100); }
+vector bool int testb_8 (vector bool int x) { return vec_splat (x, 0b01000); }
+vector bool int testb_10 (vector bool int x) { return vec_splat (x, 0b10000); }
+vector bool int testb_1e (vector bool int x) { return vec_splat (x, 0b11110); }
+vector bool int testb_1f (vector bool int x) { return vec_splat (x, 0b11111); }
+
+vector signed int tests_0 (vector signed int x) { return vec_splat (x, 0b00000); }
+vector signed int tests_1 (vector signed int x) { return vec_splat (x, 0b00001); }
+vector signed int tests_2 (vector signed int x) { return vec_splat (x, 0b00010); }
+vector signed int tests_4 (vector signed int x) { return vec_splat (x, 0b00100); }
+vector signed int tests_8 (vector signed int x) { return vec_splat (x, 0b01000); }
+vector signed int tests_10 (vector signed int x) { return vec_splat (x, 0b10000); }
+vector signed int tests_1e (vector signed int x) { return vec_splat (x, 0b11110); }
+vector signed int tests_1f (vector signed int x) { return vec_splat (x, 0b11111); }
+
+vector unsigned int testu_0 (vector unsigned int x) { return vec_splat (x, 0b00000); }
+vector unsigned int testu_1 (vector unsigned int x) { return vec_splat (x, 0b00001); }
+vector unsigned int testu_2 (vector unsigned int x) { return vec_splat (x, 0b00010); }
+vector unsigned int testu_4 (vector unsigned int x) { return vec_splat (x, 0b00100); }
+vector unsigned int testu_8 (vector unsigned int x) { return vec_splat (x, 0b01000); }
+vector unsigned int testu_10 (vector unsigned int x) { return vec_splat (x, 0b10000); }
+vector unsigned int testu_1e (vector unsigned int x) { return vec_splat (x, 0b11110); }
+vector unsigned int testu_1f (vector unsigned int x) { return vec_splat (x, 0b11111); }
+
+/* Similar test as above, but the source vector is a known constant. */
+vector bool int test_bic () { const vector bool int y = { 1,2,3,4}; return vec_splat (y, 0b00010); }
+vector signed int test_sic () { const vector signed int y = { 1,2,3,4}; return vec_splat (y, 0b00010); }
+vector unsigned int test_uic () { const vector unsigned int y = { 1,2,3,4}; return vec_splat (y, 0b00010); }
+
+/* Similar tests as above, mask is greater than number of elements in the
+ source vector. */
+vector bool int test_obic () { const vector bool int y = { 1,2,3,4}; return vec_splat (y, 0b10010); }
+vector signed int test_osic () { const vector signed int y = { 1,2,3,4}; return vec_splat (y, 0b10010); }
+vector unsigned int test_ouic () { const vector unsigned int y = { 1,2,3,4}; return vec_splat (y, 0b10010); }
+
+/* { dg-final { scan-assembler-times "vspltisw" 6 } } */
+/* { dg-final { scan-assembler-times "vspltw|xxspltw" 24 } } */
+
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-longlong.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-longlong.c
new file mode 100644
index 0000000..0720e20
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-longlong.c
@@ -0,0 +1,60 @@
+/* Verify that overloaded built-ins for vec_splat with long long
+ inputs produce the right code. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-mvsx -O2" } */
+
+#include <altivec.h>
+
+vector bool long long testb_00 (vector bool long long x) { return vec_splat (x, 0b00000); }
+vector bool long long testb_01 (vector bool long long x) { return vec_splat (x, 0b00001); }
+vector bool long long testb_02 (vector bool long long x) { return vec_splat (x, 0b00010); }
+vector bool long long testb_04 (vector bool long long x) { return vec_splat (x, 0b00100); }
+vector bool long long testb_08 (vector bool long long x) { return vec_splat (x, 0b01000); }
+vector bool long long testb_10 (vector bool long long x) { return vec_splat (x, 0b10000); }
+vector bool long long testb_1e (vector bool long long x) { return vec_splat (x, 0b11110); }
+vector bool long long testb_1f (vector bool long long x) { return vec_splat (x, 0b11111); }
+
+vector signed long long tests_00 (vector signed long long x) { return vec_splat (x, 0b00000); }
+vector signed long long tests_01 (vector signed long long x) { return vec_splat (x, 0b00001); }
+vector signed long long tests_02 (vector signed long long x) { return vec_splat (x, 0b00010); }
+vector signed long long tests_04 (vector signed long long x) { return vec_splat (x, 0b00100); }
+vector signed long long tests_08 (vector signed long long x) { return vec_splat (x, 0b01000); }
+vector signed long long tests_10 (vector signed long long x) { return vec_splat (x, 0b10000); }
+vector signed long long tests_1e (vector signed long long x) { return vec_splat (x, 0b11110); }
+vector signed long long tests_1f (vector signed long long x) { return vec_splat (x, 0b11111); }
+
+vector unsigned long long testu_00 (vector unsigned long long x) { return vec_splat (x, 0b00000); }
+vector unsigned long long testu_01 (vector unsigned long long x) { return vec_splat (x, 0b00001); }
+vector unsigned long long testu_02 (vector unsigned long long x) { return vec_splat (x, 0b00010); }
+vector unsigned long long testu_04 (vector unsigned long long x) { return vec_splat (x, 0b00100); }
+vector unsigned long long testu_08 (vector unsigned long long x) { return vec_splat (x, 0b01000); }
+vector unsigned long long testu_10 (vector unsigned long long x) { return vec_splat (x, 0b10000); }
+vector unsigned long long testu_1e (vector unsigned long long x) { return vec_splat (x, 0b11110); }
+vector unsigned long long testu_1f (vector unsigned long long x) { return vec_splat (x, 0b11111); }
+
+/* Similar test as above, but the source vector is a known constant. */
+vector bool long long test_bll () { const vector bool long long y = {12, 23}; return vec_splat (y, 0b00010); }
+vector signed long long test_sll () { const vector signed long long y = {34, 45}; return vec_splat (y, 0b00010); }
+vector unsigned long long test_ull () { const vector unsigned long long y = {56, 67}; return vec_splat (y, 0b00010); }
+
+/* Similar tests as above, mask is greater than number of elements in the
+ source vector. */
+vector bool long long test_obll () { const vector bool long long y = {12, 23}; return vec_splat (y, 0b10010); }
+vector signed long long test_osll () { const vector signed long long y = {34, 45}; return vec_splat (y, 0b10010); }
+vector unsigned long long test_oull () { const vector unsigned long long y = {56, 67}; return vec_splat (y, 0b10010); }
+
+/* lvx for the initialization with known constants. */
+/* { dg-final { scan-assembler-times {\mlvx\M|\mlxvd2x\M} 6 } } */
+
+/* xxpermdi for vec_splat of long long vectors.
+ At the time of this writing, the number of xxpermdi instructions
+ generated could be 24 or 26 or 27, ultimately depending on the
+ platform and whether or not folding is enabled.
+ Roughly:
+ 24 occurrences on older targets (power5) regardless of folding state.
+ 26 occurrences with gimple folding enabled (through power9).
+ 27 occurrences with gimple folding disabled (through power9).
+ So, ensure we have at least one hit. */
+/* { dg-final { scan-assembler "xxpermdi" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-pixel.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-pixel.c
new file mode 100644
index 0000000..7170588
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-pixel.c
@@ -0,0 +1,27 @@
+/* Verify that overloaded built-ins for vec_splat with pixel
+ inputs produce the right code. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-mvsx -O2" } */
+
+#include <altivec.h>
+
+vector pixel test1_00 (vector pixel x) { return vec_splat (x, 0b00000); }
+vector pixel test1_01 (vector pixel x) { return vec_splat (x, 0b00001); }
+vector pixel test1_02 (vector pixel x) { return vec_splat (x, 0b00010); }
+vector pixel test1_04 (vector pixel x) { return vec_splat (x, 0b00100); }
+vector pixel test1_08 (vector pixel x) { return vec_splat (x, 0b01000); }
+vector pixel test1_10 (vector pixel x) { return vec_splat (x, 0b10000); }
+vector pixel test1_1e (vector pixel x) { return vec_splat (x, 0b11110); }
+vector pixel test1_1f (vector pixel x) { return vec_splat (x, 0b11111); }
+
+/* Similar test as above, but the source vector is a known constant. */
+vector pixel test_p () { const vector pixel y = { 1,2,3,4}; return vec_splat (y, 0b00010); }
+
+/* Similar tests as above, mask is greater than number of elements in the
+ source vector. */
+vector pixel test_op () { const vector pixel y = { 1,2,3,4}; return vec_splat (y, 0b10010); }
+
+/* { dg-final { scan-assembler-times "vspltish" 2 } } */
+/* { dg-final { scan-assembler-times "vsplth" 8 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-short.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-short.c
new file mode 100644
index 0000000..96c553f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-short.c
@@ -0,0 +1,49 @@
+/* Verify that overloaded built-ins for vec_splat with short
+ inputs produce the right results. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-maltivec -O2" } */
+
+#include <altivec.h>
+
+vector bool short testb_00 (vector bool short x) { return vec_splat (x, 0b00000); }
+vector bool short testb_01 (vector bool short x) { return vec_splat (x, 0b00001); }
+vector bool short testb_02 (vector bool short x) { return vec_splat (x, 0b00010); }
+vector bool short testb_04 (vector bool short x) { return vec_splat (x, 0b00100); }
+vector bool short testb_08 (vector bool short x) { return vec_splat (x, 0b01000); }
+vector bool short testb_10 (vector bool short x) { return vec_splat (x, 0b10000); }
+vector bool short testb_1e (vector bool short x) { return vec_splat (x, 0b11110); }
+vector bool short testb_1f (vector bool short x) { return vec_splat (x, 0b11111); }
+
+vector signed short tests_00 (vector signed short x) { return vec_splat (x, 0b00000); }
+vector signed short tests_01 (vector signed short x) { return vec_splat (x, 0b00001); }
+vector signed short tests_02 (vector signed short x) { return vec_splat (x, 0b00010); }
+vector signed short tests_04 (vector signed short x) { return vec_splat (x, 0b00100); }
+vector signed short tests_08 (vector signed short x) { return vec_splat (x, 0b01000); }
+vector signed short tests_10 (vector signed short x) { return vec_splat (x, 0b10000); }
+vector signed short tests_1e (vector signed short x) { return vec_splat (x, 0b11110); }
+vector signed short tests_1f (vector signed short x) { return vec_splat (x, 0b11111); }
+
+vector unsigned short testu_00 (vector unsigned short x) { return vec_splat (x, 0b00000); }
+vector unsigned short testu_01 (vector unsigned short x) { return vec_splat (x, 0b00001); }
+vector unsigned short testu_02 (vector unsigned short x) { return vec_splat (x, 0b00010); }
+vector unsigned short testu_04 (vector unsigned short x) { return vec_splat (x, 0b00100); }
+vector unsigned short testu_08 (vector unsigned short x) { return vec_splat (x, 0b01000); }
+vector unsigned short testu_10 (vector unsigned short x) { return vec_splat (x, 0b10000); }
+vector unsigned short testu_1e (vector unsigned short x) { return vec_splat (x, 0b11110); }
+vector unsigned short testu_1f (vector unsigned short x) { return vec_splat (x, 0b11111); }
+
+/* Similar test as above, but the source vector is a known constant. */
+vector bool short test_bs () { const vector bool short y = {1, 2, 3, 4, 5, 6, 7, 8}; return vec_splat (y, 0b00010); }
+vector signed short test_ss () { const vector signed short y = {1, 2, 3, 4, 5, 6, 7, 8}; return vec_splat (y, 0b00010); }
+vector unsigned short test_us () { const vector unsigned short y = {1, 2, 3, 4, 5, 6, 7, 8}; return vec_splat (y, 0b00010); }
+
+/* Similar tests as above, mask is greater than number of elements in the
+ source vector. */
+vector bool short test_obs () { const vector bool short y = {1, 2, 3, 4, 5, 6, 7, 8}; return vec_splat (y, 0b10010); }
+vector signed short test_oss () { const vector signed short y = {1, 2, 3, 4, 5, 6, 7, 8}; return vec_splat (y, 0b10010); }
+vector unsigned short test_ous () { const vector unsigned short y = {1, 2, 3, 4, 5, 6, 7, 8}; return vec_splat (y, 0b10010); }
+
+/* { dg-final { scan-assembler-times "vspltish" 6 } } */
+/* { dg-final { scan-assembler-times "vsplth" 24 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/p8-vec-xl-xst-v2.c b/gcc/testsuite/gcc.target/powerpc/p8-vec-xl-xst-v2.c
index cc68ceb..6f48d72 100644
--- a/gcc/testsuite/gcc.target/powerpc/p8-vec-xl-xst-v2.c
+++ b/gcc/testsuite/gcc.target/powerpc/p8-vec-xl-xst-v2.c
@@ -59,6 +59,5 @@ bartle (vector unsigned short x, unsigned short * address)
vec_xst (x, 0, address);
}
-/* { dg-final { scan-assembler-times "lvx" 4 } } */
-/* { dg-final { scan-assembler-times "stvx" 4 } } */
-/* { dg-final { scan-assembler-times "xxpermdi" 0 } } */
+/* { dg-final { scan-assembler-times {\mlxvd2x\M} 4 } } */
+/* { dg-final { scan-assembler-times {\mstxvd2x\M} 4 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr56605.c b/gcc/testsuite/gcc.target/powerpc/pr56605.c
index dc87640..304d6d68 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr56605.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr56605.c
@@ -12,5 +12,5 @@ void foo (short* __restrict sb, int* __restrict ia)
ia[i] = (int) sb[i];
}
-/* { dg-final { scan-rtl-dump-times "\\\(compare:CC \\\(zero_extend:DI \\\(reg:SI" 1 "combine" } } */
+/* { dg-final { scan-rtl-dump-times "\\\(compare:CC \\\((?:and|zero_extend):DI \\\(reg:\[SD\]I" 1 "combine" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr86731-fwrapv-longlong.c b/gcc/testsuite/gcc.target/powerpc/pr86731-fwrapv-longlong.c
new file mode 100644
index 0000000..1269fe6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr86731-fwrapv-longlong.c
@@ -0,0 +1,34 @@
+/* PR86731. Verify that the rs6000 gimple-folding code handles the
+ left shift operation properly. This is a testcase variation that
+ explicitly specifies -fwrapv, which is a condition for the
+ gimple folding of the vec_sl() intrinsic. */
+
+/* specify -mpower8-vector, which provides vec_sl(long long,...) support. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-maltivec -O3 -fwrapv -mpower8-vector " } */
+
+#include <altivec.h>
+
+vector unsigned long long splatu4(void)
+{
+ vector unsigned long long mzero = {-1,-1};
+ return (vector unsigned long long) vec_sl(mzero, mzero);
+}
+
+vector signed long long splats4(void)
+{
+ vector unsigned long long mzero = {-1,-1};
+ return (vector signed long long) vec_sl(mzero, mzero);
+}
+
+/* Codegen will consist of splat and shift instructions for most types.
+ If folding is enabled, the vec_sl tests using vector long long type will
+ generate a lvx instead of a vspltisw+vsld pair. */
+
+/* { dg-final { scan-assembler-times {\mvspltis[bhw]\M} 0 } } */
+/* { dg-final { scan-assembler-times {\mvsl[bhwd]\M} 0 } } */
+/* { dg-final { scan-assembler-times {\mlvx\M|\mlxv\M|\mlxvd2x\M} 2 } } */
+
diff --git a/gcc/testsuite/gcc.target/powerpc/pr86731-fwrapv.c b/gcc/testsuite/gcc.target/powerpc/pr86731-fwrapv.c
new file mode 100644
index 0000000..f312550
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr86731-fwrapv.c
@@ -0,0 +1,63 @@
+/* PR86731. Verify that the rs6000 gimple-folding code handles the
+ left shift operation properly. This is a testcase variation that
+ explicitly specifies -fwrapv, which is a condition for the
+ gimple folding of the vec_sl() intrinsic. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-maltivec -O3 -fwrapv " } */
+
+#include <altivec.h>
+/* original test as reported. */
+vector unsigned int splat(void)
+{
+ vector unsigned int mzero = vec_splat_u32(-1);
+ return (vector unsigned int) vec_sl(mzero, mzero);
+}
+
+/* more testcase variations. */
+vector unsigned char splatu1(void)
+{
+ vector unsigned char mzero = vec_splat_u8(-1);
+ return (vector unsigned char) vec_sl(mzero, mzero);
+}
+
+vector unsigned short splatu2(void)
+{
+ vector unsigned short mzero = vec_splat_u16(-1);
+ return (vector unsigned short) vec_sl(mzero, mzero);
+}
+
+vector unsigned int splatu3(void)
+{
+ vector unsigned int mzero = vec_splat_u32(-1);
+ return (vector unsigned int) vec_sl(mzero, mzero);
+}
+
+vector signed char splats1(void)
+{
+ vector unsigned char mzero = vec_splat_u8(-1);
+ return (vector signed char) vec_sl(mzero, mzero);
+}
+
+vector signed short splats2(void)
+{
+ vector unsigned short mzero = vec_splat_u16(-1);
+ return (vector signed short) vec_sl(mzero, mzero);
+}
+
+vector signed int splats3(void)
+{
+ vector unsigned int mzero = vec_splat_u32(-1);
+ return (vector signed int) vec_sl(mzero, mzero);
+}
+
+/* Codegen will consist of splat and shift instructions.
+ If folding is enabled, the vec_sl tests using vector long long type will
+ generate a lvx instead of a vspltisw+vsld pair. */
+
+/* { dg-final { scan-assembler-times {\mvspltis[bhw]\M|\mxxspltib\M} 7 } } */
+/* { dg-final { scan-assembler-times {\mvsl[bhwd]\M} 7 } } */
+/* { dg-final { scan-assembler-times {\mlvx\M|\mlxvd2x\M} 0 } } */
+
diff --git a/gcc/testsuite/gcc.target/powerpc/pr86731-longlong.c b/gcc/testsuite/gcc.target/powerpc/pr86731-longlong.c
new file mode 100644
index 0000000..b862091
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr86731-longlong.c
@@ -0,0 +1,29 @@
+/* PR86731. Verify that the rs6000 gimple-folding code handles the
+ left shift properly. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-maltivec -O3 -mpower8-vector " } */
+
+#include <altivec.h>
+
+vector unsigned long long splatu4(void)
+{
+ vector unsigned long long mzero = {-1,-1};
+ return (vector unsigned long long) vec_sl(mzero, mzero);
+}
+vector signed long long splats4(void)
+{
+ vector unsigned long long mzero = {-1,-1};
+ return (vector signed long long) vec_sl(mzero, mzero);
+}
+
+/* Codegen will consist of splat and shift instructions for most types.
+ Noted variations: if gimple folding is disabled, or if -fwrapv is not
+ specified, the long long tests will generate a vspltisw+vsld pair,
+ versus generating a single lvx. */
+/* { dg-final { scan-assembler-times {\mvspltis[bhw]\M|\mxxspltib\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mvsl[bhwd]\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mlvx\M} 0 } } */
+
diff --git a/gcc/testsuite/gcc.target/powerpc/pr86731-nogimplefold-longlong.c b/gcc/testsuite/gcc.target/powerpc/pr86731-nogimplefold-longlong.c
new file mode 100644
index 0000000..2c46312
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr86731-nogimplefold-longlong.c
@@ -0,0 +1,32 @@
+/* PR86731. Verify that the rs6000 gimple-folding code handles the
+ left shift operation properly. This is a testcase variation that
+ explicitly disables gimple folding. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-maltivec -O3 -fwrapv -mno-fold-gimple -mpower8-vector " } */
+/* { dg-prune-output "gimple folding of rs6000 builtins has been disabled." } */
+
+
+#include <altivec.h>
+
+vector unsigned long long splatu4(void)
+{
+ vector unsigned long long mzero = {-1,-1};
+ return (vector unsigned long long) vec_sl(mzero, mzero);
+}
+
+vector signed long long splats4(void)
+{
+ vector unsigned long long mzero = {-1,-1};
+ return (vector signed long long) vec_sl(mzero, mzero);
+}
+
+/* Codegen will consist of splat and shift instructions for most types.
+ Noted variations: if gimple folding is disabled, or if -fwrapv is not specified, the
+ long long tests will generate a vspltisw+vsld pair, versus generating a lvx. */
+/* { dg-final { scan-assembler-times {\mvspltis[bhw]\M|\mxxspltib\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mvsl[bhwd]\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mlvx\M} 0 } } */
+
diff --git a/gcc/testsuite/gcc.target/powerpc/pr86731-nogimplefold.c b/gcc/testsuite/gcc.target/powerpc/pr86731-nogimplefold.c
new file mode 100644
index 0000000..d424b0c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr86731-nogimplefold.c
@@ -0,0 +1,63 @@
+/* PR86731. Verify that the rs6000 gimple-folding code handles the
+ left shift operation properly. This is a testcase variation that
+ explicitly disables gimple folding. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-maltivec -O3 -fwrapv -mno-fold-gimple" } */
+/* { dg-prune-output "gimple folding of rs6000 builtins has been disabled." } */
+
+
+#include <altivec.h>
+/* original test as reported. */
+vector unsigned int splat(void)
+{
+ vector unsigned int mzero = vec_splat_u32(-1);
+ return (vector unsigned int) vec_sl(mzero, mzero);
+}
+
+/* more testcase variations. */
+vector unsigned char splatu1(void)
+{
+ vector unsigned char mzero = vec_splat_u8(-1);
+ return (vector unsigned char) vec_sl(mzero, mzero);
+}
+
+vector unsigned short splatu2(void)
+{
+ vector unsigned short mzero = vec_splat_u16(-1);
+ return (vector unsigned short) vec_sl(mzero, mzero);
+}
+
+vector unsigned int splatu3(void)
+{
+ vector unsigned int mzero = vec_splat_u32(-1);
+ return (vector unsigned int) vec_sl(mzero, mzero);
+}
+
+vector signed char splats1(void)
+{
+ vector unsigned char mzero = vec_splat_u8(-1);
+ return (vector signed char) vec_sl(mzero, mzero);
+}
+
+vector signed short splats2(void)
+{
+ vector unsigned short mzero = vec_splat_u16(-1);
+ return (vector signed short) vec_sl(mzero, mzero);
+}
+
+vector signed int splats3(void)
+{
+ vector unsigned int mzero = vec_splat_u32(-1);
+ return (vector signed int) vec_sl(mzero, mzero);
+}
+
+/* Codegen will consist of splat and shift instructions for most types.
+ Noted variations: if gimple folding is disabled, or if -fwrapv is not specified, the
+ long long tests will generate a vspltisw+vsld pair, versus generating a lvx. */
+/* { dg-final { scan-assembler-times {\mvspltis[bhw]\M|\mxxspltib\M} 7 } } */
+/* { dg-final { scan-assembler-times {\mvsl[bhwd]\M} 7 } } */
+/* { dg-final { scan-assembler-times {\mlvx\M} 0 } } */
+
diff --git a/gcc/testsuite/gcc.target/powerpc/pr86731.c b/gcc/testsuite/gcc.target/powerpc/pr86731.c
new file mode 100644
index 0000000..19fefa5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr86731.c
@@ -0,0 +1,61 @@
+/* PR86731. Verify that the rs6000 gimple-folding code handles the
+ left shift properly. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-maltivec -O3" } */
+
+#include <altivec.h>
+/* The original test as reported. */
+vector unsigned int splat(void)
+{
+ vector unsigned int mzero = vec_splat_u32(-1);
+ return (vector unsigned int) vec_sl(mzero, mzero);
+}
+
+/* more testcase variations. */
+vector unsigned char splatu1(void)
+{
+ vector unsigned char mzero = vec_splat_u8(-1);
+ return (vector unsigned char) vec_sl(mzero, mzero);
+}
+
+vector unsigned short splatu2(void)
+{
+ vector unsigned short mzero = vec_splat_u16(-1);
+ return (vector unsigned short) vec_sl(mzero, mzero);
+}
+
+vector unsigned int splatu3(void)
+{
+ vector unsigned int mzero = vec_splat_u32(-1);
+ return (vector unsigned int) vec_sl(mzero, mzero);
+}
+
+vector signed char splats1(void)
+{
+ vector unsigned char mzero = vec_splat_u8(-1);
+ return (vector signed char) vec_sl(mzero, mzero);
+}
+
+vector signed short splats2(void)
+{
+ vector unsigned short mzero = vec_splat_u16(-1);
+ return (vector signed short) vec_sl(mzero, mzero);
+}
+
+vector signed int splats3(void)
+{
+ vector unsigned int mzero = vec_splat_u32(-1);
+ return (vector signed int) vec_sl(mzero, mzero);
+}
+
+/* Codegen will consist of splat and shift instructions for most types.
+ Noted variations: if gimple folding is disabled, or if -fwrapv is not
+ specified, the long long tests will generate a vspltisw+vsld pair,
+ versus generating a single lvx. */
+/* { dg-final { scan-assembler-times {\mvspltis[bhw]\M|\mxxspltib\M} 7 } } */
+/* { dg-final { scan-assembler-times {\mvsl[bhwd]\M} 7 } } */
+/* { dg-final { scan-assembler-times {\mlvx\M} 0 } } */
+
diff --git a/gcc/testsuite/gcc.target/powerpc/pr87033.c b/gcc/testsuite/gcc.target/powerpc/pr87033.c
new file mode 100644
index 0000000..9d62ce7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr87033.c
@@ -0,0 +1,12 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-options "-O2" } */
+
+/* Insure that a LWAX is generated instead of ADD + LWA. LP64 is needed
+ because the LWA and LWAX instructions are only available in 64-bit mode. */
+long func (int *p, unsigned long n)
+{
+ return p[n];
+}
+
+/* { dg-final { scan-assembler {\mlwax\M} } } */
+/* { dg-final { scan-assembler-not {\mlwa\M} } } */
diff --git a/gcc/testsuite/gcc.target/s390/TI-constants-lra.c b/gcc/testsuite/gcc.target/s390/TI-constants-lra.c
new file mode 100644
index 0000000..cc52a62
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/TI-constants-lra.c
@@ -0,0 +1,47 @@
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O3" } */
+
+/* 2x lghi */
+__int128 a() {
+ return 0;
+}
+
+/* 2x lghi */
+__int128 b() {
+ return -1;
+}
+
+/* 2x lghi */
+__int128 c() {
+ return -2;
+}
+
+/* lghi + llilh */
+__int128 d() {
+ return 16000 << 16;
+}
+
+/* lghi + llihf */
+__int128 e() {
+ return (unsigned long long)80000 << 32;
+}
+
+/* lghi + llihf */
+__int128 f() {
+ return (unsigned __int128)80000 << 96;
+}
+
+/* llihf + llihf - this is handled via movti_bigconst pattern */
+__int128 g() {
+ return ((unsigned __int128)80000 << 96) | ((unsigned __int128)80000 << 32);
+}
+
+/* Literal pool */
+__int128 h() {
+ return ((unsigned __int128)80000 << 32) | 1;
+}
+
+/* Literal pool */
+__int128 i() {
+ return (((unsigned __int128)80000 << 32) | 1) << 64;
+}
diff --git a/gcc/testsuite/gcc.target/s390/TI-constants-nolra.c b/gcc/testsuite/gcc.target/s390/TI-constants-nolra.c
new file mode 100644
index 0000000..b9948fc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/TI-constants-nolra.c
@@ -0,0 +1,47 @@
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O3 -mno-lra" } */
+
+/* 2x lghi */
+__int128 a() {
+ return 0;
+}
+
+/* 2x lghi */
+__int128 b() {
+ return -1;
+}
+
+/* 2x lghi */
+__int128 c() {
+ return -2;
+}
+
+/* lghi + llilh */
+__int128 d() {
+ return 16000 << 16;
+}
+
+/* lghi + llihf */
+__int128 e() {
+ return (unsigned long long)80000 << 32;
+}
+
+/* lghi + llihf */
+__int128 f() {
+ return (unsigned __int128)80000 << 96;
+}
+
+/* llihf + llihf - this is handled via movti_bigconst pattern */
+__int128 g() {
+ return ((unsigned __int128)80000 << 96) | ((unsigned __int128)80000 << 32);
+}
+
+/* Literal pool */
+__int128 h() {
+ return ((unsigned __int128)80000 << 32) | 1;
+}
+
+/* Literal pool */
+__int128 i() {
+ return (((unsigned __int128)80000 << 32) | 1) << 64;
+}
diff --git a/gcc/testsuite/gcc.target/s390/dfp_to_bfp_rounding.c b/gcc/testsuite/gcc.target/s390/dfp_to_bfp_rounding.c
new file mode 100644
index 0000000..9a32abf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/dfp_to_bfp_rounding.c
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -march=z10" } */
+
+/* According to IEEE 754 2008 4.3 Conversion operations between
+ different radixes must use the rounding mode of the target radix.
+ On S/390 this means passing the right value in GPR0 to PFPO
+ instruction. */
+
+#include <fenv.h>
+
+double __attribute__((noclone,noinline))
+convert (_Decimal64 in)
+{
+ return (double)in;
+}
+
+int
+main ()
+{
+ fesetround (FE_UPWARD);
+
+ if (convert (1e-325DD) != __DBL_DENORM_MIN__)
+ __builtin_abort ();
+
+ fesetround (FE_DOWNWARD);
+
+ if (convert (-1e-325DD) != -__DBL_DENORM_MIN__)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-8.c b/gcc/testsuite/gcc.target/s390/hotpatch-8.c
deleted file mode 100644
index a2fb83f..0000000
--- a/gcc/testsuite/gcc.target/s390/hotpatch-8.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Functional tests for the function hotpatching feature. */
-
-/* { dg-do compile { target { ! lp64 } } } */
-/* { dg-options "-mesa -march=g5 -Wno-deprecated -mhotpatch=0,3" } */
-/* { dg-skip-if "" { *-*-* } { "*" } { "-O*" } } */
-
-#include <stdio.h>
-
-void hp1(void)
-{
- printf("hello, world!\n");
-}
-
-/* Check number of occurences of certain instructions. */
-/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
-/* { dg-final { scan-assembler "^\[^.\].*:\n.*post-label.*(3 halfwords).*\n\(\(.L.*:\n\)\|\(\[\[:space:\]\]*.cfi_.*\n\)\)*\[\[:space:\]\]*nop\t0" } } */
-/* { dg-final { scan-assembler-times "nopr\t%r0" 1 } } */
-/* { dg-final { scan-assembler-times "nop\t0" 1 } } */
-/* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
-/* { dg-final { scan-assembler-not "alignment for hotpatch" } } */
diff --git a/gcc/testsuite/gcc.target/s390/hotpatch-9.c b/gcc/testsuite/gcc.target/s390/hotpatch-9.c
deleted file mode 100644
index 34fae55..0000000
--- a/gcc/testsuite/gcc.target/s390/hotpatch-9.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Functional tests for the function hotpatching feature. */
-
-/* { dg-do compile { target { ! lp64 } } } */
-/* { dg-options "-mesa -march=g5 -Wno-deprecated -mhotpatch=0,4" } */
-/* { dg-skip-if "" { *-*-* } { "*" } { "-O*" } } */
-
-#include <stdio.h>
-
-void hp1(void)
-{
- printf("hello, world!\n");
-}
-
-/* Check number of occurences of certain instructions. */
-/* { dg-final { scan-assembler-not "pre-label NOPs" } } */
-/* { dg-final { scan-assembler "^\[^.\].*:\n.*post-label.*(4 halfwords).*\n\(\(.L.*:\n\)\|\(\[\[:space:\]\]*.cfi_.*\n\)\)*\[\[:space:\]\]*nop\t0" } } */
-/* { dg-final { scan-assembler-not "nopr\t%r0" } } */
-/* { dg-final { scan-assembler-times "nop\t0" 2 } } */
-/* { dg-final { scan-assembler-not "brcl\t0, 0" } } */
diff --git a/gcc/testsuite/gcc.target/s390/memset-1.c b/gcc/testsuite/gcc.target/s390/memset-1.c
index 7b43b97c..3e201df 100644
--- a/gcc/testsuite/gcc.target/s390/memset-1.c
+++ b/gcc/testsuite/gcc.target/s390/memset-1.c
@@ -2,16 +2,23 @@
without loop statements. */
/* { dg-do compile } */
-/* { dg-options "-O3 -mzarch" } */
+/* { dg-options "-O3 -mzarch -march=z13" } */
-/* 1 mvc */
+/* 1 stc */
+void
+*memset0(void *s, int c)
+{
+ return __builtin_memset (s, c, 1);
+}
+
+/* 1 stc 1 mvc */
void
*memset1(void *s, int c)
{
return __builtin_memset (s, c, 42);
}
-/* 3 mvc */
+/* 3 stc 3 mvc */
void
*memset2(void *s, int c)
{
@@ -25,55 +32,62 @@ void
return __builtin_memset (s, c, 0);
}
-/* mvc */
+/* 1 stc 1 mvc */
void
*memset4(void *s, int c)
{
return __builtin_memset (s, c, 256);
}
-/* 2 mvc */
+/* 2 stc 2 mvc */
void
*memset5(void *s, int c)
{
return __builtin_memset (s, c, 512);
}
-/* still 2 mvc through the additional first byte */
+/* 2 stc 2 mvc - still due to the stc bytes */
void
*memset6(void *s, int c)
{
return __builtin_memset (s, c, 514);
}
-/* 3 mvc */
+/* 3 stc 2 mvc */
void
*memset7(void *s, int c)
{
return __builtin_memset (s, c, 515);
}
-/* still 3 mvc through the additional first byte */
+/* 4 stc 4 mvc - 4 * 256 + 4 stc bytes */
void
*memset8(void *s, int c)
{
- return __builtin_memset (s, c, 771);
+ return __builtin_memset (s, c, 1028);
}
-/* Use mvc loop: 2 mvc */
+/* 2 stc 1 pfd 2 mvc - start using mvc loop */
void
*memset9(void *s, int c)
{
- return __builtin_memset (s, c, 772);
+ return __builtin_memset (s, c, 1029);
}
-/* 3 mvc with displacement overflow after the first */
+/* 2 stc 1 stcy 3 mvc - displacement overflow after the first */
void
*memset10(void *s, int c)
{
return __builtin_memset ((char*)s + 4000, c, 700);
}
+/* 1 mvi */
+void
+*clrmem0(void *s)
+{
+ return __builtin_memset (s, 0, 1);
+}
+
/* 1 xc */
void
*clrmem1(void *s)
@@ -109,26 +123,55 @@ void
return __builtin_memset (s, 0, 512);
}
-/* 3 xc */
+/* 4 xc */
void
*clrmem6(void *s)
{
- return __builtin_memset (s, 0, 768);
+ return __builtin_memset (s, 0, 1024);
}
-/* start using xc loop */
+/* 2 xc - start using xc loop*/
void
*clrmem7(void *s)
{
+ return __builtin_memset (s, 0, 1025);
+}
+
+/* 5 xc - on z10 PFD would be used in the loop body so the unrolled
+ variant would still be shorter. */
+__attribute__ ((target("tune=z10")))
+void
+*clrmem7_z10(void *s)
+{
+ return __builtin_memset (s, 0, 1025);
+}
+
+/* 5 xc */
+__attribute__ ((target("tune=z10")))
+void
+*clrmem8_z10(void *s)
+{
+ return __builtin_memset (s, 0, 1280);
+}
+
+/* 1 pfd 2 xc - start using xc loop also on z10 */
+__attribute__ ((target("tune=z10")))
+void
+*clrmem9_z10(void *s)
+{
return __builtin_memset (s, 0, 1281);
}
-/* 3 xc with displacement overflow after the first */
+/* 3 xc - displacement overflow after the first */
void
-*clrmem8(void *s)
+*clrmem10(void *s)
{
return __builtin_memset (s + 4000, 0, 700);
}
-/* { dg-final { scan-assembler-times "mvc" 19 } } */
-/* { dg-final { scan-assembler-times "xc" 15 } } */
+/* { dg-final { scan-assembler-times "mvi\\s" 1 } } */
+/* { dg-final { scan-assembler-times "mvc\\s" 20 } } */
+/* { dg-final { scan-assembler-times "xc\\s" 28 } } */
+/* { dg-final { scan-assembler-times "stc\\s" 21 } } */
+/* { dg-final { scan-assembler-times "stcy\\s" 1 } } */
+/* { dg-final { scan-assembler-times "pfd\\s" 2 } } */
diff --git a/gcc/testsuite/gcc.target/s390/mnop-mcount-m31-fpic.c b/gcc/testsuite/gcc.target/s390/mnop-mcount-m31-fpic.c
deleted file mode 100644
index 5b00ab6..0000000
--- a/gcc/testsuite/gcc.target/s390/mnop-mcount-m31-fpic.c
+++ /dev/null
@@ -1,8 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-m31 -mesa -march=g5 -fPIC -pg -mnop-mcount -Wno-deprecated" } */
-
-void
-profileme (void)
-{
- /* { dg-final { scan-assembler "NOPs for -mnop-mcount \\(16 halfwords\\)\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0" } } */
-}
diff --git a/gcc/testsuite/gcc.target/s390/mnop-mcount-m31.c b/gcc/testsuite/gcc.target/s390/mnop-mcount-m31.c
deleted file mode 100644
index e64c8d7..0000000
--- a/gcc/testsuite/gcc.target/s390/mnop-mcount-m31.c
+++ /dev/null
@@ -1,8 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-m31 -mesa -march=g5 -pg -mnop-mcount -Wno-deprecated" } */
-
-void
-profileme (void)
-{
- /* { dg-final { scan-assembler "NOPs for -mnop-mcount \\(15 halfwords\\)\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bc\t0,0\n.*bcr\t0,0" } } */
-}
diff --git a/gcc/testsuite/gcc.target/s390/nomemloopunroll-1.c b/gcc/testsuite/gcc.target/s390/nomemloopunroll-1.c
new file mode 100644
index 0000000..695d925
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nomemloopunroll-1.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -funroll-loops -march=z13" } */
+
+/* 2x mvc */
+void *
+foo (char *a, int c, long len)
+{
+ return __builtin_memset (a, c, len);
+}
+
+/* 2x mvc */
+void
+bar (char *a, char *b)
+{
+ __builtin_memcpy (a, b, 30000);
+}
+
+/* 2x clc */
+
+int
+baz (char *a, char *b)
+{
+ return __builtin_memcmp (a, b, 30000);
+}
+
+/* { dg-final { scan-assembler-times "\\\smvc\\\s" 4 } } */
+/* { dg-final { scan-assembler-times "\\\sclc\\\s" 2 } } */
diff --git a/gcc/testsuite/gcc.target/s390/pr80080-3.c b/gcc/testsuite/gcc.target/s390/pr80080-3.c
new file mode 100644
index 0000000..9068b8d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr80080-3.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-march=z10" } */
+
+extern int foo3_mem;
+int foo3 (void)
+{
+ return __atomic_exchange_n (&foo3_mem, 5, __ATOMIC_ACQUIRE);
+}
+
+/* { dg-final { scan-assembler "\n\(\\.L\\d+):\n\tcs\t.*\n\tjne\t\\1\n" } } */
diff --git a/gcc/testsuite/gcc.target/s390/pr84332.c b/gcc/testsuite/gcc.target/s390/pr84332.c
new file mode 100644
index 0000000..3dec99f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr84332.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-march=z900 -fstack-clash-protection --param stack-clash-protection-probe-interval=16" } */
+
+struct b
+{
+ char a[65536];
+};
+
+void c (void) { struct b d; }
diff --git a/gcc/testsuite/gcc.target/s390/risbg-ll-3.c b/gcc/testsuite/gcc.target/s390/risbg-ll-3.c
index 838f1ff..2a2db54 100644
--- a/gcc/testsuite/gcc.target/s390/risbg-ll-3.c
+++ b/gcc/testsuite/gcc.target/s390/risbg-ll-3.c
@@ -23,7 +23,7 @@ i64 f1 (i64 v_a, i64 v_b)
extern i64 f2_foo();
i64 f2 (i64 v_a, i64 v_b)
{
-/* { dg-final { scan-assembler "f2:\n\trisbg\t%r2,%r3,60,62,0\n\tje\t" { target { lp64 } } } } */
+/* { dg-final { scan-assembler "f2:\n\trisbg\t%r2,%r3,60,62,0\n\tbner\t%r14\n\tjg\tf2_foo\n" { target { lp64 } } } } */
/* { dg-final { scan-assembler "f2:\n\trisbgn\t%r3,%r2,0,0\\\+32-1,64-0-32\n\trisbg\t%r3,%r5,60,62,0" { target { ! lp64 } } } } */
i64 v_anda = v_a & -15;
i64 v_andb = v_b & 14;
@@ -37,8 +37,8 @@ i64 f2 (i64 v_a, i64 v_b)
void f2_bar ();
void f2_cconly (i64 v_a, i64 v_b)
{
-/* { dg-final { scan-assembler "f2_cconly:\n\trisbg\t%r3,%r2,63,59,0\n\tjne\t" { target { lp64 } } } } */
-/* { dg-final { scan-assembler "f2_cconly:\n\trisbgn\t%r3,%r2,0,0\\\+32-1,64-0-32\n\trisbg\t%r3,%r5,60,62,0\n\tjne\t" { target { ! lp64 } } } } */
+/* { dg-final { scan-assembler "f2_cconly:\n\trisbg\t%r3,%r2,63,59,0\n\tber\t%r14\n\tjg\tf2_bar\n" { target { lp64 } } } } */
+/* { dg-final { scan-assembler "f2_cconly:\n\trisbgn\t%r3,%r2,0,0\\\+32-1,64-0-32\n\trisbg\t%r3,%r5,60,62,0\n\tber\t%r14\n\tjg\tf2_bar\n" { target { ! lp64 } } } } */
if ((v_a & -15) | (v_b & 14))
f2_bar();
}
diff --git a/gcc/testsuite/gcc.target/s390/s390.exp b/gcc/testsuite/gcc.target/s390/s390.exp
index 93c570a..a9c428d 100644
--- a/gcc/testsuite/gcc.target/s390/s390.exp
+++ b/gcc/testsuite/gcc.target/s390/s390.exp
@@ -252,5 +252,14 @@ set-torture-options $MD_TEST_OPTS
gcc-dg-runtest [lsort [glob -nocomplain $md_tests]] "" "$DEFAULT_CFLAGS"
torture-finish
+# Tests that should pass on all optimization levels.
+foreach t [list $srcdir/$subdir/pr80080-3.c] {
+ torture-init
+ set-torture-options [list -O1 -O2 -O3 -O0 -Os -Ofast -Og]
+ gcc-dg-runtest [list $t] \
+ "" $DEFAULT_CFLAGS
+ torture-finish
+}
+
# All done.
dg-finish
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-arch-tune-1.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-arch-tune-1.c
index ded0885..f1fdaa4 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-arch-tune-1.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-arch-tune-1.c
@@ -8,28 +8,28 @@
**/
void fn_p0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_p0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_p0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_1 tu7" } } */
__attribute__ ((target("arch=zEC12")))
void fn_p0_2 (void) { }
-/* { dg-final { scan-assembler "fn:fn_p0_2 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_p0_2 tu8" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_2 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_2 tu6" } } */
__attribute__ ((target("tune=z196")))
void fn_p0_3 (void) { }
-/* { dg-final { scan-assembler "fn:fn_p0_3 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_p0_3 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_3 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_3 tu5" } } */
__attribute__ ((target("arch=zEC12,tune=z196")))
void fn_p0_4 (void) { }
-/* { dg-final { scan-assembler "fn:fn_p0_4 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_p0_4 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_4 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_4 tu5" } } */
__attribute__ ((target("tune=z196,arch=zEC12")))
void fn_p0_5 (void) { }
-/* { dg-final { scan-assembler "fn:fn_p0_5 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_p0_5 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_5 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_5 tu5" } } */
/**
** arch pragma
@@ -38,28 +38,28 @@ void fn_p0_5 (void) { }
#pragma GCC target ("arch=z9-ec")
void fn_pa_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pa_1 ar5" } } */
-/* { dg-final { scan-assembler "fn:fn_pa_1 tu5" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_1 ar3" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_1 tu3" } } */
__attribute__ ((target("arch=zEC12")))
void fn_pa_2 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pa_2 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pa_2 tu8" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_2 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_2 tu6" } } */
__attribute__ ((target("tune=z196")))
void fn_pa_3 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pa_3 ar5" } } */
-/* { dg-final { scan-assembler "fn:fn_pa_3 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_3 ar3" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_3 tu5" } } */
__attribute__ ((target("arch=zEC12,tune=z196")))
void fn_pa_4 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pa_4 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pa_4 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_4 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_4 tu5" } } */
__attribute__ ((target("tune=z196,arch=zEC12")))
void fn_pa_5 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pa_5 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pa_5 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_5 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_5 tu5" } } */
#pragma GCC reset_options
@@ -70,28 +70,28 @@ void fn_pa_5 (void) { }
#pragma GCC target ("tune=z9-109")
void fn_pt_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pt_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pt_1 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_1 tu2" } } */
__attribute__ ((target("arch=zEC12")))
void fn_pt_2 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pt_2 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pt_2 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_2 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_2 tu2" } } */
__attribute__ ((target("tune=z196")))
void fn_pt_3 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pt_3 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pt_3 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_3 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_3 tu5" } } */
__attribute__ ((target("arch=zEC12,tune=z196")))
void fn_pt_4 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pt_4 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pt_4 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_4 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_4 tu5" } } */
__attribute__ ((target("tune=z196,arch=zEC12")))
void fn_pt_5 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pt_5 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pt_5 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_5 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_5 tu5" } } */
#pragma GCC reset_options
@@ -102,28 +102,28 @@ void fn_pt_5 (void) { }
#pragma GCC target ("arch=z9-ec,tune=z9-109")
void fn_pat_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pat_1 ar5" } } */
-/* { dg-final { scan-assembler "fn:fn_pat_1 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_1 ar3" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_1 tu2" } } */
__attribute__ ((target("arch=zEC12")))
void fn_pat_2 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pat_2 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pat_2 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_2 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_2 tu2" } } */
__attribute__ ((target("tune=z196")))
void fn_pat_3 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pat_3 ar5" } } */
-/* { dg-final { scan-assembler "fn:fn_pat_3 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_3 ar3" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_3 tu5" } } */
__attribute__ ((target("arch=zEC12,tune=z196")))
void fn_pat_4 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pat_4 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pat_4 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_4 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_4 tu5" } } */
__attribute__ ((target("tune=z196,arch=zEC12")))
void fn_pat_5 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pat_5 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pat_5 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_5 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_5 tu5" } } */
#pragma GCC reset_options
@@ -134,27 +134,27 @@ void fn_pat_5 (void) { }
#pragma GCC target ("tune=z9-109,arch=z9-ec")
void fn_pta_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pta_1 ar5" } } */
-/* { dg-final { scan-assembler "fn:fn_pta_1 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_1 ar3" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_1 tu2" } } */
__attribute__ ((target("arch=zEC12")))
void fn_pta_2 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pta_2 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pta_2 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_2 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_2 tu2" } } */
__attribute__ ((target("tune=z196")))
void fn_pta_3 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pta_3 ar5" } } */
-/* { dg-final { scan-assembler "fn:fn_pta_3 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_3 ar3" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_3 tu5" } } */
__attribute__ ((target("arch=zEC12,tune=z196")))
void fn_pta_4 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pta_4 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pta_4 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_4 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_4 tu5" } } */
__attribute__ ((target("tune=z196,arch=zEC12")))
void fn_pta_5 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pta_5 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pta_5 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_5 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_5 tu5" } } */
#pragma GCC reset_options
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-arch-tune-2.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-arch-tune-2.c
index d21a522..ccdb98a 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-arch-tune-2.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-arch-tune-2.c
@@ -8,28 +8,28 @@
**/
void fn_p0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_p0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_p0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_1 tu4" } } */
__attribute__ ((target("arch=zEC12")))
void fn_p0_2 (void) { }
-/* { dg-final { scan-assembler "fn:fn_p0_2 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_p0_2 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_2 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_2 tu4" } } */
__attribute__ ((target("tune=z196")))
void fn_p0_3 (void) { }
-/* { dg-final { scan-assembler "fn:fn_p0_3 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_p0_3 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_3 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_3 tu5" } } */
__attribute__ ((target("arch=zEC12,tune=z196")))
void fn_p0_4 (void) { }
-/* { dg-final { scan-assembler "fn:fn_p0_4 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_p0_4 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_4 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_4 tu5" } } */
__attribute__ ((target("tune=z196,arch=zEC12")))
void fn_p0_5 (void) { }
-/* { dg-final { scan-assembler "fn:fn_p0_5 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_p0_5 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_5 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_p0_5 tu5" } } */
/**
** arch pragma
@@ -38,28 +38,28 @@ void fn_p0_5 (void) { }
#pragma GCC target ("arch=z9-ec")
void fn_pa_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pa_1 ar5" } } */
-/* { dg-final { scan-assembler "fn:fn_pa_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_1 ar3" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_1 tu4" } } */
__attribute__ ((target("arch=zEC12")))
void fn_pa_2 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pa_2 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pa_2 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_2 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_2 tu4" } } */
__attribute__ ((target("tune=z196")))
void fn_pa_3 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pa_3 ar5" } } */
-/* { dg-final { scan-assembler "fn:fn_pa_3 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_3 ar3" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_3 tu5" } } */
__attribute__ ((target("arch=zEC12,tune=z196")))
void fn_pa_4 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pa_4 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pa_4 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_4 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_4 tu5" } } */
__attribute__ ((target("tune=z196,arch=zEC12")))
void fn_pa_5 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pa_5 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pa_5 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_5 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pa_5 tu5" } } */
#pragma GCC reset_options
@@ -70,28 +70,28 @@ void fn_pa_5 (void) { }
#pragma GCC target ("tune=z9-109")
void fn_pt_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pt_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pt_1 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_1 tu2" } } */
__attribute__ ((target("arch=zEC12")))
void fn_pt_2 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pt_2 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pt_2 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_2 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_2 tu2" } } */
__attribute__ ((target("tune=z196")))
void fn_pt_3 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pt_3 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pt_3 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_3 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_3 tu5" } } */
__attribute__ ((target("arch=zEC12,tune=z196")))
void fn_pt_4 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pt_4 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pt_4 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_4 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_4 tu5" } } */
__attribute__ ((target("tune=z196,arch=zEC12")))
void fn_pt_5 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pt_5 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pt_5 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_5 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pt_5 tu5" } } */
#pragma GCC reset_options
@@ -102,28 +102,28 @@ void fn_pt_5 (void) { }
#pragma GCC target ("arch=z9-ec,tune=z9-109")
void fn_pat_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pat_1 ar5" } } */
-/* { dg-final { scan-assembler "fn:fn_pat_1 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_1 ar3" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_1 tu2" } } */
__attribute__ ((target("arch=zEC12")))
void fn_pat_2 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pat_2 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pat_2 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_2 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_2 tu2" } } */
__attribute__ ((target("tune=z196")))
void fn_pat_3 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pat_3 ar5" } } */
-/* { dg-final { scan-assembler "fn:fn_pat_3 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_3 ar3" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_3 tu5" } } */
__attribute__ ((target("arch=zEC12,tune=z196")))
void fn_pat_4 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pat_4 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pat_4 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_4 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_4 tu5" } } */
__attribute__ ((target("tune=z196,arch=zEC12")))
void fn_pat_5 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pat_5 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pat_5 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_5 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pat_5 tu5" } } */
#pragma GCC reset_options
@@ -134,27 +134,27 @@ void fn_pat_5 (void) { }
#pragma GCC target ("tune=z9-109,arch=z9-ec")
void fn_pta_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pta_1 ar5" } } */
-/* { dg-final { scan-assembler "fn:fn_pta_1 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_1 ar3" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_1 tu2" } } */
__attribute__ ((target("arch=zEC12")))
void fn_pta_2 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pta_2 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pta_2 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_2 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_2 tu2" } } */
__attribute__ ((target("tune=z196")))
void fn_pta_3 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pta_3 ar5" } } */
-/* { dg-final { scan-assembler "fn:fn_pta_3 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_3 ar3" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_3 tu5" } } */
__attribute__ ((target("arch=zEC12,tune=z196")))
void fn_pta_4 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pta_4 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pta_4 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_4 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_4 tu5" } } */
__attribute__ ((target("tune=z196,arch=zEC12")))
void fn_pta_5 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pta_5 ar8" } } */
-/* { dg-final { scan-assembler "fn:fn_pta_5 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_5 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pta_5 tu5" } } */
#pragma GCC reset_options
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-1.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-1.c
index 2dbb462..3247fff 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-1.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-1.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -36,8 +36,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("arch=z13")))
void fn_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -57,8 +57,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("arch=z10")))
void fn_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -78,8 +78,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("arch=z10,arch=z13")))
void fn_att_0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -97,8 +97,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("arch=z13,arch=z10")))
void fn_att_1_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -122,8 +122,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("arch=z13")
void fn_pragma_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -160,8 +160,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("arch=z10")
void fn_pragma_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -199,8 +199,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("arch=z10")
#pragma GCC target ("arch=z13")
void fn_pragma_0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -220,8 +220,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("arch=z13")
#pragma GCC target ("arch=z10")
void fn_pragma_1_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -247,8 +247,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("arch=z13")
__attribute__ ((target ("arch=z13")))
void fn_pragma_1_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -268,8 +268,8 @@ void fn_pragma_1_att_1 (void) { }
#pragma GCC target ("arch=z13")
__attribute__ ((target ("arch=z13")))
void fn_pragma_0_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -289,8 +289,8 @@ void fn_pragma_0_att_1 (void) { }
#pragma GCC target ("arch=z13")
__attribute__ ((target ("arch=z10")))
void fn_pragma_1_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -310,8 +310,8 @@ void fn_pragma_1_att_0 (void) { }
#pragma GCC target ("arch=z13")
__attribute__ ((target ("arch=z10")))
void fn_pragma_0_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-10.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-10.c
index edae1ef..f1beb1d 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-10.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-10.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("branch-cost=1")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 wf512" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("branch-cost=2")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 wf512" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("branch-cost=2,branch-cost=1")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 wf512" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("branch-cost=1,branch-cost=2")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 wf512" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("branch-cost=1")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 wf512" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("branch-cost=2")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 wf512" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("branch-cost=1")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wf512" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("branch-cost=2")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wf512" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("branch-cost=1")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wf512" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("branch-cost=1")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wf512" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("branch-cost=2")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wf512" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("branch-cost=2")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wf512" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-11.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-11.c
index 4b66d73..d459eec 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-11.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-11.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("warn-framesize=512")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("warn-framesize=0")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("warn-framesize=0,warn-framesize=512")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("warn-framesize=512,warn-framesize=0")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("warn-framesize=512")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("warn-framesize=0")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("warn-framesize=512")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("warn-framesize=0")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("warn-framesize=512")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("warn-framesize=512")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("warn-framesize=0")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("warn-framesize=0")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-12.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-12.c
index 515f504..8868f91 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-12.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-12.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("warn-framesize=0")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("warn-framesize=512")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("warn-framesize=512,warn-framesize=0")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("warn-framesize=0,warn-framesize=512")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("warn-framesize=0")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("warn-framesize=512")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("warn-framesize=0")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("warn-framesize=512")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("warn-framesize=0")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("warn-framesize=0")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("warn-framesize=512")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("warn-framesize=512")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-13.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-13.c
index ef0914e..6e2c5e4 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-13.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-13.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("backchain")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("no-backchain")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("no-backchain,backchain")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("backchain,no-backchain")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("backchain")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-backchain")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("backchain")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("no-backchain")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("backchain")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("backchain")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("no-backchain")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("no-backchain")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-14.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-14.c
index 7a7cb36..f928bef 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-14.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-14.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("no-backchain")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("backchain")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("backchain,no-backchain")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("no-backchain,backchain")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("no-backchain")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("backchain")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-backchain")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("backchain")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("no-backchain")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("no-backchain")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("backchain")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("backchain")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-15.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-15.c
index e1987c0..de9d79d 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-15.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-15.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("hard-dfp")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("no-hard-dfp")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("no-hard-dfp,hard-dfp")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("hard-dfp,no-hard-dfp")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("hard-dfp")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-hard-dfp")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("hard-dfp")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("no-hard-dfp")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("hard-dfp")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("hard-dfp")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("no-hard-dfp")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("no-hard-dfp")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-16.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-16.c
index b99a5f3..3a893fb 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-16.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-16.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("no-hard-dfp")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("hard-dfp")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("hard-dfp,no-hard-dfp")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("no-hard-dfp,hard-dfp")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("no-hard-dfp")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("hard-dfp")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-hard-dfp")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("hard-dfp")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("no-hard-dfp")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("no-hard-dfp")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("hard-dfp")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("hard-dfp")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-17.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-17.c
index 73e0228..5cd0810 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-17.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-17.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("hard-float")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("soft-float")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("soft-float,hard-float")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("hard-float,soft-float")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("hard-float")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("soft-float")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("hard-float")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("soft-float")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("hard-float")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("hard-float")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("soft-float")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("soft-float")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-18.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-18.c
index 63407a0..878f002 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-18.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-18.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("soft-float")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("hard-float")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("hard-float,soft-float")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("soft-float,hard-float")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("soft-float")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("hard-float")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("soft-float")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("hard-float")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("soft-float")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("soft-float")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("hard-float")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("hard-float")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-19.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-19.c
index b0ace81..918f26a 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-19.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-19.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("htm")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("no-htm")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("no-htm,htm")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("htm,no-htm")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("htm")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-htm")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("htm")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("no-htm")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("htm")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("htm")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("no-htm")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("no-htm")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-2.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-2.c
index 1e6713f..c663b9e 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-2.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-2.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -36,8 +36,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("arch=z10")))
void fn_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -57,8 +57,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("arch=z13")))
void fn_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -78,8 +78,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("arch=z13,arch=z10")))
void fn_att_1_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -97,8 +97,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("arch=z10,arch=z13")))
void fn_att_0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -122,8 +122,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("arch=z10")
void fn_pragma_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -160,8 +160,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("arch=z13")
void fn_pragma_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -199,8 +199,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("arch=z13")
#pragma GCC target ("arch=z10")
void fn_pragma_1_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -220,8 +220,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("arch=z10")
#pragma GCC target ("arch=z13")
void fn_pragma_0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -247,8 +247,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("arch=z10")
__attribute__ ((target ("arch=z10")))
void fn_pragma_0_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -268,8 +268,8 @@ void fn_pragma_0_att_0 (void) { }
#pragma GCC target ("arch=z10")
__attribute__ ((target ("arch=z10")))
void fn_pragma_1_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -289,8 +289,8 @@ void fn_pragma_1_att_0 (void) { }
#pragma GCC target ("arch=z10")
__attribute__ ((target ("arch=z13")))
void fn_pragma_0_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -310,8 +310,8 @@ void fn_pragma_0_att_1 (void) { }
#pragma GCC target ("arch=z10")
__attribute__ ((target ("arch=z13")))
void fn_pragma_1_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-20.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-20.c
index 48fa677..e9eacaa 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-20.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-20.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("no-htm")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("htm")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("htm,no-htm")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("no-htm,htm")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("no-htm")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("htm")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-htm")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("htm")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("no-htm")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("no-htm")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("htm")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("htm")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-21.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-21.c
index e8a2cba..64ff61a 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-21.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-21.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("vx")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("no-vx")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("no-vx,vx")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("vx,no-vx")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("vx")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-vx")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("vx")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("no-vx")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("vx")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("vx")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("no-vx")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("no-vx")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-22.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-22.c
index 53f7c11..1595475 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-22.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-22.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("no-vx")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("vx")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("vx,no-vx")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("no-vx,vx")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("no-vx")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("vx")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-vx")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("vx")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("no-vx")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("no-vx")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("vx")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("vx")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-23.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-23.c
index 79b0ac3..d8da7d7 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-23.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-23.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("packed-stack")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("no-packed-stack")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("no-packed-stack,packed-stack")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("packed-stack,no-packed-stack")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("packed-stack")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-packed-stack")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("packed-stack")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("no-packed-stack")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("packed-stack")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("packed-stack")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("no-packed-stack")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("no-packed-stack")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-24.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-24.c
index 8a7c6dc..87e4da5 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-24.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-24.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("no-packed-stack")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("packed-stack")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("packed-stack,no-packed-stack")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("no-packed-stack,packed-stack")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("no-packed-stack")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("packed-stack")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-packed-stack")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("packed-stack")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("no-packed-stack")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("no-packed-stack")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("packed-stack")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("packed-stack")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-25.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-25.c
index 926846b..19b238c 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-25.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-25.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("small-exec")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("no-small-exec")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("no-small-exec,small-exec")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("small-exec,no-small-exec")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("small-exec")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-small-exec")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("small-exec")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("no-small-exec")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("small-exec")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("small-exec")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("no-small-exec")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("no-small-exec")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-26.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-26.c
index 1c11b6d..e4b49dc 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-26.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-26.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("no-small-exec")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("small-exec")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("small-exec,no-small-exec")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("no-small-exec,small-exec")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("no-small-exec")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("small-exec")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-small-exec")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("small-exec")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("no-small-exec")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("no-small-exec")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("small-exec")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("small-exec")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-27.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-27.c
index d93c7d4..030ddae 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-27.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-27.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("mvcle")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("no-mvcle")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("no-mvcle,mvcle")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("mvcle,no-mvcle")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("mvcle")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-mvcle")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("mvcle")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("no-mvcle")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("mvcle")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("mvcle")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("no-mvcle")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("no-mvcle")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-28.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-28.c
index 7eb069a..ae784a6 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-28.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-28.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("no-mvcle")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("mvcle")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("mvcle,no-mvcle")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("no-mvcle,mvcle")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("no-mvcle")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("mvcle")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-mvcle")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("mvcle")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("no-mvcle")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("no-mvcle")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("mvcle")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("mvcle")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-29.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-29.c
index 2e38c6e..2a50e6a 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-29.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-29.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
#pragma GCC target ("zvector")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 zv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -55,8 +55,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -75,8 +75,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-zvector")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 zv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -93,8 +93,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -114,8 +114,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("zvector")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 zv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -135,8 +135,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("no-zvector")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 zv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -159,8 +159,8 @@ void fn_pragma_1_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-3.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-3.c
index 77739cc30..a2ee075 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-3.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-3.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -36,8 +36,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("tune=z13")))
void fn_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -57,8 +57,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("tune=z10")))
void fn_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -78,8 +78,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("tune=z10,tune=z13")))
void fn_att_0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -97,8 +97,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("tune=z13,tune=z10")))
void fn_att_1_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -122,8 +122,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("tune=z13")
void fn_pragma_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -160,8 +160,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("tune=z10")
void fn_pragma_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -199,8 +199,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("tune=z10")
#pragma GCC target ("tune=z13")
void fn_pragma_0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -220,8 +220,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("tune=z13")
#pragma GCC target ("tune=z10")
void fn_pragma_1_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -247,8 +247,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("tune=z13")
__attribute__ ((target ("tune=z13")))
void fn_pragma_1_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -268,8 +268,8 @@ void fn_pragma_1_att_1 (void) { }
#pragma GCC target ("tune=z13")
__attribute__ ((target ("tune=z13")))
void fn_pragma_0_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -289,8 +289,8 @@ void fn_pragma_0_att_1 (void) { }
#pragma GCC target ("tune=z13")
__attribute__ ((target ("tune=z10")))
void fn_pragma_1_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -310,8 +310,8 @@ void fn_pragma_1_att_0 (void) { }
#pragma GCC target ("tune=z13")
__attribute__ ((target ("tune=z10")))
void fn_pragma_0_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-30.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-30.c
index cc882fe..f82d9ee 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-30.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-30.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
#pragma GCC target ("no-zvector")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 zv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -55,8 +55,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -75,8 +75,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("zvector")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 zv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -93,8 +93,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -114,8 +114,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-zvector")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 zv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -135,8 +135,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("zvector")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 zv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -159,8 +159,8 @@ void fn_pragma_0_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-31.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-31.c
index 1b16c8e..77939aa 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-31.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-31.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("warn-dynamicstack")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("no-warn-dynamicstack")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("no-warn-dynamicstack,warn-dynamicstack")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("warn-dynamicstack,no-warn-dynamicstack")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("warn-dynamicstack")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-warn-dynamicstack")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("warn-dynamicstack")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("no-warn-dynamicstack")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("warn-dynamicstack")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("warn-dynamicstack")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("no-warn-dynamicstack")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("no-warn-dynamicstack")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-32.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-32.c
index cd0ef40..6bdc55a 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-32.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-32.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("no-warn-dynamicstack")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("warn-dynamicstack")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("warn-dynamicstack,no-warn-dynamicstack")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("no-warn-dynamicstack,warn-dynamicstack")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("no-warn-dynamicstack")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("warn-dynamicstack")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-warn-dynamicstack")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("warn-dynamicstack")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("no-warn-dynamicstack")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("no-warn-dynamicstack")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("warn-dynamicstack")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("warn-dynamicstack")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-4.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-4.c
index 163f722..5780f96 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-4.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-4.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -36,8 +36,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("tune=z10")))
void fn_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -57,8 +57,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("tune=z13")))
void fn_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -78,8 +78,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("tune=z13,tune=z10")))
void fn_att_1_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -97,8 +97,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("tune=z10,tune=z13")))
void fn_att_0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -122,8 +122,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("tune=z10")
void fn_pragma_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -160,8 +160,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("tune=z13")
void fn_pragma_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -199,8 +199,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("tune=z13")
#pragma GCC target ("tune=z10")
void fn_pragma_1_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -220,8 +220,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("tune=z10")
#pragma GCC target ("tune=z13")
void fn_pragma_0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -247,8 +247,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("tune=z10")
__attribute__ ((target ("tune=z10")))
void fn_pragma_0_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -268,8 +268,8 @@ void fn_pragma_0_att_0 (void) { }
#pragma GCC target ("tune=z10")
__attribute__ ((target ("tune=z10")))
void fn_pragma_1_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -289,8 +289,8 @@ void fn_pragma_1_att_0 (void) { }
#pragma GCC target ("tune=z10")
__attribute__ ((target ("tune=z13")))
void fn_pragma_0_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -310,8 +310,8 @@ void fn_pragma_0_att_1 (void) { }
#pragma GCC target ("tune=z10")
__attribute__ ((target ("tune=z13")))
void fn_pragma_1_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-5.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-5.c
index 4ad1d08..15e7f22 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-5.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-5.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("stack-size=4096")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 wf0" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("stack-size=2048")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 wf0" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("stack-size=2048,stack-size=4096")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 wf0" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("stack-size=4096,stack-size=2048")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 wf0" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("stack-size=4096")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 wf0" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("stack-size=2048")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 wf0" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("stack-size=4096")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wf0" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("stack-size=2048")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wf0" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("stack-size=4096")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wf0" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("stack-size=4096")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wf0" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("stack-size=2048")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wf0" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("stack-size=2048")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wf0" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-6.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-6.c
index 58ca602..a946ff8 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-6.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-6.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("stack-size=2048")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 wf512" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("stack-size=4096")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 wf512" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("stack-size=4096,stack-size=2048")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 wf512" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("stack-size=2048,stack-size=4096")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 wf512" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("stack-size=2048")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 wf512" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("stack-size=4096")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 wf512" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("stack-size=2048")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wf512" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("stack-size=4096")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wf512" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("stack-size=2048")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wf512" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("stack-size=2048")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wf512" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("stack-size=4096")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wf512" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("stack-size=4096")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wf512" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-7.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-7.c
index 2fc4c4f1..b929f675 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-7.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-7.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("stack-guard=16")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 wf0" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("stack-guard=0")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 wf0" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("stack-guard=0,stack-guard=16")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 wf0" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("stack-guard=16,stack-guard=0")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 wf0" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("stack-guard=16")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 wf0" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("stack-guard=0")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 wf0" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("stack-guard=16")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wf0" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("stack-guard=0")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wf0" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("stack-guard=16")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wf0" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("stack-guard=16")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wf0" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("stack-guard=0")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wf0" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("stack-guard=0")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wf0" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-8.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-8.c
index 1a4dcb7..fee9644 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-8.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-8.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("stack-guard=0")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 wf512" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("stack-guard=16")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 wf512" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("stack-guard=16,stack-guard=0")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 wf512" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("stack-guard=0,stack-guard=16")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 wf512" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("stack-guard=0")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 wf512" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("stack-guard=16")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 wf512" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("stack-guard=0")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wf512" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("stack-guard=16")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wf512" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("stack-guard=0")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wf512" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("stack-guard=0")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wf512" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("stack-guard=16")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wf512" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("stack-guard=16")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wf512" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-9.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-9.c
index d4304f9..04741ef 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-9.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m31-9.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("branch-cost=2")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 wf0" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("branch-cost=1")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 wf0" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("branch-cost=1,branch-cost=2")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 wf0" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("branch-cost=2,branch-cost=1")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 wf0" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("branch-cost=2")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 wf0" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("branch-cost=1")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 wf0" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("branch-cost=2")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wf0" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("branch-cost=1")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wf0" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("branch-cost=2")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wf0" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("branch-cost=2")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wf0" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("branch-cost=1")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wf0" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("branch-cost=1")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wf0" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-1.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-1.c
index 73003f0..41144a7 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-1.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-1.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -36,8 +36,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("arch=z13")))
void fn_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -57,8 +57,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("arch=z10")))
void fn_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -78,8 +78,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("arch=z10,arch=z13")))
void fn_att_0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -97,8 +97,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("arch=z13,arch=z10")))
void fn_att_1_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -122,8 +122,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("arch=z13")
void fn_pragma_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -160,8 +160,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("arch=z10")
void fn_pragma_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -199,8 +199,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("arch=z10")
#pragma GCC target ("arch=z13")
void fn_pragma_0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -220,8 +220,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("arch=z13")
#pragma GCC target ("arch=z10")
void fn_pragma_1_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -247,8 +247,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("arch=z13")
__attribute__ ((target ("arch=z13")))
void fn_pragma_1_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -268,8 +268,8 @@ void fn_pragma_1_att_1 (void) { }
#pragma GCC target ("arch=z13")
__attribute__ ((target ("arch=z13")))
void fn_pragma_0_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -289,8 +289,8 @@ void fn_pragma_0_att_1 (void) { }
#pragma GCC target ("arch=z13")
__attribute__ ((target ("arch=z10")))
void fn_pragma_1_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -310,8 +310,8 @@ void fn_pragma_1_att_0 (void) { }
#pragma GCC target ("arch=z13")
__attribute__ ((target ("arch=z10")))
void fn_pragma_0_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-10.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-10.c
index 7d33c89..7071be2 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-10.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-10.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("branch-cost=1")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 wf512" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("branch-cost=2")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 wf512" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("branch-cost=2,branch-cost=1")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 wf512" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("branch-cost=1,branch-cost=2")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 wf512" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("branch-cost=1")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 wf512" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("branch-cost=2")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 wf512" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("branch-cost=1")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wf512" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("branch-cost=2")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wf512" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("branch-cost=1")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wf512" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("branch-cost=1")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wf512" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("branch-cost=2")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wf512" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("branch-cost=2")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wf512" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-11.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-11.c
index 4737e9c..66537ce 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-11.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-11.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("warn-framesize=512")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("warn-framesize=0")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("warn-framesize=0,warn-framesize=512")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("warn-framesize=512,warn-framesize=0")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("warn-framesize=512")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("warn-framesize=0")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("warn-framesize=512")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("warn-framesize=0")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("warn-framesize=512")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("warn-framesize=512")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("warn-framesize=0")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("warn-framesize=0")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-12.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-12.c
index 71addb8..1bee25d 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-12.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-12.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("warn-framesize=0")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("warn-framesize=512")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("warn-framesize=512,warn-framesize=0")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("warn-framesize=0,warn-framesize=512")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("warn-framesize=0")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("warn-framesize=512")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("warn-framesize=0")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("warn-framesize=512")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("warn-framesize=0")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("warn-framesize=0")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("warn-framesize=512")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("warn-framesize=512")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wf512" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-13.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-13.c
index 27e3ec5..8accc80 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-13.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-13.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("backchain")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("no-backchain")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("no-backchain,backchain")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("backchain,no-backchain")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("backchain")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-backchain")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("backchain")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("no-backchain")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("backchain")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("backchain")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("no-backchain")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("no-backchain")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-14.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-14.c
index 9eb0cc5..80cd6d4 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-14.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-14.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("no-backchain")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("backchain")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("backchain,no-backchain")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("no-backchain,backchain")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("no-backchain")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("backchain")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-backchain")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("backchain")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("no-backchain")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("no-backchain")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ba0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("backchain")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("backchain")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ba1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-15.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-15.c
index 3818ccd..b717eb2 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-15.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-15.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("hard-dfp")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("no-hard-dfp")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("no-hard-dfp,hard-dfp")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("hard-dfp,no-hard-dfp")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("hard-dfp")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-hard-dfp")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("hard-dfp")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("no-hard-dfp")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("hard-dfp")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("hard-dfp")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("no-hard-dfp")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("no-hard-dfp")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-16.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-16.c
index 1660029..52c7981 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-16.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-16.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("no-hard-dfp")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("hard-dfp")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("hard-dfp,no-hard-dfp")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("no-hard-dfp,hard-dfp")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("no-hard-dfp")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("hard-dfp")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-hard-dfp")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("hard-dfp")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("no-hard-dfp")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("no-hard-dfp")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 hd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("hard-dfp")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("hard-dfp")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 hd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-17.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-17.c
index 39e588d..6b21745 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-17.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-17.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("hard-float")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("soft-float")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("soft-float,hard-float")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("hard-float,soft-float")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("hard-float")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("soft-float")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("hard-float")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("soft-float")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("hard-float")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("hard-float")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("soft-float")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("soft-float")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-18.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-18.c
index 0b68242..d5ab735 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-18.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-18.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("soft-float")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("hard-float")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("hard-float,soft-float")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("soft-float,hard-float")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("soft-float")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("hard-float")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("soft-float")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("hard-float")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("soft-float")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("soft-float")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 hf0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("hard-float")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("hard-float")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 hf1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-19.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-19.c
index 4088002..2967bcb 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-19.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-19.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("htm")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("no-htm")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("no-htm,htm")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("htm,no-htm")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("htm")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-htm")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("htm")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("no-htm")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("htm")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("htm")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("no-htm")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("no-htm")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-2.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-2.c
index 55a86bf..e30c9c4 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-2.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-2.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -36,8 +36,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("arch=z10")))
void fn_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -57,8 +57,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("arch=z13")))
void fn_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -78,8 +78,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("arch=z13,arch=z10")))
void fn_att_1_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -97,8 +97,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("arch=z10,arch=z13")))
void fn_att_0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -122,8 +122,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("arch=z10")
void fn_pragma_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -160,8 +160,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("arch=z13")
void fn_pragma_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -199,8 +199,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("arch=z13")
#pragma GCC target ("arch=z10")
void fn_pragma_1_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -220,8 +220,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("arch=z10")
#pragma GCC target ("arch=z13")
void fn_pragma_0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -247,8 +247,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("arch=z10")
__attribute__ ((target ("arch=z10")))
void fn_pragma_0_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -268,8 +268,8 @@ void fn_pragma_0_att_0 (void) { }
#pragma GCC target ("arch=z10")
__attribute__ ((target ("arch=z10")))
void fn_pragma_1_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -289,8 +289,8 @@ void fn_pragma_1_att_0 (void) { }
#pragma GCC target ("arch=z10")
__attribute__ ((target ("arch=z13")))
void fn_pragma_0_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -310,8 +310,8 @@ void fn_pragma_0_att_1 (void) { }
#pragma GCC target ("arch=z10")
__attribute__ ((target ("arch=z13")))
void fn_pragma_1_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-20.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-20.c
index d2b6566..bea7732 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-20.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-20.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("no-htm")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("htm")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("htm,no-htm")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("no-htm,htm")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("no-htm")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("htm")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-htm")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("htm")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("no-htm")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("no-htm")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ht0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("htm")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("htm")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ht1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-21.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-21.c
index 441e6bc..414a794 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-21.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-21.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("vx")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("no-vx")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("no-vx,vx")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("vx,no-vx")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("vx")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-vx")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("vx")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("no-vx")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("vx")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("vx")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("no-vx")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("no-vx")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-22.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-22.c
index e954106..28fa01f 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-22.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-22.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("no-vx")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("vx")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("vx,no-vx")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("no-vx,vx")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("no-vx")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("vx")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-vx")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("vx")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("no-vx")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("no-vx")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 vx0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("vx")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("vx")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 vx1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-23.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-23.c
index 6e6b37a..19550ab 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-23.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-23.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("packed-stack")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("no-packed-stack")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("no-packed-stack,packed-stack")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("packed-stack,no-packed-stack")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("packed-stack")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-packed-stack")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("packed-stack")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("no-packed-stack")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("packed-stack")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("packed-stack")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("no-packed-stack")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("no-packed-stack")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-24.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-24.c
index b97454f..56d92b5 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-24.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-24.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("no-packed-stack")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("packed-stack")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("packed-stack,no-packed-stack")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("no-packed-stack,packed-stack")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("no-packed-stack")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("packed-stack")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-packed-stack")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("packed-stack")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("no-packed-stack")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("no-packed-stack")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ps0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("packed-stack")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("packed-stack")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ps1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-25.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-25.c
index 46c41cc..56ec1d4 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-25.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-25.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("small-exec")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("no-small-exec")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("no-small-exec,small-exec")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("small-exec,no-small-exec")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("small-exec")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-small-exec")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("small-exec")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("no-small-exec")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("small-exec")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("small-exec")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("no-small-exec")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("no-small-exec")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-26.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-26.c
index 957d658..70a8d4b 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-26.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-26.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("no-small-exec")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("small-exec")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("small-exec,no-small-exec")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("no-small-exec,small-exec")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("no-small-exec")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("small-exec")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-small-exec")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("small-exec")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("no-small-exec")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("no-small-exec")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 se0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("small-exec")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("small-exec")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 se1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-27.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-27.c
index 59b5812..d73faea 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-27.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-27.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("mvcle")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("no-mvcle")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("no-mvcle,mvcle")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("mvcle,no-mvcle")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("mvcle")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-mvcle")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("mvcle")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("no-mvcle")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("mvcle")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("mvcle")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("no-mvcle")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("no-mvcle")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-28.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-28.c
index 7720127..a5985f8 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-28.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-28.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("no-mvcle")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("mvcle")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("mvcle,no-mvcle")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("no-mvcle,mvcle")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("no-mvcle")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("mvcle")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-mvcle")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("mvcle")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("no-mvcle")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("no-mvcle")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 mv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("mvcle")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("mvcle")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 mv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-29.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-29.c
index c5bbfaf..db1f97a 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-29.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-29.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
#pragma GCC target ("zvector")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 zv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -55,8 +55,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -75,8 +75,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-zvector")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 zv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -93,8 +93,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -114,8 +114,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("zvector")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 zv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -135,8 +135,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("no-zvector")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 zv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -159,8 +159,8 @@ void fn_pragma_1_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-3.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-3.c
index 948da10..7edbe60 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-3.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-3.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -36,8 +36,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("tune=z13")))
void fn_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -57,8 +57,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("tune=z10")))
void fn_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -78,8 +78,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("tune=z10,tune=z13")))
void fn_att_0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -97,8 +97,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("tune=z13,tune=z10")))
void fn_att_1_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -122,8 +122,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("tune=z13")
void fn_pragma_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -160,8 +160,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("tune=z10")
void fn_pragma_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -199,8 +199,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("tune=z10")
#pragma GCC target ("tune=z13")
void fn_pragma_0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -220,8 +220,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("tune=z13")
#pragma GCC target ("tune=z10")
void fn_pragma_1_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -247,8 +247,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("tune=z13")
__attribute__ ((target ("tune=z13")))
void fn_pragma_1_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -268,8 +268,8 @@ void fn_pragma_1_att_1 (void) { }
#pragma GCC target ("tune=z13")
__attribute__ ((target ("tune=z13")))
void fn_pragma_0_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -289,8 +289,8 @@ void fn_pragma_0_att_1 (void) { }
#pragma GCC target ("tune=z13")
__attribute__ ((target ("tune=z10")))
void fn_pragma_1_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -310,8 +310,8 @@ void fn_pragma_1_att_0 (void) { }
#pragma GCC target ("tune=z13")
__attribute__ ((target ("tune=z10")))
void fn_pragma_0_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-30.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-30.c
index 6aa813b..783a653 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-30.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-30.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
#pragma GCC target ("no-zvector")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 zv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -55,8 +55,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -75,8 +75,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("zvector")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 zv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -93,8 +93,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -114,8 +114,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-zvector")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 zv0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -135,8 +135,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("zvector")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 zv1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -159,8 +159,8 @@ void fn_pragma_0_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-31.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-31.c
index 5227e9a..afb6bc1 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-31.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-31.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("warn-dynamicstack")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("no-warn-dynamicstack")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("no-warn-dynamicstack,warn-dynamicstack")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("warn-dynamicstack,no-warn-dynamicstack")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("warn-dynamicstack")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-warn-dynamicstack")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("warn-dynamicstack")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("no-warn-dynamicstack")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("warn-dynamicstack")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("warn-dynamicstack")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("no-warn-dynamicstack")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("no-warn-dynamicstack")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-32.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-32.c
index 5d9eef7..6793a4e 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-32.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-32.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("no-warn-dynamicstack")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("warn-dynamicstack")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("warn-dynamicstack,no-warn-dynamicstack")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("no-warn-dynamicstack,warn-dynamicstack")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("no-warn-dynamicstack")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("warn-dynamicstack")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("no-warn-dynamicstack")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("warn-dynamicstack")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("no-warn-dynamicstack")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("no-warn-dynamicstack")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wd0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("warn-dynamicstack")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("warn-dynamicstack")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wd1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-33.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-33.c
index 5476ad3..70d9a79 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-33.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-33.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -36,8 +36,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("arch=arch11")))
void fn_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
@@ -57,8 +57,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("arch=arch8")))
void fn_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
@@ -78,8 +78,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("arch=arch8,arch=arch11")))
void fn_att_0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
@@ -97,8 +97,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("arch=arch11,arch=arch8")))
void fn_att_1_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
@@ -122,8 +122,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("arch=arch11")
void fn_pragma_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -160,8 +160,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("arch=arch8")
void fn_pragma_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -199,8 +199,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("arch=arch8")
#pragma GCC target ("arch=arch11")
void fn_pragma_0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
@@ -220,8 +220,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("arch=arch11")
#pragma GCC target ("arch=arch8")
void fn_pragma_1_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
@@ -247,8 +247,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("arch=arch11")
__attribute__ ((target ("arch=arch11")))
void fn_pragma_1_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
@@ -268,8 +268,8 @@ void fn_pragma_1_att_1 (void) { }
#pragma GCC target ("arch=arch11")
__attribute__ ((target ("arch=arch11")))
void fn_pragma_0_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
@@ -289,8 +289,8 @@ void fn_pragma_0_att_1 (void) { }
#pragma GCC target ("arch=arch11")
__attribute__ ((target ("arch=arch8")))
void fn_pragma_1_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
@@ -310,8 +310,8 @@ void fn_pragma_1_att_0 (void) { }
#pragma GCC target ("arch=arch11")
__attribute__ ((target ("arch=arch8")))
void fn_pragma_0_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-4.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-4.c
index 9b50913..ac795ea 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-4.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-4.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -36,8 +36,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("tune=z10")))
void fn_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
@@ -57,8 +57,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("tune=z13")))
void fn_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
@@ -78,8 +78,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("tune=z13,tune=z10")))
void fn_att_1_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
@@ -97,8 +97,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("tune=z10,tune=z13")))
void fn_att_0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
@@ -122,8 +122,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("tune=z10")
void fn_pragma_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -160,8 +160,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("tune=z13")
void fn_pragma_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -199,8 +199,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("tune=z13")
#pragma GCC target ("tune=z10")
void fn_pragma_1_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
@@ -220,8 +220,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("tune=z10")
#pragma GCC target ("tune=z13")
void fn_pragma_0_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
@@ -247,8 +247,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("tune=z10")
__attribute__ ((target ("tune=z10")))
void fn_pragma_0_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
@@ -268,8 +268,8 @@ void fn_pragma_0_att_0 (void) { }
#pragma GCC target ("tune=z10")
__attribute__ ((target ("tune=z10")))
void fn_pragma_1_att_0 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
@@ -289,8 +289,8 @@ void fn_pragma_1_att_0 (void) { }
#pragma GCC target ("tune=z10")
__attribute__ ((target ("tune=z13")))
void fn_pragma_0_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
@@ -310,8 +310,8 @@ void fn_pragma_0_att_1 (void) { }
#pragma GCC target ("tune=z10")
__attribute__ ((target ("tune=z13")))
void fn_pragma_1_att_1 (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-5.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-5.c
index bfc8803..2c185c3 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-5.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-5.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("stack-size=4096")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 wf0" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("stack-size=2048")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 wf0" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("stack-size=2048,stack-size=4096")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 wf0" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("stack-size=4096,stack-size=2048")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 wf0" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("stack-size=4096")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 wf0" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("stack-size=2048")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 wf0" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("stack-size=4096")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wf0" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("stack-size=2048")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wf0" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("stack-size=4096")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wf0" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("stack-size=4096")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wf0" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("stack-size=2048")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wf0" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("stack-size=2048")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wf0" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-6.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-6.c
index b3bc0f6..1487f97 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-6.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-6.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("stack-size=2048")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 wf512" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("stack-size=4096")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 wf512" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("stack-size=4096,stack-size=2048")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 wf512" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("stack-size=2048,stack-size=4096")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 wf512" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("stack-size=2048")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 wf512" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("stack-size=4096")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 wf512" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("stack-size=2048")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wf512" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("stack-size=4096")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wf512" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("stack-size=2048")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wf512" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("stack-size=2048")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wf512" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("stack-size=4096")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wf512" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("stack-size=4096")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wf512" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-7.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-7.c
index ac0b08d..1195982 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-7.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-7.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("stack-guard=16")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 wf0" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("stack-guard=0")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 wf0" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("stack-guard=0,stack-guard=16")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 wf0" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("stack-guard=16,stack-guard=0")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 wf0" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("stack-guard=16")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 wf0" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("stack-guard=0")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 wf0" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("stack-guard=16")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wf0" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("stack-guard=0")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wf0" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("stack-guard=16")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wf0" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("stack-guard=16")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wf0" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("stack-guard=0")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wf0" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("stack-guard=0")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc2" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wf0" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-8.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-8.c
index 9ceca50..b14042b 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-8.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-8.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc1" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("stack-guard=0")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 wf512" } } */
@@ -58,8 +58,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("stack-guard=16")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 wf512" } } */
@@ -79,8 +79,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("stack-guard=16,stack-guard=0")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 wf512" } } */
@@ -98,8 +98,8 @@ void fn_att_1_0 (void) { }
__attribute__ ((target ("stack-guard=0,stack-guard=16")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 wf512" } } */
@@ -123,8 +123,8 @@ void fn_att_0_1 (void) { }
#pragma GCC target ("stack-guard=0")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 wf512" } } */
@@ -141,8 +141,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc1" } } */
@@ -161,8 +161,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("stack-guard=16")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 wf512" } } */
@@ -179,8 +179,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg16" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc1" } } */
@@ -200,8 +200,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("stack-guard=0")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wf512" } } */
@@ -221,8 +221,8 @@ void fn_pragma_1_0 (void) { }
#pragma GCC target ("stack-guard=16")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wf512" } } */
@@ -248,8 +248,8 @@ void fn_pragma_0_1 (void) { }
__attribute__ ((target ("stack-guard=0")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wf512" } } */
@@ -269,8 +269,8 @@ void fn_pragma_0_att_0 (void) { }
__attribute__ ((target ("stack-guard=0")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wf512" } } */
@@ -290,8 +290,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("stack-guard=16")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wf512" } } */
@@ -311,8 +311,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("stack-guard=16")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg16" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu7" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc1" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wf512" } } */
@@ -335,8 +335,8 @@ void fn_pragma_1_att_1 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar6" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu9" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar4" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu7" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss2048" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg16" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-9.c b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-9.c
index ac63555..a3d791b 100644
--- a/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-9.c
+++ b/gcc/testsuite/gcc.target/s390/target-attribute/tattr-m64-9.c
@@ -11,8 +11,8 @@
**/
void fn_default_start (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_start ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_start tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_start tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_start ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_start sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_start bc2" } } */
@@ -37,8 +37,8 @@ void fn_default_start (void) { }
__attribute__ ((target ("branch-cost=2")))
void fn_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1 wf0" } } */
@@ -58,8 +58,8 @@ void fn_att_1_default (void) { }
__attribute__ ((target ("branch-cost=1")))
void fn_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0 wf0" } } */
@@ -79,8 +79,8 @@ void fn_att_0_default (void) { }
__attribute__ ((target ("branch-cost=1,branch-cost=2")))
void fn_att_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_0_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_0_1 wf0" } } */
@@ -98,8 +98,8 @@ void fn_att_0_1 (void) { }
__attribute__ ((target ("branch-cost=2,branch-cost=1")))
void fn_att_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_att_1_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_att_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_att_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_att_1_0 wf0" } } */
@@ -123,8 +123,8 @@ void fn_att_1_0 (void) { }
#pragma GCC target ("branch-cost=2")
void fn_pragma_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1 wf0" } } */
@@ -141,8 +141,8 @@ void fn_pragma_1 (void) { }
#pragma GCC reset_options
void fn_pragma_1_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_default bc2" } } */
@@ -161,8 +161,8 @@ void fn_pragma_1_default (void) { }
#pragma GCC target ("branch-cost=1")
void fn_pragma_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0 wf0" } } */
@@ -179,8 +179,8 @@ void fn_pragma_0 (void) { }
#pragma GCC reset_options
void fn_pragma_0_default (void) { }
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_default tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_default bc2" } } */
@@ -200,8 +200,8 @@ void fn_pragma_0_default (void) { }
#pragma GCC target ("branch-cost=2")
void fn_pragma_0_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_1 wf0" } } */
@@ -221,8 +221,8 @@ void fn_pragma_0_1 (void) { }
#pragma GCC target ("branch-cost=1")
void fn_pragma_1_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_0 wf0" } } */
@@ -248,8 +248,8 @@ void fn_pragma_1_0 (void) { }
__attribute__ ((target ("branch-cost=2")))
void fn_pragma_1_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_1 wf0" } } */
@@ -269,8 +269,8 @@ void fn_pragma_1_att_1 (void) { }
__attribute__ ((target ("branch-cost=2")))
void fn_pragma_0_att_1 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 bc2" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_1 wf0" } } */
@@ -290,8 +290,8 @@ void fn_pragma_0_att_1 (void) { }
__attribute__ ((target ("branch-cost=1")))
void fn_pragma_1_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_1_att_0 wf0" } } */
@@ -311,8 +311,8 @@ void fn_pragma_1_att_0 (void) { }
__attribute__ ((target ("branch-cost=1")))
void fn_pragma_0_att_0 (void) { }
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 bc1" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 tu4" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 sg0" } } */
/* { dg-final { scan-assembler "fn:fn_pragma_0_att_0 wf0" } } */
@@ -335,8 +335,8 @@ void fn_pragma_0_att_0 (void) { }
**/
void fn_default_end (void) { }
-/* { dg-final { scan-assembler "fn:fn_default_end ar9" } } */
-/* { dg-final { scan-assembler "fn:fn_default_end tu6" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end ar7" } } */
+/* { dg-final { scan-assembler "fn:fn_default_end tu4" } } */
/* { dg-final { scan-assembler "fn:fn_default_end ss4096" } } */
/* { dg-final { scan-assembler "fn:fn_default_end sg0" } } */
/* { dg-final { scan-assembler "fn:fn_default_end bc2" } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/vec-cmp-2.c b/gcc/testsuite/gcc.target/s390/zvector/vec-cmp-2.c
index 1e63def..09a15eb 100644
--- a/gcc/testsuite/gcc.target/s390/zvector/vec-cmp-2.c
+++ b/gcc/testsuite/gcc.target/s390/zvector/vec-cmp-2.c
@@ -15,7 +15,7 @@ all_eq_double (vector double a, vector double b)
if (__builtin_expect (vec_all_eq (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times all_eq_double:\n\tvfcedbs\t%v\[0-9\]*,%v24,%v26\n\tjne 1 } } */
+/* { dg-final { scan-assembler-times all_eq_double:\n\tvfcedbs\t%v\[0-9\]*,%v24,%v26\n\tbner\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
all_ne_double (vector double a, vector double b)
@@ -23,7 +23,7 @@ all_ne_double (vector double a, vector double b)
if (__builtin_expect (vec_all_ne (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times all_ne_double:\n\tvfcedbs\t%v\[0-9\]*,%v24,%v26\n\tjle 1 } } */
+/* { dg-final { scan-assembler-times all_ne_double:\n\tvfcedbs\t%v\[0-9\]*,%v24,%v26\n\tbler\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
all_gt_double (vector double a, vector double b)
@@ -31,7 +31,7 @@ all_gt_double (vector double a, vector double b)
if (__builtin_expect (vec_all_gt (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times all_gt_double:\n\tvfchdbs\t%v\[0-9\]*,%v24,%v26\n\tjne 1 } } */
+/* { dg-final { scan-assembler-times all_gt_double:\n\tvfchdbs\t%v\[0-9\]*,%v24,%v26\n\tbner\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
all_lt_double (vector double a, vector double b)
@@ -39,7 +39,7 @@ all_lt_double (vector double a, vector double b)
if (__builtin_expect (vec_all_lt (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times all_lt_double:\n\tvfchdbs\t%v\[0-9\]*,%v26,%v24\n\tjne 1 } } */
+/* { dg-final { scan-assembler-times all_lt_double:\n\tvfchdbs\t%v\[0-9\]*,%v26,%v24\n\tbner\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
all_ge_double (vector double a, vector double b)
@@ -47,7 +47,7 @@ all_ge_double (vector double a, vector double b)
if (__builtin_expect (vec_all_ge (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times all_ge_double:\n\tvfchedbs\t%v\[0-9\]*,%v24,%v26\n\tjne 1 } } */
+/* { dg-final { scan-assembler-times all_ge_double:\n\tvfchedbs\t%v\[0-9\]*,%v24,%v26\n\tbner\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
all_le_double (vector double a, vector double b)
@@ -55,7 +55,7 @@ all_le_double (vector double a, vector double b)
if (__builtin_expect (vec_all_le (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times all_le_double:\n\tvfchedbs\t%v\[0-9\]*,%v26,%v24\n\tjne 1 } } */
+/* { dg-final { scan-assembler-times all_le_double:\n\tvfchedbs\t%v\[0-9\]*,%v26,%v24\n\tbner\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
any_eq_double (vector double a, vector double b)
@@ -63,7 +63,7 @@ any_eq_double (vector double a, vector double b)
if (__builtin_expect (vec_any_eq (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times any_eq_double:\n\tvfcedbs\t%v\[0-9\]*,%v24,%v26\n\tjnle 1 } } */
+/* { dg-final { scan-assembler-times any_eq_double:\n\tvfcedbs\t%v\[0-9\]*,%v24,%v26\n\tbnler\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
any_ne_double (vector double a, vector double b)
@@ -71,7 +71,7 @@ any_ne_double (vector double a, vector double b)
if (__builtin_expect (vec_any_ne (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times any_ne_double:\n\tvfcedbs\t%v\[0-9\]*,%v24,%v26\n\tje 1 } } */
+/* { dg-final { scan-assembler-times any_ne_double:\n\tvfcedbs\t%v\[0-9\]*,%v24,%v26\n\tber\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
any_gt_double (vector double a, vector double b)
@@ -79,7 +79,7 @@ any_gt_double (vector double a, vector double b)
if (__builtin_expect (vec_any_gt (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times any_gt_double:\n\tvfchdbs\t%v\[0-9\]*,%v24,%v26\n\tjnle 1 } } */
+/* { dg-final { scan-assembler-times any_gt_double:\n\tvfchdbs\t%v\[0-9\]*,%v24,%v26\n\tbnler\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
any_lt_double (vector double a, vector double b)
@@ -87,7 +87,7 @@ any_lt_double (vector double a, vector double b)
if (__builtin_expect (vec_any_lt (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times any_lt_double:\n\tvfchdbs\t%v\[0-9\]*,%v26,%v24\n\tjnle 1 } } */
+/* { dg-final { scan-assembler-times any_lt_double:\n\tvfchdbs\t%v\[0-9\]*,%v26,%v24\n\tbnler\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
any_ge_double (vector double a, vector double b)
@@ -95,7 +95,7 @@ any_ge_double (vector double a, vector double b)
if (__builtin_expect (vec_any_ge (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times any_ge_double:\n\tvfchedbs\t%v\[0-9\]*,%v24,%v26\n\tjnle 1 } } */
+/* { dg-final { scan-assembler-times any_ge_double:\n\tvfchedbs\t%v\[0-9\]*,%v24,%v26\n\tbnler\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
any_le_double (vector double a, vector double b)
@@ -103,7 +103,7 @@ any_le_double (vector double a, vector double b)
if (__builtin_expect (vec_any_le (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times any_le_double:\n\tvfchedbs\t%v\[0-9\]*,%v26,%v24\n\tjnle 1 } } */
+/* { dg-final { scan-assembler-times any_le_double:\n\tvfchedbs\t%v\[0-9\]*,%v26,%v24\n\tbnler\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
all_eq_int (vector int a, vector int b)
@@ -111,7 +111,7 @@ all_eq_int (vector int a, vector int b)
if (__builtin_expect (vec_all_eq (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times all_eq_int:\n\tvceqfs\t%v\[0-9\]*,%v24,%v26\n\tjne 1 } } */
+/* { dg-final { scan-assembler-times all_eq_int:\n\tvceqfs\t%v\[0-9\]*,%v24,%v26\n\tbner\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
all_ne_int (vector int a, vector int b)
@@ -119,7 +119,7 @@ all_ne_int (vector int a, vector int b)
if (__builtin_expect (vec_all_ne (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times all_ne_int:\n\tvceqfs\t%v\[0-9\]*,%v24,%v26\n\tjle 1 } } */
+/* { dg-final { scan-assembler-times all_ne_int:\n\tvceqfs\t%v\[0-9\]*,%v24,%v26\n\tbler\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
all_gt_int (vector int a, vector int b)
@@ -127,7 +127,7 @@ all_gt_int (vector int a, vector int b)
if (__builtin_expect (vec_all_gt (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times all_gt_int:\n\tvchfs\t%v\[0-9\]*,%v24,%v26\n\tjne 1 } } */
+/* { dg-final { scan-assembler-times all_gt_int:\n\tvchfs\t%v\[0-9\]*,%v24,%v26\n\tbner\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
all_lt_int (vector int a, vector int b)
@@ -135,7 +135,7 @@ all_lt_int (vector int a, vector int b)
if (__builtin_expect (vec_all_lt (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times all_lt_int:\n\tvchfs\t%v\[0-9\]*,%v26,%v24\n\tjne 1 } } */
+/* { dg-final { scan-assembler-times all_lt_int:\n\tvchfs\t%v\[0-9\]*,%v26,%v24\n\tbner\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
all_ge_int (vector int a, vector int b)
@@ -143,7 +143,7 @@ all_ge_int (vector int a, vector int b)
if (__builtin_expect (vec_all_ge (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times all_ge_int:\n\tvchfs\t%v\[0-9\]*,%v26,%v24\n\tjle 1 } } */
+/* { dg-final { scan-assembler-times all_ge_int:\n\tvchfs\t%v\[0-9\]*,%v26,%v24\n\tbler\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
all_le_int (vector int a, vector int b)
@@ -151,7 +151,7 @@ all_le_int (vector int a, vector int b)
if (__builtin_expect (vec_all_le (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times all_le_int:\n\tvchfs\t%v\[0-9\]*,%v24,%v26\n\tjle 1 } } */
+/* { dg-final { scan-assembler-times all_le_int:\n\tvchfs\t%v\[0-9\]*,%v24,%v26\n\tbler\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
any_eq_int (vector int a, vector int b)
@@ -159,7 +159,7 @@ any_eq_int (vector int a, vector int b)
if (__builtin_expect (vec_any_eq (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times any_eq_int:\n\tvceqfs\t%v\[0-9\]*,%v24,%v26\n\tjnle 1 } } */
+/* { dg-final { scan-assembler-times any_eq_int:\n\tvceqfs\t%v\[0-9\]*,%v24,%v26\n\tbnler\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
any_ne_int (vector int a, vector int b)
@@ -167,7 +167,7 @@ any_ne_int (vector int a, vector int b)
if (__builtin_expect (vec_any_ne (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times any_ne_int:\n\tvceqfs\t%v\[0-9\]*,%v24,%v26\n\tje 1 } } */
+/* { dg-final { scan-assembler-times any_ne_int:\n\tvceqfs\t%v\[0-9\]*,%v24,%v26\n\tber\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
any_gt_int (vector int a, vector int b)
@@ -175,7 +175,7 @@ any_gt_int (vector int a, vector int b)
if (__builtin_expect (vec_any_gt (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times any_gt_int:\n\tvchfs\t%v\[0-9\]*,%v24,%v26\n\tjnle 1 } } */
+/* { dg-final { scan-assembler-times any_gt_int:\n\tvchfs\t%v\[0-9\]*,%v24,%v26\n\tbnler\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
any_lt_int (vector int a, vector int b)
@@ -183,7 +183,7 @@ any_lt_int (vector int a, vector int b)
if (__builtin_expect (vec_any_lt (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times any_lt_int:\n\tvchfs\t%v\[0-9\]*,%v26,%v24\n\tjnle 1 } } */
+/* { dg-final { scan-assembler-times any_lt_int:\n\tvchfs\t%v\[0-9\]*,%v26,%v24\n\tbnler\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
any_ge_int (vector int a, vector int b)
@@ -191,7 +191,7 @@ any_ge_int (vector int a, vector int b)
if (__builtin_expect (vec_any_ge (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times any_ge_int:\n\tvchfs\t%v\[0-9\]*,%v26,%v24\n\tje 1 } } */
+/* { dg-final { scan-assembler-times any_ge_int:\n\tvchfs\t%v\[0-9\]*,%v26,%v24\n\tber\t%r14\n 1 } } */
void __attribute__((noinline,noclone))
any_le_int (vector int a, vector int b)
@@ -199,5 +199,5 @@ any_le_int (vector int a, vector int b)
if (__builtin_expect (vec_any_le (a, b), 1))
g = 2;
}
-/* { dg-final { scan-assembler-times any_le_int:\n\tvchfs\t%v\[0-9\]*,%v24,%v26\n\tje 1 } } */
+/* { dg-final { scan-assembler-times any_le_int:\n\tvchfs\t%v\[0-9\]*,%v24,%v26\n\tber\t%r14\n 1 } } */
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/ms-sysv.exp b/gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/ms-sysv.exp
index bfdb787..f42b9be 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/ms-sysv.exp
+++ b/gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/ms-sysv.exp
@@ -109,7 +109,7 @@ proc runtest_ms_sysv { cflags generator_args } {
< [file mtime "$src"]) } {
# Temporarily switch to the environment for the host compiler.
restore_ld_library_path_env_vars
- set cxx "$HOSTCXX $HOSTCXXFLAGS $TEST_ALWAYS_FLAGS $warn_flags -std=c++11"
+ set cxx "$HOSTCXX $HOSTCXXFLAGS $warn_flags -std=c++11"
set status [remote_exec host "$cxx -o $generator $src"]
set status [lindex $status 0]
set_ld_library_path_env_vars
diff --git a/gcc/testsuite/gfortran.dg/actual_pointer_function_1.f90 b/gcc/testsuite/gfortran.dg/actual_pointer_function_1.f90
index 01213fd..ecb5cbb 100644
--- a/gcc/testsuite/gfortran.dg/actual_pointer_function_1.f90
+++ b/gcc/testsuite/gfortran.dg/actual_pointer_function_1.f90
@@ -17,7 +17,11 @@ CONTAINS
logical function cp_logger_log(logger)
TYPE(cp_logger_type), POINTER ::logger
- cp_logger_log = associated (logger) .and. (logger%a .eq. 42)
+ if (associated (logger)) then
+ cp_logger_log = (logger%a .eq. 42)
+ else
+ cp_logger_log = .false.
+ end if
END function
FUNCTION cp_get_default_logger(v) RESULT(res)
diff --git a/gcc/testsuite/gfortran.dg/alloc_comp_basics_6.f90 b/gcc/testsuite/gfortran.dg/alloc_comp_basics_6.f90
index 3ed221d..4eb0e49 100644
--- a/gcc/testsuite/gfortran.dg/alloc_comp_basics_6.f90
+++ b/gcc/testsuite/gfortran.dg/alloc_comp_basics_6.f90
@@ -5,7 +5,8 @@
! Contributed by Joost VandeVondele <Joost.VandeVondele@mat.ethz.ch>
type sysmtx_t
- type(ext_complex_t), allocatable :: S(:) ! { dg-error "has not been previously defined" }
+ type(ext_complex_t), allocatable :: S(:) ! { dg-error "has not been declared" }
+ class(some_type), allocatable :: X ! { dg-error "has not been declared" }
end type
end
diff --git a/gcc/testsuite/gfortran.dg/alloc_comp_basics_7.f90 b/gcc/testsuite/gfortran.dg/alloc_comp_basics_7.f90
new file mode 100644
index 0000000..7229630
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/alloc_comp_basics_7.f90
@@ -0,0 +1,15 @@
+! { dg-do compile }
+!
+! PR 86888: [F08] allocatable components of indirectly recursive type
+!
+! Contributed by Janus Weil <janus@gcc.gnu.org>
+
+type :: s
+ type(t), allocatable :: x
+end type
+
+type :: t
+ type(s), allocatable :: y
+end type
+
+end
diff --git a/gcc/testsuite/gfortran.dg/allocatable_scalar_14.f90 b/gcc/testsuite/gfortran.dg/allocatable_scalar_14.f90
new file mode 100644
index 0000000..23f6bbf
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/allocatable_scalar_14.f90
@@ -0,0 +1,17 @@
+! { dg-do run }
+!
+! Test the fix for PR64120 in which the initialisation of the
+! string length of 's' was not being done.
+!
+! Contributed by Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+!
+ call g(1)
+ call g(2)
+contains
+ subroutine g(x)
+ integer :: x
+ character(len=x), allocatable :: s
+ allocate(s)
+ if (len(s) .ne. x) stop x
+ end subroutine
+end
diff --git a/gcc/testsuite/gfortran.dg/allocate_with_mold_2.f90 b/gcc/testsuite/gfortran.dg/allocate_with_mold_2.f90
new file mode 100644
index 0000000..fcf7a8a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/allocate_with_mold_2.f90
@@ -0,0 +1,62 @@
+! { dg-do compile }
+! { dg-options "-fdump-tree-original" }
+!
+! Test the fix for PR87284 in which the indexing in allocate with mold
+! was incorrect for class array initialization and resulted in the valgrind
+! error:
+! "Conditional jump or move depends on uninitialised value(s)" at line 42.
+!
+! Contributed by Andrew Baldwin on clf.
+!
+ MODULE INTS_TYPE_MODULE
+ TYPE, ABSTRACT :: BASE_TYPE
+ END TYPE BASE_TYPE
+
+ TYPE, EXTENDS (BASE_TYPE) :: INTS_TYPE
+ INTEGER, ALLOCATABLE :: INTS(:)
+ END TYPE INTS_TYPE
+ CONTAINS
+ SUBROUTINE MOLD_ALLOCATE (IT_OBJS, MOLD_OBJ)
+ CLASS (BASE_TYPE), ALLOCATABLE, INTENT (OUT) :: IT_OBJS(:)
+ CLASS (BASE_TYPE), INTENT (IN) :: MOLD_OBJ
+
+ ALLOCATE (IT_OBJS(2), mold = MOLD_OBJ)
+
+ RETURN
+ END SUBROUTINE MOLD_ALLOCATE
+ END MODULE INTS_TYPE_MODULE
+
+ PROGRAM MFE
+ USE INTS_TYPE_MODULE
+ IMPLICIT NONE
+
+ CLASS (BASE_TYPE), ALLOCATABLE :: IT_OBJS(:)
+ INTEGER :: I
+ TYPE (INTS_TYPE) :: MOLD_OBJ
+
+ ALLOCATE (INTS_TYPE :: IT_OBJS(2))
+
+ SELECT TYPE (IT_OBJS)
+ TYPE IS (INTS_TYPE)
+ ALLOCATE (IT_OBJS(1)%INTS(10))
+
+ ALLOCATE (IT_OBJS(2)%INTS(10))
+ END SELECT
+
+
+ DEALLOCATE (IT_OBJS)
+
+ CALL MOLD_ALLOCATE (IT_OBJS, MOLD_OBJ)
+
+ IF (ALLOCATED(IT_OBJS)) THEN
+ IF (SIZE(IT_OBJS) .GE. 2) THEN
+ SELECT TYPE (IT_OBJS)
+ TYPE IS (INTS_TYPE)
+ ALLOCATE (IT_OBJS(1)%INTS(10))
+
+ ALLOCATE (IT_OBJS(2)%INTS(10))
+ END SELECT
+ END IF
+ END IF
+ END PROGRAM MFE
+! { dg-final { scan-tree-dump-times "it_objs->_vptr->_size" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/allocate_with_source_25.f90 b/gcc/testsuite/gfortran.dg/allocate_with_source_25.f90
new file mode 100644
index 0000000..92dc507
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/allocate_with_source_25.f90
@@ -0,0 +1,71 @@
+! { dg-do compile }
+! { dg-options "-fdump-tree-original" }
+!
+! Test the fix for PR86481
+!
+! Contributed by Rich Townsend <townsend@astro.wisc.edu>
+!
+program simple_leak
+
+ implicit none
+
+ type, abstract :: foo_t
+ end type foo_t
+
+ type, extends(foo_t) :: foo_a_t
+ real(8), allocatable :: a(:)
+ end type foo_a_t
+
+ type, extends(foo_t) :: bar_t
+ class(foo_t), allocatable :: f
+ end type bar_t
+
+ integer, parameter :: N = 2
+ integer, parameter :: D = 3
+
+ type(bar_t) :: b(N)
+ integer :: i
+
+ do i = 1, N
+ b(i) = func_bar(D)
+ end do
+
+ do i = 1, N
+ deallocate (b(i)%f)
+ end do
+
+contains
+
+ function func_bar (D) result (b)
+
+ integer, intent(in) :: D
+ type(bar_t) :: b
+
+ allocate(b%f, SOURCE=func_foo(D))
+
+ end function func_bar
+
+ !****
+
+ function func_foo (D) result (f)
+
+ integer, intent(in) :: D
+ class(foo_t), allocatable :: f
+
+ allocate(f, SOURCE=func_foo_a(D)) ! Lose one of these for each allocation
+
+ end function func_foo
+
+ !****
+
+ function func_foo_a (D) result (f)
+
+ integer, intent(in) :: D
+ type(foo_a_t) :: f
+
+ allocate(f%a(D)) ! Lose one of these for each allocation => N*D*elem_size(f%a)
+
+ end function func_foo_a
+
+end program simple_leak
+! { dg-final { scan-tree-dump-times "\>_final" 6 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/assign_10.f90 b/gcc/testsuite/gfortran.dg/assign_10.f90
index 42f66e5..6e57bef 100644
--- a/gcc/testsuite/gfortran.dg/assign_10.f90
+++ b/gcc/testsuite/gfortran.dg/assign_10.f90
@@ -23,5 +23,5 @@ end
! cases will all yield a temporary, so that atmp appears 18 times.
! Note that it is the kind conversion that generates the temp.
!
-! { dg-final { scan-tree-dump-times "parm" 18 "original" } }
+! { dg-final { scan-tree-dump-times "parm" 20 "original" } }
! { dg-final { scan-tree-dump-times "atmp" 18 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/associate_3.f03 b/gcc/testsuite/gfortran.dg/associate_3.f03
index 20a375d..da7bec9 100644
--- a/gcc/testsuite/gfortran.dg/associate_3.f03
+++ b/gcc/testsuite/gfortran.dg/associate_3.f03
@@ -13,7 +13,7 @@ PROGRAM main
ASSOCIATE (a => 1) 5 ! { dg-error "Junk after ASSOCIATE" }
- ASSOCIATE (x =>) ! { dg-error "Expected association" }
+ ASSOCIATE (x =>) ! { dg-error "Invalid association target" }
ASSOCIATE (=> 5) ! { dg-error "Expected association" }
diff --git a/gcc/testsuite/gfortran.dg/associate_39.f90 b/gcc/testsuite/gfortran.dg/associate_39.f90
new file mode 100644
index 0000000..16357c3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/associate_39.f90
@@ -0,0 +1,19 @@
+! { dg-do compile }
+!
+! PR 86935: Bad locus in ASSOCIATE statement
+!
+! Contributed by Janus Weil <janus@gcc.gnu.org>
+
+implicit none
+
+type :: t
+ real :: r = 0.5
+ integer :: i = 3
+end type
+
+type(t) :: x
+
+associate (r => x%r, &
+ i => x%ii) ! { dg-error "Invalid association target" }
+
+end
diff --git a/gcc/testsuite/gfortran.dg/auto_char_len_2.f90 b/gcc/testsuite/gfortran.dg/auto_char_len_2.f90
index 95825c4..e103b6d 100644
--- a/gcc/testsuite/gfortran.dg/auto_char_len_2.f90
+++ b/gcc/testsuite/gfortran.dg/auto_char_len_2.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-fwhole-file" }
+! { dg-options "" }
!
! PR fortran/41235
!
diff --git a/gcc/testsuite/gfortran.dg/auto_char_len_4.f90 b/gcc/testsuite/gfortran.dg/auto_char_len_4.f90
index 72ee845..16789fa 100644
--- a/gcc/testsuite/gfortran.dg/auto_char_len_4.f90
+++ b/gcc/testsuite/gfortran.dg/auto_char_len_4.f90
@@ -1,5 +1,4 @@
! { dg-do compile }
-! { dg-options "-pedantic -fwhole-file" }
!
! Tests the fix for PR25087, in which the following invalid code
! was not detected.
diff --git a/gcc/testsuite/gfortran.dg/blas_gemm_routines.f b/gcc/testsuite/gfortran.dg/blas_gemm_routines.f
new file mode 100644
index 0000000..f97a33b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/blas_gemm_routines.f
@@ -0,0 +1,1955 @@
+! { dg-do compile }
+! { dg-options "-std=legacy" }
+*> \brief \b CGEMM
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE CGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC)
+*
+* .. Scalar Arguments ..
+* COMPLEX ALPHA,BETA
+* INTEGER K,LDA,LDB,LDC,M,N
+* CHARACTER TRANSA,TRANSB
+* ..
+* .. Array Arguments ..
+* COMPLEX A(LDA,*),B(LDB,*),C(LDC,*)
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> CGEMM performs one of the matrix-matrix operations
+*>
+*> C := alpha*op( A )*op( B ) + beta*C,
+*>
+*> where op( X ) is one of
+*>
+*> op( X ) = X or op( X ) = X**T or op( X ) = X**H,
+*>
+*> alpha and beta are scalars, and A, B and C are matrices, with op( A )
+*> an m by k matrix, op( B ) a k by n matrix and C an m by n matrix.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] TRANSA
+*> \verbatim
+*> TRANSA is CHARACTER*1
+*> On entry, TRANSA specifies the form of op( A ) to be used in
+*> the matrix multiplication as follows:
+*>
+*> TRANSA = 'N' or 'n', op( A ) = A.
+*>
+*> TRANSA = 'T' or 't', op( A ) = A**T.
+*>
+*> TRANSA = 'C' or 'c', op( A ) = A**H.
+*> \endverbatim
+*>
+*> \param[in] TRANSB
+*> \verbatim
+*> TRANSB is CHARACTER*1
+*> On entry, TRANSB specifies the form of op( B ) to be used in
+*> the matrix multiplication as follows:
+*>
+*> TRANSB = 'N' or 'n', op( B ) = B.
+*>
+*> TRANSB = 'T' or 't', op( B ) = B**T.
+*>
+*> TRANSB = 'C' or 'c', op( B ) = B**H.
+*> \endverbatim
+*>
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> On entry, M specifies the number of rows of the matrix
+*> op( A ) and of the matrix C. M must be at least zero.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> On entry, N specifies the number of columns of the matrix
+*> op( B ) and the number of columns of the matrix C. N must be
+*> at least zero.
+*> \endverbatim
+*>
+*> \param[in] K
+*> \verbatim
+*> K is INTEGER
+*> On entry, K specifies the number of columns of the matrix
+*> op( A ) and the number of rows of the matrix op( B ). K must
+*> be at least zero.
+*> \endverbatim
+*>
+*> \param[in] ALPHA
+*> \verbatim
+*> ALPHA is COMPLEX
+*> On entry, ALPHA specifies the scalar alpha.
+*> \endverbatim
+*>
+*> \param[in] A
+*> \verbatim
+*> A is COMPLEX array, dimension ( LDA, ka ), where ka is
+*> k when TRANSA = 'N' or 'n', and is m otherwise.
+*> Before entry with TRANSA = 'N' or 'n', the leading m by k
+*> part of the array A must contain the matrix A, otherwise
+*> the leading k by m part of the array A must contain the
+*> matrix A.
+*> \endverbatim
+*>
+*> \param[in] LDA
+*> \verbatim
+*> LDA is INTEGER
+*> On entry, LDA specifies the first dimension of A as declared
+*> in the calling (sub) program. When TRANSA = 'N' or 'n' then
+*> LDA must be at least max( 1, m ), otherwise LDA must be at
+*> least max( 1, k ).
+*> \endverbatim
+*>
+*> \param[in] B
+*> \verbatim
+*> B is COMPLEX array, dimension ( LDB, kb ), where kb is
+*> n when TRANSB = 'N' or 'n', and is k otherwise.
+*> Before entry with TRANSB = 'N' or 'n', the leading k by n
+*> part of the array B must contain the matrix B, otherwise
+*> the leading n by k part of the array B must contain the
+*> matrix B.
+*> \endverbatim
+*>
+*> \param[in] LDB
+*> \verbatim
+*> LDB is INTEGER
+*> On entry, LDB specifies the first dimension of B as declared
+*> in the calling (sub) program. When TRANSB = 'N' or 'n' then
+*> LDB must be at least max( 1, k ), otherwise LDB must be at
+*> least max( 1, n ).
+*> \endverbatim
+*>
+*> \param[in] BETA
+*> \verbatim
+*> BETA is COMPLEX
+*> On entry, BETA specifies the scalar beta. When BETA is
+*> supplied as zero then C need not be set on input.
+*> \endverbatim
+*>
+*> \param[in,out] C
+*> \verbatim
+*> C is COMPLEX array, dimension ( LDC, N )
+*> Before entry, the leading m by n part of the array C must
+*> contain the matrix C, except when beta is zero, in which
+*> case C need not be set on entry.
+*> On exit, the array C is overwritten by the m by n matrix
+*> ( alpha*op( A )*op( B ) + beta*C ).
+*> \endverbatim
+*>
+*> \param[in] LDC
+*> \verbatim
+*> LDC is INTEGER
+*> On entry, LDC specifies the first dimension of C as declared
+*> in the calling (sub) program. LDC must be at least
+*> max( 1, m ).
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date December 2016
+*
+*> \ingroup complex_blas_level3
+*
+*> \par Further Details:
+* =====================
+*>
+*> \verbatim
+*>
+*> Level 3 Blas routine.
+*>
+*> -- Written on 8-February-1989.
+*> Jack Dongarra, Argonne National Laboratory.
+*> Iain Duff, AERE Harwell.
+*> Jeremy Du Croz, Numerical Algorithms Group Ltd.
+*> Sven Hammarling, Numerical Algorithms Group Ltd.
+*> \endverbatim
+*>
+* =====================================================================
+ SUBROUTINE CGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC)
+*
+* -- Reference BLAS level3 routine (version 3.7.0) --
+* -- Reference BLAS is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* December 2016
+*
+* .. Scalar Arguments ..
+ COMPLEX ALPHA,BETA
+ INTEGER K,LDA,LDB,LDC,M,N
+ CHARACTER TRANSA,TRANSB
+* ..
+* .. Array Arguments ..
+ COMPLEX A(LDA,*),B(LDB,*),C(LDC,*)
+* ..
+*
+* =====================================================================
+*
+* .. External Functions ..
+ LOGICAL LSAME
+ EXTERNAL LSAME
+* ..
+* .. External Subroutines ..
+ EXTERNAL XERBLA
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC CONJG,MAX
+* ..
+* .. Local Scalars ..
+ COMPLEX TEMP
+ INTEGER I,INFO,J,L,NCOLA,NROWA,NROWB
+ LOGICAL CONJA,CONJB,NOTA,NOTB
+* ..
+* .. Parameters ..
+ COMPLEX ONE
+ PARAMETER (ONE= (1.0E+0,0.0E+0))
+ COMPLEX ZERO
+ PARAMETER (ZERO= (0.0E+0,0.0E+0))
+* ..
+*
+* Set NOTA and NOTB as true if A and B respectively are not
+* conjugated or transposed, set CONJA and CONJB as true if A and
+* B respectively are to be transposed but not conjugated and set
+* NROWA, NCOLA and NROWB as the number of rows and columns of A
+* and the number of rows of B respectively.
+*
+ NOTA = LSAME(TRANSA,'N')
+ NOTB = LSAME(TRANSB,'N')
+ CONJA = LSAME(TRANSA,'C')
+ CONJB = LSAME(TRANSB,'C')
+ IF (NOTA) THEN
+ NROWA = M
+ NCOLA = K
+ ELSE
+ NROWA = K
+ NCOLA = M
+ END IF
+ IF (NOTB) THEN
+ NROWB = K
+ ELSE
+ NROWB = N
+ END IF
+*
+* Test the input parameters.
+*
+ INFO = 0
+ IF ((.NOT.NOTA) .AND. (.NOT.CONJA) .AND.
+ + (.NOT.LSAME(TRANSA,'T'))) THEN
+ INFO = 1
+ ELSE IF ((.NOT.NOTB) .AND. (.NOT.CONJB) .AND.
+ + (.NOT.LSAME(TRANSB,'T'))) THEN
+ INFO = 2
+ ELSE IF (M.LT.0) THEN
+ INFO = 3
+ ELSE IF (N.LT.0) THEN
+ INFO = 4
+ ELSE IF (K.LT.0) THEN
+ INFO = 5
+ ELSE IF (LDA.LT.MAX(1,NROWA)) THEN
+ INFO = 8
+ ELSE IF (LDB.LT.MAX(1,NROWB)) THEN
+ INFO = 10
+ ELSE IF (LDC.LT.MAX(1,M)) THEN
+ INFO = 13
+ END IF
+ IF (INFO.NE.0) THEN
+ CALL XERBLA('CGEMM ',INFO)
+ RETURN
+ END IF
+*
+* Quick return if possible.
+*
+ IF ((M.EQ.0) .OR. (N.EQ.0) .OR.
+ + (((ALPHA.EQ.ZERO).OR. (K.EQ.0)).AND. (BETA.EQ.ONE))) RETURN
+*
+* And when alpha.eq.zero.
+*
+ IF (ALPHA.EQ.ZERO) THEN
+ IF (BETA.EQ.ZERO) THEN
+ DO 20 J = 1,N
+ DO 10 I = 1,M
+ C(I,J) = ZERO
+ 10 CONTINUE
+ 20 CONTINUE
+ ELSE
+ DO 40 J = 1,N
+ DO 30 I = 1,M
+ C(I,J) = BETA*C(I,J)
+ 30 CONTINUE
+ 40 CONTINUE
+ END IF
+ RETURN
+ END IF
+*
+* Start the operations.
+*
+ IF (NOTB) THEN
+ IF (NOTA) THEN
+*
+* Form C := alpha*A*B + beta*C.
+*
+ DO 90 J = 1,N
+ IF (BETA.EQ.ZERO) THEN
+ DO 50 I = 1,M
+ C(I,J) = ZERO
+ 50 CONTINUE
+ ELSE IF (BETA.NE.ONE) THEN
+ DO 60 I = 1,M
+ C(I,J) = BETA*C(I,J)
+ 60 CONTINUE
+ END IF
+ DO 80 L = 1,K
+ TEMP = ALPHA*B(L,J)
+ DO 70 I = 1,M
+ C(I,J) = C(I,J) + TEMP*A(I,L)
+ 70 CONTINUE
+ 80 CONTINUE
+ 90 CONTINUE
+ ELSE IF (CONJA) THEN
+*
+* Form C := alpha*A**H*B + beta*C.
+*
+ DO 120 J = 1,N
+ DO 110 I = 1,M
+ TEMP = ZERO
+ DO 100 L = 1,K
+ TEMP = TEMP + CONJG(A(L,I))*B(L,J)
+ 100 CONTINUE
+ IF (BETA.EQ.ZERO) THEN
+ C(I,J) = ALPHA*TEMP
+ ELSE
+ C(I,J) = ALPHA*TEMP + BETA*C(I,J)
+ END IF
+ 110 CONTINUE
+ 120 CONTINUE
+ ELSE
+*
+* Form C := alpha*A**T*B + beta*C
+*
+ DO 150 J = 1,N
+ DO 140 I = 1,M
+ TEMP = ZERO
+ DO 130 L = 1,K
+ TEMP = TEMP + A(L,I)*B(L,J)
+ 130 CONTINUE
+ IF (BETA.EQ.ZERO) THEN
+ C(I,J) = ALPHA*TEMP
+ ELSE
+ C(I,J) = ALPHA*TEMP + BETA*C(I,J)
+ END IF
+ 140 CONTINUE
+ 150 CONTINUE
+ END IF
+ ELSE IF (NOTA) THEN
+ IF (CONJB) THEN
+*
+* Form C := alpha*A*B**H + beta*C.
+*
+ DO 200 J = 1,N
+ IF (BETA.EQ.ZERO) THEN
+ DO 160 I = 1,M
+ C(I,J) = ZERO
+ 160 CONTINUE
+ ELSE IF (BETA.NE.ONE) THEN
+ DO 170 I = 1,M
+ C(I,J) = BETA*C(I,J)
+ 170 CONTINUE
+ END IF
+ DO 190 L = 1,K
+ TEMP = ALPHA*CONJG(B(J,L))
+ DO 180 I = 1,M
+ C(I,J) = C(I,J) + TEMP*A(I,L)
+ 180 CONTINUE
+ 190 CONTINUE
+ 200 CONTINUE
+ ELSE
+*
+* Form C := alpha*A*B**T + beta*C
+*
+ DO 250 J = 1,N
+ IF (BETA.EQ.ZERO) THEN
+ DO 210 I = 1,M
+ C(I,J) = ZERO
+ 210 CONTINUE
+ ELSE IF (BETA.NE.ONE) THEN
+ DO 220 I = 1,M
+ C(I,J) = BETA*C(I,J)
+ 220 CONTINUE
+ END IF
+ DO 240 L = 1,K
+ TEMP = ALPHA*B(J,L)
+ DO 230 I = 1,M
+ C(I,J) = C(I,J) + TEMP*A(I,L)
+ 230 CONTINUE
+ 240 CONTINUE
+ 250 CONTINUE
+ END IF
+ ELSE IF (CONJA) THEN
+ IF (CONJB) THEN
+*
+* Form C := alpha*A**H*B**H + beta*C.
+*
+ DO 280 J = 1,N
+ DO 270 I = 1,M
+ TEMP = ZERO
+ DO 260 L = 1,K
+ TEMP = TEMP + CONJG(A(L,I))*CONJG(B(J,L))
+ 260 CONTINUE
+ IF (BETA.EQ.ZERO) THEN
+ C(I,J) = ALPHA*TEMP
+ ELSE
+ C(I,J) = ALPHA*TEMP + BETA*C(I,J)
+ END IF
+ 270 CONTINUE
+ 280 CONTINUE
+ ELSE
+*
+* Form C := alpha*A**H*B**T + beta*C
+*
+ DO 310 J = 1,N
+ DO 300 I = 1,M
+ TEMP = ZERO
+ DO 290 L = 1,K
+ TEMP = TEMP + CONJG(A(L,I))*B(J,L)
+ 290 CONTINUE
+ IF (BETA.EQ.ZERO) THEN
+ C(I,J) = ALPHA*TEMP
+ ELSE
+ C(I,J) = ALPHA*TEMP + BETA*C(I,J)
+ END IF
+ 300 CONTINUE
+ 310 CONTINUE
+ END IF
+ ELSE
+ IF (CONJB) THEN
+*
+* Form C := alpha*A**T*B**H + beta*C
+*
+ DO 340 J = 1,N
+ DO 330 I = 1,M
+ TEMP = ZERO
+ DO 320 L = 1,K
+ TEMP = TEMP + A(L,I)*CONJG(B(J,L))
+ 320 CONTINUE
+ IF (BETA.EQ.ZERO) THEN
+ C(I,J) = ALPHA*TEMP
+ ELSE
+ C(I,J) = ALPHA*TEMP + BETA*C(I,J)
+ END IF
+ 330 CONTINUE
+ 340 CONTINUE
+ ELSE
+*
+* Form C := alpha*A**T*B**T + beta*C
+*
+ DO 370 J = 1,N
+ DO 360 I = 1,M
+ TEMP = ZERO
+ DO 350 L = 1,K
+ TEMP = TEMP + A(L,I)*B(J,L)
+ 350 CONTINUE
+ IF (BETA.EQ.ZERO) THEN
+ C(I,J) = ALPHA*TEMP
+ ELSE
+ C(I,J) = ALPHA*TEMP + BETA*C(I,J)
+ END IF
+ 360 CONTINUE
+ 370 CONTINUE
+ END IF
+ END IF
+*
+ RETURN
+*
+* End of CGEMM .
+*
+ END
+
+*> \brief \b LSAME
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+* Definition:
+* ===========
+*
+* LOGICAL FUNCTION LSAME(CA,CB)
+*
+* .. Scalar Arguments ..
+* CHARACTER CA,CB
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> LSAME returns .TRUE. if CA is the same letter as CB regardless of
+*> case.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] CA
+*> \verbatim
+*> CA is CHARACTER*1
+*> \endverbatim
+*>
+*> \param[in] CB
+*> \verbatim
+*> CB is CHARACTER*1
+*> CA and CB specify the single characters to be compared.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date December 2016
+*
+*> \ingroup aux_blas
+*
+* =====================================================================
+ LOGICAL FUNCTION LSAME(CA,CB)
+*
+* -- Reference BLAS level1 routine (version 3.1) --
+* -- Reference BLAS is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* December 2016
+*
+* .. Scalar Arguments ..
+ CHARACTER CA,CB
+* ..
+*
+* =====================================================================
+*
+* .. Intrinsic Functions ..
+ INTRINSIC ICHAR
+* ..
+* .. Local Scalars ..
+ INTEGER INTA,INTB,ZCODE
+* ..
+*
+* Test if the characters are equal
+*
+ LSAME = CA .EQ. CB
+ IF (LSAME) RETURN
+*
+* Now test for equivalence if both characters are alphabetic.
+*
+ ZCODE = ICHAR('Z')
+*
+* Use 'Z' rather than 'A' so that ASCII can be detected on Prime
+* machines, on which ICHAR returns a value with bit 8 set.
+* ICHAR('A') on Prime machines returns 193 which is the same as
+* ICHAR('A') on an EBCDIC machine.
+*
+ INTA = ICHAR(CA)
+ INTB = ICHAR(CB)
+*
+ IF (ZCODE.EQ.90 .OR. ZCODE.EQ.122) THEN
+*
+* ASCII is assumed - ZCODE is the ASCII code of either lower or
+* upper case 'Z'.
+*
+ IF (INTA.GE.97 .AND. INTA.LE.122) INTA = INTA - 32
+ IF (INTB.GE.97 .AND. INTB.LE.122) INTB = INTB - 32
+*
+ ELSE IF (ZCODE.EQ.233 .OR. ZCODE.EQ.169) THEN
+*
+* EBCDIC is assumed - ZCODE is the EBCDIC code of either lower or
+* upper case 'Z'.
+*
+ IF (INTA.GE.129 .AND. INTA.LE.137 .OR.
+ + INTA.GE.145 .AND. INTA.LE.153 .OR.
+ + INTA.GE.162 .AND. INTA.LE.169) INTA = INTA + 64
+ IF (INTB.GE.129 .AND. INTB.LE.137 .OR.
+ + INTB.GE.145 .AND. INTB.LE.153 .OR.
+ + INTB.GE.162 .AND. INTB.LE.169) INTB = INTB + 64
+*
+ ELSE IF (ZCODE.EQ.218 .OR. ZCODE.EQ.250) THEN
+*
+* ASCII is assumed, on Prime machines - ZCODE is the ASCII code
+* plus 128 of either lower or upper case 'Z'.
+*
+ IF (INTA.GE.225 .AND. INTA.LE.250) INTA = INTA - 32
+ IF (INTB.GE.225 .AND. INTB.LE.250) INTB = INTB - 32
+ END IF
+ LSAME = INTA .EQ. INTB
+*
+* RETURN
+*
+* End of LSAME
+*
+ END
+
+*> \brief \b XERBLA
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE XERBLA( SRNAME, INFO )
+*
+* .. Scalar Arguments ..
+* CHARACTER*(*) SRNAME
+* INTEGER INFO
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> XERBLA is an error handler for the LAPACK routines.
+*> It is called by an LAPACK routine if an input parameter has an
+*> invalid value. A message is printed and execution stops.
+*>
+*> Installers may consider modifying the STOP statement in order to
+*> call system-specific exception-handling facilities.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] SRNAME
+*> \verbatim
+*> SRNAME is CHARACTER*(*)
+*> The name of the routine which called XERBLA.
+*> \endverbatim
+*>
+*> \param[in] INFO
+*> \verbatim
+*> INFO is INTEGER
+*> The position of the invalid parameter in the parameter list
+*> of the calling routine.
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date December 2016
+*
+*> \ingroup aux_blas
+*
+* =====================================================================
+ SUBROUTINE XERBLA( SRNAME, INFO )
+*
+* -- Reference BLAS level1 routine (version 3.7.0) --
+* -- Reference BLAS is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* December 2016
+*
+* .. Scalar Arguments ..
+ CHARACTER*(*) SRNAME
+ INTEGER INFO
+* ..
+*
+* =====================================================================
+*
+* .. Intrinsic Functions ..
+ INTRINSIC LEN_TRIM
+* ..
+* .. Executable Statements ..
+*
+ WRITE( *, FMT = 9999 )SRNAME( 1:LEN_TRIM( SRNAME ) ), INFO
+*
+ STOP
+*
+ 9999 FORMAT( ' ** On entry to ', A, ' parameter number ', I2, ' had ',
+ $ 'an illegal value' )
+*
+* End of XERBLA
+*
+ END
+
+*> \brief \b SGEMM
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE SGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC)
+*
+* .. Scalar Arguments ..
+* REAL ALPHA,BETA
+* INTEGER K,LDA,LDB,LDC,M,N
+* CHARACTER TRANSA,TRANSB
+* ..
+* .. Array Arguments ..
+* REAL A(LDA,*),B(LDB,*),C(LDC,*)
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> SGEMM performs one of the matrix-matrix operations
+*>
+*> C := alpha*op( A )*op( B ) + beta*C,
+*>
+*> where op( X ) is one of
+*>
+*> op( X ) = X or op( X ) = X**T,
+*>
+*> alpha and beta are scalars, and A, B and C are matrices, with op( A )
+*> an m by k matrix, op( B ) a k by n matrix and C an m by n matrix.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] TRANSA
+*> \verbatim
+*> TRANSA is CHARACTER*1
+*> On entry, TRANSA specifies the form of op( A ) to be used in
+*> the matrix multiplication as follows:
+*>
+*> TRANSA = 'N' or 'n', op( A ) = A.
+*>
+*> TRANSA = 'T' or 't', op( A ) = A**T.
+*>
+*> TRANSA = 'C' or 'c', op( A ) = A**T.
+*> \endverbatim
+*>
+*> \param[in] TRANSB
+*> \verbatim
+*> TRANSB is CHARACTER*1
+*> On entry, TRANSB specifies the form of op( B ) to be used in
+*> the matrix multiplication as follows:
+*>
+*> TRANSB = 'N' or 'n', op( B ) = B.
+*>
+*> TRANSB = 'T' or 't', op( B ) = B**T.
+*>
+*> TRANSB = 'C' or 'c', op( B ) = B**T.
+*> \endverbatim
+*>
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> On entry, M specifies the number of rows of the matrix
+*> op( A ) and of the matrix C. M must be at least zero.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> On entry, N specifies the number of columns of the matrix
+*> op( B ) and the number of columns of the matrix C. N must be
+*> at least zero.
+*> \endverbatim
+*>
+*> \param[in] K
+*> \verbatim
+*> K is INTEGER
+*> On entry, K specifies the number of columns of the matrix
+*> op( A ) and the number of rows of the matrix op( B ). K must
+*> be at least zero.
+*> \endverbatim
+*>
+*> \param[in] ALPHA
+*> \verbatim
+*> ALPHA is REAL
+*> On entry, ALPHA specifies the scalar alpha.
+*> \endverbatim
+*>
+*> \param[in] A
+*> \verbatim
+*> A is REAL array, dimension ( LDA, ka ), where ka is
+*> k when TRANSA = 'N' or 'n', and is m otherwise.
+*> Before entry with TRANSA = 'N' or 'n', the leading m by k
+*> part of the array A must contain the matrix A, otherwise
+*> the leading k by m part of the array A must contain the
+*> matrix A.
+*> \endverbatim
+*>
+*> \param[in] LDA
+*> \verbatim
+*> LDA is INTEGER
+*> On entry, LDA specifies the first dimension of A as declared
+*> in the calling (sub) program. When TRANSA = 'N' or 'n' then
+*> LDA must be at least max( 1, m ), otherwise LDA must be at
+*> least max( 1, k ).
+*> \endverbatim
+*>
+*> \param[in] B
+*> \verbatim
+*> B is REAL array, dimension ( LDB, kb ), where kb is
+*> n when TRANSB = 'N' or 'n', and is k otherwise.
+*> Before entry with TRANSB = 'N' or 'n', the leading k by n
+*> part of the array B must contain the matrix B, otherwise
+*> the leading n by k part of the array B must contain the
+*> matrix B.
+*> \endverbatim
+*>
+*> \param[in] LDB
+*> \verbatim
+*> LDB is INTEGER
+*> On entry, LDB specifies the first dimension of B as declared
+*> in the calling (sub) program. When TRANSB = 'N' or 'n' then
+*> LDB must be at least max( 1, k ), otherwise LDB must be at
+*> least max( 1, n ).
+*> \endverbatim
+*>
+*> \param[in] BETA
+*> \verbatim
+*> BETA is REAL
+*> On entry, BETA specifies the scalar beta. When BETA is
+*> supplied as zero then C need not be set on input.
+*> \endverbatim
+*>
+*> \param[in,out] C
+*> \verbatim
+*> C is REAL array, dimension ( LDC, N )
+*> Before entry, the leading m by n part of the array C must
+*> contain the matrix C, except when beta is zero, in which
+*> case C need not be set on entry.
+*> On exit, the array C is overwritten by the m by n matrix
+*> ( alpha*op( A )*op( B ) + beta*C ).
+*> \endverbatim
+*>
+*> \param[in] LDC
+*> \verbatim
+*> LDC is INTEGER
+*> On entry, LDC specifies the first dimension of C as declared
+*> in the calling (sub) program. LDC must be at least
+*> max( 1, m ).
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date December 2016
+*
+*> \ingroup single_blas_level3
+*
+*> \par Further Details:
+* =====================
+*>
+*> \verbatim
+*>
+*> Level 3 Blas routine.
+*>
+*> -- Written on 8-February-1989.
+*> Jack Dongarra, Argonne National Laboratory.
+*> Iain Duff, AERE Harwell.
+*> Jeremy Du Croz, Numerical Algorithms Group Ltd.
+*> Sven Hammarling, Numerical Algorithms Group Ltd.
+*> \endverbatim
+*>
+* =====================================================================
+ SUBROUTINE SGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC)
+*
+* -- Reference BLAS level3 routine (version 3.7.0) --
+* -- Reference BLAS is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* December 2016
+*
+* .. Scalar Arguments ..
+ REAL ALPHA,BETA
+ INTEGER K,LDA,LDB,LDC,M,N
+ CHARACTER TRANSA,TRANSB
+* ..
+* .. Array Arguments ..
+ REAL A(LDA,*),B(LDB,*),C(LDC,*)
+* ..
+*
+* =====================================================================
+*
+* .. External Functions ..
+ LOGICAL LSAME
+ EXTERNAL LSAME
+* ..
+* .. External Subroutines ..
+ EXTERNAL XERBLA
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC MAX
+* ..
+* .. Local Scalars ..
+ REAL TEMP
+ INTEGER I,INFO,J,L,NCOLA,NROWA,NROWB
+ LOGICAL NOTA,NOTB
+* ..
+* .. Parameters ..
+ REAL ONE,ZERO
+ PARAMETER (ONE=1.0E+0,ZERO=0.0E+0)
+* ..
+*
+* Set NOTA and NOTB as true if A and B respectively are not
+* transposed and set NROWA, NCOLA and NROWB as the number of rows
+* and columns of A and the number of rows of B respectively.
+*
+ NOTA = LSAME(TRANSA,'N')
+ NOTB = LSAME(TRANSB,'N')
+ IF (NOTA) THEN
+ NROWA = M
+ NCOLA = K
+ ELSE
+ NROWA = K
+ NCOLA = M
+ END IF
+ IF (NOTB) THEN
+ NROWB = K
+ ELSE
+ NROWB = N
+ END IF
+*
+* Test the input parameters.
+*
+ INFO = 0
+ IF ((.NOT.NOTA) .AND. (.NOT.LSAME(TRANSA,'C')) .AND.
+ + (.NOT.LSAME(TRANSA,'T'))) THEN
+ INFO = 1
+ ELSE IF ((.NOT.NOTB) .AND. (.NOT.LSAME(TRANSB,'C')) .AND.
+ + (.NOT.LSAME(TRANSB,'T'))) THEN
+ INFO = 2
+ ELSE IF (M.LT.0) THEN
+ INFO = 3
+ ELSE IF (N.LT.0) THEN
+ INFO = 4
+ ELSE IF (K.LT.0) THEN
+ INFO = 5
+ ELSE IF (LDA.LT.MAX(1,NROWA)) THEN
+ INFO = 8
+ ELSE IF (LDB.LT.MAX(1,NROWB)) THEN
+ INFO = 10
+ ELSE IF (LDC.LT.MAX(1,M)) THEN
+ INFO = 13
+ END IF
+ IF (INFO.NE.0) THEN
+ CALL XERBLA('SGEMM ',INFO)
+ RETURN
+ END IF
+*
+* Quick return if possible.
+*
+ IF ((M.EQ.0) .OR. (N.EQ.0) .OR.
+ + (((ALPHA.EQ.ZERO).OR. (K.EQ.0)).AND. (BETA.EQ.ONE))) RETURN
+*
+* And if alpha.eq.zero.
+*
+ IF (ALPHA.EQ.ZERO) THEN
+ IF (BETA.EQ.ZERO) THEN
+ DO 20 J = 1,N
+ DO 10 I = 1,M
+ C(I,J) = ZERO
+ 10 CONTINUE
+ 20 CONTINUE
+ ELSE
+ DO 40 J = 1,N
+ DO 30 I = 1,M
+ C(I,J) = BETA*C(I,J)
+ 30 CONTINUE
+ 40 CONTINUE
+ END IF
+ RETURN
+ END IF
+*
+* Start the operations.
+*
+ IF (NOTB) THEN
+ IF (NOTA) THEN
+*
+* Form C := alpha*A*B + beta*C.
+*
+ DO 90 J = 1,N
+ IF (BETA.EQ.ZERO) THEN
+ DO 50 I = 1,M
+ C(I,J) = ZERO
+ 50 CONTINUE
+ ELSE IF (BETA.NE.ONE) THEN
+ DO 60 I = 1,M
+ C(I,J) = BETA*C(I,J)
+ 60 CONTINUE
+ END IF
+ DO 80 L = 1,K
+ TEMP = ALPHA*B(L,J)
+ DO 70 I = 1,M
+ C(I,J) = C(I,J) + TEMP*A(I,L)
+ 70 CONTINUE
+ 80 CONTINUE
+ 90 CONTINUE
+ ELSE
+*
+* Form C := alpha*A**T*B + beta*C
+*
+ DO 120 J = 1,N
+ DO 110 I = 1,M
+ TEMP = ZERO
+ DO 100 L = 1,K
+ TEMP = TEMP + A(L,I)*B(L,J)
+ 100 CONTINUE
+ IF (BETA.EQ.ZERO) THEN
+ C(I,J) = ALPHA*TEMP
+ ELSE
+ C(I,J) = ALPHA*TEMP + BETA*C(I,J)
+ END IF
+ 110 CONTINUE
+ 120 CONTINUE
+ END IF
+ ELSE
+ IF (NOTA) THEN
+*
+* Form C := alpha*A*B**T + beta*C
+*
+ DO 170 J = 1,N
+ IF (BETA.EQ.ZERO) THEN
+ DO 130 I = 1,M
+ C(I,J) = ZERO
+ 130 CONTINUE
+ ELSE IF (BETA.NE.ONE) THEN
+ DO 140 I = 1,M
+ C(I,J) = BETA*C(I,J)
+ 140 CONTINUE
+ END IF
+ DO 160 L = 1,K
+ TEMP = ALPHA*B(J,L)
+ DO 150 I = 1,M
+ C(I,J) = C(I,J) + TEMP*A(I,L)
+ 150 CONTINUE
+ 160 CONTINUE
+ 170 CONTINUE
+ ELSE
+*
+* Form C := alpha*A**T*B**T + beta*C
+*
+ DO 200 J = 1,N
+ DO 190 I = 1,M
+ TEMP = ZERO
+ DO 180 L = 1,K
+ TEMP = TEMP + A(L,I)*B(J,L)
+ 180 CONTINUE
+ IF (BETA.EQ.ZERO) THEN
+ C(I,J) = ALPHA*TEMP
+ ELSE
+ C(I,J) = ALPHA*TEMP + BETA*C(I,J)
+ END IF
+ 190 CONTINUE
+ 200 CONTINUE
+ END IF
+ END IF
+*
+ RETURN
+*
+* End of SGEMM .
+*
+ END
+
+*> \brief \b DGEMM
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE DGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC)
+*
+* .. Scalar Arguments ..
+* DOUBLE PRECISION ALPHA,BETA
+* INTEGER K,LDA,LDB,LDC,M,N
+* CHARACTER TRANSA,TRANSB
+* ..
+* .. Array Arguments ..
+* DOUBLE PRECISION A(LDA,*),B(LDB,*),C(LDC,*)
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> DGEMM performs one of the matrix-matrix operations
+*>
+*> C := alpha*op( A )*op( B ) + beta*C,
+*>
+*> where op( X ) is one of
+*>
+*> op( X ) = X or op( X ) = X**T,
+*>
+*> alpha and beta are scalars, and A, B and C are matrices, with op( A )
+*> an m by k matrix, op( B ) a k by n matrix and C an m by n matrix.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] TRANSA
+*> \verbatim
+*> TRANSA is CHARACTER*1
+*> On entry, TRANSA specifies the form of op( A ) to be used in
+*> the matrix multiplication as follows:
+*>
+*> TRANSA = 'N' or 'n', op( A ) = A.
+*>
+*> TRANSA = 'T' or 't', op( A ) = A**T.
+*>
+*> TRANSA = 'C' or 'c', op( A ) = A**T.
+*> \endverbatim
+*>
+*> \param[in] TRANSB
+*> \verbatim
+*> TRANSB is CHARACTER*1
+*> On entry, TRANSB specifies the form of op( B ) to be used in
+*> the matrix multiplication as follows:
+*>
+*> TRANSB = 'N' or 'n', op( B ) = B.
+*>
+*> TRANSB = 'T' or 't', op( B ) = B**T.
+*>
+*> TRANSB = 'C' or 'c', op( B ) = B**T.
+*> \endverbatim
+*>
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> On entry, M specifies the number of rows of the matrix
+*> op( A ) and of the matrix C. M must be at least zero.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> On entry, N specifies the number of columns of the matrix
+*> op( B ) and the number of columns of the matrix C. N must be
+*> at least zero.
+*> \endverbatim
+*>
+*> \param[in] K
+*> \verbatim
+*> K is INTEGER
+*> On entry, K specifies the number of columns of the matrix
+*> op( A ) and the number of rows of the matrix op( B ). K must
+*> be at least zero.
+*> \endverbatim
+*>
+*> \param[in] ALPHA
+*> \verbatim
+*> ALPHA is DOUBLE PRECISION.
+*> On entry, ALPHA specifies the scalar alpha.
+*> \endverbatim
+*>
+*> \param[in] A
+*> \verbatim
+*> A is DOUBLE PRECISION array, dimension ( LDA, ka ), where ka is
+*> k when TRANSA = 'N' or 'n', and is m otherwise.
+*> Before entry with TRANSA = 'N' or 'n', the leading m by k
+*> part of the array A must contain the matrix A, otherwise
+*> the leading k by m part of the array A must contain the
+*> matrix A.
+*> \endverbatim
+*>
+*> \param[in] LDA
+*> \verbatim
+*> LDA is INTEGER
+*> On entry, LDA specifies the first dimension of A as declared
+*> in the calling (sub) program. When TRANSA = 'N' or 'n' then
+*> LDA must be at least max( 1, m ), otherwise LDA must be at
+*> least max( 1, k ).
+*> \endverbatim
+*>
+*> \param[in] B
+*> \verbatim
+*> B is DOUBLE PRECISION array, dimension ( LDB, kb ), where kb is
+*> n when TRANSB = 'N' or 'n', and is k otherwise.
+*> Before entry with TRANSB = 'N' or 'n', the leading k by n
+*> part of the array B must contain the matrix B, otherwise
+*> the leading n by k part of the array B must contain the
+*> matrix B.
+*> \endverbatim
+*>
+*> \param[in] LDB
+*> \verbatim
+*> LDB is INTEGER
+*> On entry, LDB specifies the first dimension of B as declared
+*> in the calling (sub) program. When TRANSB = 'N' or 'n' then
+*> LDB must be at least max( 1, k ), otherwise LDB must be at
+*> least max( 1, n ).
+*> \endverbatim
+*>
+*> \param[in] BETA
+*> \verbatim
+*> BETA is DOUBLE PRECISION.
+*> On entry, BETA specifies the scalar beta. When BETA is
+*> supplied as zero then C need not be set on input.
+*> \endverbatim
+*>
+*> \param[in,out] C
+*> \verbatim
+*> C is DOUBLE PRECISION array, dimension ( LDC, N )
+*> Before entry, the leading m by n part of the array C must
+*> contain the matrix C, except when beta is zero, in which
+*> case C need not be set on entry.
+*> On exit, the array C is overwritten by the m by n matrix
+*> ( alpha*op( A )*op( B ) + beta*C ).
+*> \endverbatim
+*>
+*> \param[in] LDC
+*> \verbatim
+*> LDC is INTEGER
+*> On entry, LDC specifies the first dimension of C as declared
+*> in the calling (sub) program. LDC must be at least
+*> max( 1, m ).
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date December 2016
+*
+*> \ingroup double_blas_level3
+*
+*> \par Further Details:
+* =====================
+*>
+*> \verbatim
+*>
+*> Level 3 Blas routine.
+*>
+*> -- Written on 8-February-1989.
+*> Jack Dongarra, Argonne National Laboratory.
+*> Iain Duff, AERE Harwell.
+*> Jeremy Du Croz, Numerical Algorithms Group Ltd.
+*> Sven Hammarling, Numerical Algorithms Group Ltd.
+*> \endverbatim
+*>
+* =====================================================================
+ SUBROUTINE DGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC)
+*
+* -- Reference BLAS level3 routine (version 3.7.0) --
+* -- Reference BLAS is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* December 2016
+*
+* .. Scalar Arguments ..
+ DOUBLE PRECISION ALPHA,BETA
+ INTEGER K,LDA,LDB,LDC,M,N
+ CHARACTER TRANSA,TRANSB
+* ..
+* .. Array Arguments ..
+ DOUBLE PRECISION A(LDA,*),B(LDB,*),C(LDC,*)
+* ..
+*
+* =====================================================================
+*
+* .. External Functions ..
+ LOGICAL LSAME
+ EXTERNAL LSAME
+* ..
+* .. External Subroutines ..
+ EXTERNAL XERBLA
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC MAX
+* ..
+* .. Local Scalars ..
+ DOUBLE PRECISION TEMP
+ INTEGER I,INFO,J,L,NCOLA,NROWA,NROWB
+ LOGICAL NOTA,NOTB
+* ..
+* .. Parameters ..
+ DOUBLE PRECISION ONE,ZERO
+ PARAMETER (ONE=1.0D+0,ZERO=0.0D+0)
+* ..
+*
+* Set NOTA and NOTB as true if A and B respectively are not
+* transposed and set NROWA, NCOLA and NROWB as the number of rows
+* and columns of A and the number of rows of B respectively.
+*
+ NOTA = LSAME(TRANSA,'N')
+ NOTB = LSAME(TRANSB,'N')
+ IF (NOTA) THEN
+ NROWA = M
+ NCOLA = K
+ ELSE
+ NROWA = K
+ NCOLA = M
+ END IF
+ IF (NOTB) THEN
+ NROWB = K
+ ELSE
+ NROWB = N
+ END IF
+*
+* Test the input parameters.
+*
+ INFO = 0
+ IF ((.NOT.NOTA) .AND. (.NOT.LSAME(TRANSA,'C')) .AND.
+ + (.NOT.LSAME(TRANSA,'T'))) THEN
+ INFO = 1
+ ELSE IF ((.NOT.NOTB) .AND. (.NOT.LSAME(TRANSB,'C')) .AND.
+ + (.NOT.LSAME(TRANSB,'T'))) THEN
+ INFO = 2
+ ELSE IF (M.LT.0) THEN
+ INFO = 3
+ ELSE IF (N.LT.0) THEN
+ INFO = 4
+ ELSE IF (K.LT.0) THEN
+ INFO = 5
+ ELSE IF (LDA.LT.MAX(1,NROWA)) THEN
+ INFO = 8
+ ELSE IF (LDB.LT.MAX(1,NROWB)) THEN
+ INFO = 10
+ ELSE IF (LDC.LT.MAX(1,M)) THEN
+ INFO = 13
+ END IF
+ IF (INFO.NE.0) THEN
+ CALL XERBLA('DGEMM ',INFO)
+ RETURN
+ END IF
+*
+* Quick return if possible.
+*
+ IF ((M.EQ.0) .OR. (N.EQ.0) .OR.
+ + (((ALPHA.EQ.ZERO).OR. (K.EQ.0)).AND. (BETA.EQ.ONE))) RETURN
+*
+* And if alpha.eq.zero.
+*
+ IF (ALPHA.EQ.ZERO) THEN
+ IF (BETA.EQ.ZERO) THEN
+ DO 20 J = 1,N
+ DO 10 I = 1,M
+ C(I,J) = ZERO
+ 10 CONTINUE
+ 20 CONTINUE
+ ELSE
+ DO 40 J = 1,N
+ DO 30 I = 1,M
+ C(I,J) = BETA*C(I,J)
+ 30 CONTINUE
+ 40 CONTINUE
+ END IF
+ RETURN
+ END IF
+*
+* Start the operations.
+*
+ IF (NOTB) THEN
+ IF (NOTA) THEN
+*
+* Form C := alpha*A*B + beta*C.
+*
+ DO 90 J = 1,N
+ IF (BETA.EQ.ZERO) THEN
+ DO 50 I = 1,M
+ C(I,J) = ZERO
+ 50 CONTINUE
+ ELSE IF (BETA.NE.ONE) THEN
+ DO 60 I = 1,M
+ C(I,J) = BETA*C(I,J)
+ 60 CONTINUE
+ END IF
+ DO 80 L = 1,K
+ TEMP = ALPHA*B(L,J)
+ DO 70 I = 1,M
+ C(I,J) = C(I,J) + TEMP*A(I,L)
+ 70 CONTINUE
+ 80 CONTINUE
+ 90 CONTINUE
+ ELSE
+*
+* Form C := alpha*A**T*B + beta*C
+*
+ DO 120 J = 1,N
+ DO 110 I = 1,M
+ TEMP = ZERO
+ DO 100 L = 1,K
+ TEMP = TEMP + A(L,I)*B(L,J)
+ 100 CONTINUE
+ IF (BETA.EQ.ZERO) THEN
+ C(I,J) = ALPHA*TEMP
+ ELSE
+ C(I,J) = ALPHA*TEMP + BETA*C(I,J)
+ END IF
+ 110 CONTINUE
+ 120 CONTINUE
+ END IF
+ ELSE
+ IF (NOTA) THEN
+*
+* Form C := alpha*A*B**T + beta*C
+*
+ DO 170 J = 1,N
+ IF (BETA.EQ.ZERO) THEN
+ DO 130 I = 1,M
+ C(I,J) = ZERO
+ 130 CONTINUE
+ ELSE IF (BETA.NE.ONE) THEN
+ DO 140 I = 1,M
+ C(I,J) = BETA*C(I,J)
+ 140 CONTINUE
+ END IF
+ DO 160 L = 1,K
+ TEMP = ALPHA*B(J,L)
+ DO 150 I = 1,M
+ C(I,J) = C(I,J) + TEMP*A(I,L)
+ 150 CONTINUE
+ 160 CONTINUE
+ 170 CONTINUE
+ ELSE
+*
+* Form C := alpha*A**T*B**T + beta*C
+*
+ DO 200 J = 1,N
+ DO 190 I = 1,M
+ TEMP = ZERO
+ DO 180 L = 1,K
+ TEMP = TEMP + A(L,I)*B(J,L)
+ 180 CONTINUE
+ IF (BETA.EQ.ZERO) THEN
+ C(I,J) = ALPHA*TEMP
+ ELSE
+ C(I,J) = ALPHA*TEMP + BETA*C(I,J)
+ END IF
+ 190 CONTINUE
+ 200 CONTINUE
+ END IF
+ END IF
+*
+ RETURN
+*
+* End of DGEMM .
+*
+ END
+
+*> \brief \b ZGEMM
+*
+* =========== DOCUMENTATION ===========
+*
+* Online html documentation available at
+* http://www.netlib.org/lapack/explore-html/
+*
+* Definition:
+* ===========
+*
+* SUBROUTINE ZGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC)
+*
+* .. Scalar Arguments ..
+* COMPLEX*16 ALPHA,BETA
+* INTEGER K,LDA,LDB,LDC,M,N
+* CHARACTER TRANSA,TRANSB
+* ..
+* .. Array Arguments ..
+* COMPLEX*16 A(LDA,*),B(LDB,*),C(LDC,*)
+* ..
+*
+*
+*> \par Purpose:
+* =============
+*>
+*> \verbatim
+*>
+*> ZGEMM performs one of the matrix-matrix operations
+*>
+*> C := alpha*op( A )*op( B ) + beta*C,
+*>
+*> where op( X ) is one of
+*>
+*> op( X ) = X or op( X ) = X**T or op( X ) = X**H,
+*>
+*> alpha and beta are scalars, and A, B and C are matrices, with op( A )
+*> an m by k matrix, op( B ) a k by n matrix and C an m by n matrix.
+*> \endverbatim
+*
+* Arguments:
+* ==========
+*
+*> \param[in] TRANSA
+*> \verbatim
+*> TRANSA is CHARACTER*1
+*> On entry, TRANSA specifies the form of op( A ) to be used in
+*> the matrix multiplication as follows:
+*>
+*> TRANSA = 'N' or 'n', op( A ) = A.
+*>
+*> TRANSA = 'T' or 't', op( A ) = A**T.
+*>
+*> TRANSA = 'C' or 'c', op( A ) = A**H.
+*> \endverbatim
+*>
+*> \param[in] TRANSB
+*> \verbatim
+*> TRANSB is CHARACTER*1
+*> On entry, TRANSB specifies the form of op( B ) to be used in
+*> the matrix multiplication as follows:
+*>
+*> TRANSB = 'N' or 'n', op( B ) = B.
+*>
+*> TRANSB = 'T' or 't', op( B ) = B**T.
+*>
+*> TRANSB = 'C' or 'c', op( B ) = B**H.
+*> \endverbatim
+*>
+*> \param[in] M
+*> \verbatim
+*> M is INTEGER
+*> On entry, M specifies the number of rows of the matrix
+*> op( A ) and of the matrix C. M must be at least zero.
+*> \endverbatim
+*>
+*> \param[in] N
+*> \verbatim
+*> N is INTEGER
+*> On entry, N specifies the number of columns of the matrix
+*> op( B ) and the number of columns of the matrix C. N must be
+*> at least zero.
+*> \endverbatim
+*>
+*> \param[in] K
+*> \verbatim
+*> K is INTEGER
+*> On entry, K specifies the number of columns of the matrix
+*> op( A ) and the number of rows of the matrix op( B ). K must
+*> be at least zero.
+*> \endverbatim
+*>
+*> \param[in] ALPHA
+*> \verbatim
+*> ALPHA is COMPLEX*16
+*> On entry, ALPHA specifies the scalar alpha.
+*> \endverbatim
+*>
+*> \param[in] A
+*> \verbatim
+*> A is COMPLEX*16 array, dimension ( LDA, ka ), where ka is
+*> k when TRANSA = 'N' or 'n', and is m otherwise.
+*> Before entry with TRANSA = 'N' or 'n', the leading m by k
+*> part of the array A must contain the matrix A, otherwise
+*> the leading k by m part of the array A must contain the
+*> matrix A.
+*> \endverbatim
+*>
+*> \param[in] LDA
+*> \verbatim
+*> LDA is INTEGER
+*> On entry, LDA specifies the first dimension of A as declared
+*> in the calling (sub) program. When TRANSA = 'N' or 'n' then
+*> LDA must be at least max( 1, m ), otherwise LDA must be at
+*> least max( 1, k ).
+*> \endverbatim
+*>
+*> \param[in] B
+*> \verbatim
+*> B is COMPLEX*16 array, dimension ( LDB, kb ), where kb is
+*> n when TRANSB = 'N' or 'n', and is k otherwise.
+*> Before entry with TRANSB = 'N' or 'n', the leading k by n
+*> part of the array B must contain the matrix B, otherwise
+*> the leading n by k part of the array B must contain the
+*> matrix B.
+*> \endverbatim
+*>
+*> \param[in] LDB
+*> \verbatim
+*> LDB is INTEGER
+*> On entry, LDB specifies the first dimension of B as declared
+*> in the calling (sub) program. When TRANSB = 'N' or 'n' then
+*> LDB must be at least max( 1, k ), otherwise LDB must be at
+*> least max( 1, n ).
+*> \endverbatim
+*>
+*> \param[in] BETA
+*> \verbatim
+*> BETA is COMPLEX*16
+*> On entry, BETA specifies the scalar beta. When BETA is
+*> supplied as zero then C need not be set on input.
+*> \endverbatim
+*>
+*> \param[in,out] C
+*> \verbatim
+*> C is COMPLEX*16 array, dimension ( LDC, N )
+*> Before entry, the leading m by n part of the array C must
+*> contain the matrix C, except when beta is zero, in which
+*> case C need not be set on entry.
+*> On exit, the array C is overwritten by the m by n matrix
+*> ( alpha*op( A )*op( B ) + beta*C ).
+*> \endverbatim
+*>
+*> \param[in] LDC
+*> \verbatim
+*> LDC is INTEGER
+*> On entry, LDC specifies the first dimension of C as declared
+*> in the calling (sub) program. LDC must be at least
+*> max( 1, m ).
+*> \endverbatim
+*
+* Authors:
+* ========
+*
+*> \author Univ. of Tennessee
+*> \author Univ. of California Berkeley
+*> \author Univ. of Colorado Denver
+*> \author NAG Ltd.
+*
+*> \date December 2016
+*
+*> \ingroup complex16_blas_level3
+*
+*> \par Further Details:
+* =====================
+*>
+*> \verbatim
+*>
+*> Level 3 Blas routine.
+*>
+*> -- Written on 8-February-1989.
+*> Jack Dongarra, Argonne National Laboratory.
+*> Iain Duff, AERE Harwell.
+*> Jeremy Du Croz, Numerical Algorithms Group Ltd.
+*> Sven Hammarling, Numerical Algorithms Group Ltd.
+*> \endverbatim
+*>
+* =====================================================================
+ SUBROUTINE ZGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC)
+*
+* -- Reference BLAS level3 routine (version 3.7.0) --
+* -- Reference BLAS is a software package provided by Univ. of Tennessee, --
+* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
+* December 2016
+*
+* .. Scalar Arguments ..
+ COMPLEX*16 ALPHA,BETA
+ INTEGER K,LDA,LDB,LDC,M,N
+ CHARACTER TRANSA,TRANSB
+* ..
+* .. Array Arguments ..
+ COMPLEX*16 A(LDA,*),B(LDB,*),C(LDC,*)
+* ..
+*
+* =====================================================================
+*
+* .. External Functions ..
+ LOGICAL LSAME
+ EXTERNAL LSAME
+* ..
+* .. External Subroutines ..
+ EXTERNAL XERBLA
+* ..
+* .. Intrinsic Functions ..
+ INTRINSIC DCONJG,MAX
+* ..
+* .. Local Scalars ..
+ COMPLEX*16 TEMP
+ INTEGER I,INFO,J,L,NCOLA,NROWA,NROWB
+ LOGICAL CONJA,CONJB,NOTA,NOTB
+* ..
+* .. Parameters ..
+ COMPLEX*16 ONE
+ PARAMETER (ONE= (1.0D+0,0.0D+0))
+ COMPLEX*16 ZERO
+ PARAMETER (ZERO= (0.0D+0,0.0D+0))
+* ..
+*
+* Set NOTA and NOTB as true if A and B respectively are not
+* conjugated or transposed, set CONJA and CONJB as true if A and
+* B respectively are to be transposed but not conjugated and set
+* NROWA, NCOLA and NROWB as the number of rows and columns of A
+* and the number of rows of B respectively.
+*
+ NOTA = LSAME(TRANSA,'N')
+ NOTB = LSAME(TRANSB,'N')
+ CONJA = LSAME(TRANSA,'C')
+ CONJB = LSAME(TRANSB,'C')
+ IF (NOTA) THEN
+ NROWA = M
+ NCOLA = K
+ ELSE
+ NROWA = K
+ NCOLA = M
+ END IF
+ IF (NOTB) THEN
+ NROWB = K
+ ELSE
+ NROWB = N
+ END IF
+*
+* Test the input parameters.
+*
+ INFO = 0
+ IF ((.NOT.NOTA) .AND. (.NOT.CONJA) .AND.
+ + (.NOT.LSAME(TRANSA,'T'))) THEN
+ INFO = 1
+ ELSE IF ((.NOT.NOTB) .AND. (.NOT.CONJB) .AND.
+ + (.NOT.LSAME(TRANSB,'T'))) THEN
+ INFO = 2
+ ELSE IF (M.LT.0) THEN
+ INFO = 3
+ ELSE IF (N.LT.0) THEN
+ INFO = 4
+ ELSE IF (K.LT.0) THEN
+ INFO = 5
+ ELSE IF (LDA.LT.MAX(1,NROWA)) THEN
+ INFO = 8
+ ELSE IF (LDB.LT.MAX(1,NROWB)) THEN
+ INFO = 10
+ ELSE IF (LDC.LT.MAX(1,M)) THEN
+ INFO = 13
+ END IF
+ IF (INFO.NE.0) THEN
+ CALL XERBLA('ZGEMM ',INFO)
+ RETURN
+ END IF
+*
+* Quick return if possible.
+*
+ IF ((M.EQ.0) .OR. (N.EQ.0) .OR.
+ + (((ALPHA.EQ.ZERO).OR. (K.EQ.0)).AND. (BETA.EQ.ONE))) RETURN
+*
+* And when alpha.eq.zero.
+*
+ IF (ALPHA.EQ.ZERO) THEN
+ IF (BETA.EQ.ZERO) THEN
+ DO 20 J = 1,N
+ DO 10 I = 1,M
+ C(I,J) = ZERO
+ 10 CONTINUE
+ 20 CONTINUE
+ ELSE
+ DO 40 J = 1,N
+ DO 30 I = 1,M
+ C(I,J) = BETA*C(I,J)
+ 30 CONTINUE
+ 40 CONTINUE
+ END IF
+ RETURN
+ END IF
+*
+* Start the operations.
+*
+ IF (NOTB) THEN
+ IF (NOTA) THEN
+*
+* Form C := alpha*A*B + beta*C.
+*
+ DO 90 J = 1,N
+ IF (BETA.EQ.ZERO) THEN
+ DO 50 I = 1,M
+ C(I,J) = ZERO
+ 50 CONTINUE
+ ELSE IF (BETA.NE.ONE) THEN
+ DO 60 I = 1,M
+ C(I,J) = BETA*C(I,J)
+ 60 CONTINUE
+ END IF
+ DO 80 L = 1,K
+ TEMP = ALPHA*B(L,J)
+ DO 70 I = 1,M
+ C(I,J) = C(I,J) + TEMP*A(I,L)
+ 70 CONTINUE
+ 80 CONTINUE
+ 90 CONTINUE
+ ELSE IF (CONJA) THEN
+*
+* Form C := alpha*A**H*B + beta*C.
+*
+ DO 120 J = 1,N
+ DO 110 I = 1,M
+ TEMP = ZERO
+ DO 100 L = 1,K
+ TEMP = TEMP + DCONJG(A(L,I))*B(L,J)
+ 100 CONTINUE
+ IF (BETA.EQ.ZERO) THEN
+ C(I,J) = ALPHA*TEMP
+ ELSE
+ C(I,J) = ALPHA*TEMP + BETA*C(I,J)
+ END IF
+ 110 CONTINUE
+ 120 CONTINUE
+ ELSE
+*
+* Form C := alpha*A**T*B + beta*C
+*
+ DO 150 J = 1,N
+ DO 140 I = 1,M
+ TEMP = ZERO
+ DO 130 L = 1,K
+ TEMP = TEMP + A(L,I)*B(L,J)
+ 130 CONTINUE
+ IF (BETA.EQ.ZERO) THEN
+ C(I,J) = ALPHA*TEMP
+ ELSE
+ C(I,J) = ALPHA*TEMP + BETA*C(I,J)
+ END IF
+ 140 CONTINUE
+ 150 CONTINUE
+ END IF
+ ELSE IF (NOTA) THEN
+ IF (CONJB) THEN
+*
+* Form C := alpha*A*B**H + beta*C.
+*
+ DO 200 J = 1,N
+ IF (BETA.EQ.ZERO) THEN
+ DO 160 I = 1,M
+ C(I,J) = ZERO
+ 160 CONTINUE
+ ELSE IF (BETA.NE.ONE) THEN
+ DO 170 I = 1,M
+ C(I,J) = BETA*C(I,J)
+ 170 CONTINUE
+ END IF
+ DO 190 L = 1,K
+ TEMP = ALPHA*DCONJG(B(J,L))
+ DO 180 I = 1,M
+ C(I,J) = C(I,J) + TEMP*A(I,L)
+ 180 CONTINUE
+ 190 CONTINUE
+ 200 CONTINUE
+ ELSE
+*
+* Form C := alpha*A*B**T + beta*C
+*
+ DO 250 J = 1,N
+ IF (BETA.EQ.ZERO) THEN
+ DO 210 I = 1,M
+ C(I,J) = ZERO
+ 210 CONTINUE
+ ELSE IF (BETA.NE.ONE) THEN
+ DO 220 I = 1,M
+ C(I,J) = BETA*C(I,J)
+ 220 CONTINUE
+ END IF
+ DO 240 L = 1,K
+ TEMP = ALPHA*B(J,L)
+ DO 230 I = 1,M
+ C(I,J) = C(I,J) + TEMP*A(I,L)
+ 230 CONTINUE
+ 240 CONTINUE
+ 250 CONTINUE
+ END IF
+ ELSE IF (CONJA) THEN
+ IF (CONJB) THEN
+*
+* Form C := alpha*A**H*B**H + beta*C.
+*
+ DO 280 J = 1,N
+ DO 270 I = 1,M
+ TEMP = ZERO
+ DO 260 L = 1,K
+ TEMP = TEMP + DCONJG(A(L,I))*DCONJG(B(J,L))
+ 260 CONTINUE
+ IF (BETA.EQ.ZERO) THEN
+ C(I,J) = ALPHA*TEMP
+ ELSE
+ C(I,J) = ALPHA*TEMP + BETA*C(I,J)
+ END IF
+ 270 CONTINUE
+ 280 CONTINUE
+ ELSE
+*
+* Form C := alpha*A**H*B**T + beta*C
+*
+ DO 310 J = 1,N
+ DO 300 I = 1,M
+ TEMP = ZERO
+ DO 290 L = 1,K
+ TEMP = TEMP + DCONJG(A(L,I))*B(J,L)
+ 290 CONTINUE
+ IF (BETA.EQ.ZERO) THEN
+ C(I,J) = ALPHA*TEMP
+ ELSE
+ C(I,J) = ALPHA*TEMP + BETA*C(I,J)
+ END IF
+ 300 CONTINUE
+ 310 CONTINUE
+ END IF
+ ELSE
+ IF (CONJB) THEN
+*
+* Form C := alpha*A**T*B**H + beta*C
+*
+ DO 340 J = 1,N
+ DO 330 I = 1,M
+ TEMP = ZERO
+ DO 320 L = 1,K
+ TEMP = TEMP + A(L,I)*DCONJG(B(J,L))
+ 320 CONTINUE
+ IF (BETA.EQ.ZERO) THEN
+ C(I,J) = ALPHA*TEMP
+ ELSE
+ C(I,J) = ALPHA*TEMP + BETA*C(I,J)
+ END IF
+ 330 CONTINUE
+ 340 CONTINUE
+ ELSE
+*
+* Form C := alpha*A**T*B**T + beta*C
+*
+ DO 370 J = 1,N
+ DO 360 I = 1,M
+ TEMP = ZERO
+ DO 350 L = 1,K
+ TEMP = TEMP + A(L,I)*B(J,L)
+ 350 CONTINUE
+ IF (BETA.EQ.ZERO) THEN
+ C(I,J) = ALPHA*TEMP
+ ELSE
+ C(I,J) = ALPHA*TEMP + BETA*C(I,J)
+ END IF
+ 360 CONTINUE
+ 370 CONTINUE
+ END IF
+ END IF
+*
+ RETURN
+*
+* End of ZGEMM .
+*
+ END
diff --git a/gcc/testsuite/gfortran.dg/c_ptr_tests_15.f90 b/gcc/testsuite/gfortran.dg/c_ptr_tests_15.f90
index 40d1ba3..ced8c59 100644
--- a/gcc/testsuite/gfortran.dg/c_ptr_tests_15.f90
+++ b/gcc/testsuite/gfortran.dg/c_ptr_tests_15.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-fwhole-file -fdump-tree-original" }
+! { dg-options "-fdump-tree-original" }
!
! PR fortran/43042 - fix ICE with c_null_ptr when using
! -fwhole-file (or -flto, which implies -fwhole-file).
diff --git a/gcc/testsuite/gfortran.dg/char_array_structure_constructor.f90 b/gcc/testsuite/gfortran.dg/char_array_structure_constructor.f90
index b675571..ae567dc 100644
--- a/gcc/testsuite/gfortran.dg/char_array_structure_constructor.f90
+++ b/gcc/testsuite/gfortran.dg/char_array_structure_constructor.f90
@@ -1,5 +1,4 @@
! { dg-do run }
-! { dg-options "-fwhole-file" }
!
! PR fortran/19107
! -fwhole-file flag added for PR fortran/44945
diff --git a/gcc/testsuite/gfortran.dg/class_17.f03 b/gcc/testsuite/gfortran.dg/class_17.f03
index 0c5c238..24b0e7b6 100644
--- a/gcc/testsuite/gfortran.dg/class_17.f03
+++ b/gcc/testsuite/gfortran.dg/class_17.f03
@@ -56,7 +56,7 @@ end MODULE error_stack_module
module b_module
implicit none
type::b_type
- class(not_yet_defined_type_type),pointer::b_component ! { dg-error "is a type that has not been declared" }
+ class(not_yet_defined_type_type),pointer::b_component ! { dg-error "has not been declared" }
end type b_type
end module b_module
diff --git a/gcc/testsuite/gfortran.dg/class_55.f90 b/gcc/testsuite/gfortran.dg/class_55.f90
index b47989f..e629698 100644
--- a/gcc/testsuite/gfortran.dg/class_55.f90
+++ b/gcc/testsuite/gfortran.dg/class_55.f90
@@ -5,7 +5,7 @@
! Contributed by Sylwester Arabas <slayoo@staszic.waw.pl>
type :: mpdata_t
- class(bcd_t), pointer :: bcx, bcy ! { dg-error "is a type that has not been declared" }
+ class(bcd_t), pointer :: bcx, bcy ! { dg-error "has not been declared" }
end type
type(mpdata_t) :: this
call this%bcx%fill_halos() ! { dg-error "is being used before it is defined" }
diff --git a/gcc/testsuite/gfortran.dg/class_assign_2.f90 b/gcc/testsuite/gfortran.dg/class_assign_2.f90
new file mode 100644
index 0000000..3b8db4a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/class_assign_2.f90
@@ -0,0 +1,22 @@
+! { dg-do link }
+!
+! PR 86484:[OOP] Undefined symbol when using polymorphic intrinsic assignment
+!
+! Contributed by Rich Townsend <townsend@astro.wisc.edu>
+
+program test_assign
+
+ implicit none
+
+ type :: foo_t
+ end type
+
+ type, extends (foo_t) :: bar_t
+ end type
+
+ class(foo_t), allocatable :: f
+ type(bar_t) :: b
+
+ f = b
+
+end
diff --git a/gcc/testsuite/gfortran.dg/class_assign_3.f90 b/gcc/testsuite/gfortran.dg/class_assign_3.f90
new file mode 100644
index 0000000..e51651e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/class_assign_3.f90
@@ -0,0 +1,9 @@
+! { dg-do link }
+!
+! PR 84543: undefined reference to __copy_INTEGER_4_.3788
+!
+! Contributed by Neil Carlson <neil.n.carlson@gmail.com>
+
+class(*), allocatable :: x
+x = 42
+end
diff --git a/gcc/testsuite/gfortran.dg/class_result_7.f90 b/gcc/testsuite/gfortran.dg/class_result_7.f90
new file mode 100644
index 0000000..066da54
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/class_result_7.f90
@@ -0,0 +1,36 @@
+! { dg-do compile }
+! { dg-options "-fdump-tree-original" }
+!
+! Test the fix for PR80477
+!
+! Contributed by Stefano Zaghi <stefano.zaghi@cnr.it>
+!
+module a_type_m
+ implicit none
+ type :: a_type_t
+ real :: x
+ endtype
+contains
+ subroutine assign_a_type(lhs, rhs)
+ type(a_type_t), intent(inout) :: lhs
+ type(a_type_t), intent(in) :: rhs
+ lhs%x = rhs%x
+ end subroutine
+
+ function add_a_type(lhs, rhs) result( res )
+ type(a_type_t), intent(in) :: lhs
+ type(a_type_t), intent(in) :: rhs
+ class(a_type_t), allocatable :: res
+ allocate (a_type_t :: res)
+ res%x = lhs%x + rhs%x
+ end function
+end module
+
+program polymorphic_operators_memory_leaks
+ use a_type_m
+ implicit none
+ type(a_type_t) :: a = a_type_t(1) , b = a_type_t(2)
+ call assign_a_type (a, add_a_type(a,b)) ! generated a memory leak
+end
+! { dg-final { scan-tree-dump-times "builtin_free" 1 "original" } }
+! { dg-final { scan-tree-dump-times "builtin_malloc" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/class_result_8.f90 b/gcc/testsuite/gfortran.dg/class_result_8.f90
new file mode 100644
index 0000000..573dd44
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/class_result_8.f90
@@ -0,0 +1,41 @@
+! { dg-do compile }
+! { dg-options "-fdump-tree-original" }
+!
+! Test the fix for the array version of PR80477
+!
+! Contributed by Stefano Zaghi <stefano.zaghi@cnr.it>
+!
+module a_type_m
+ implicit none
+ type :: a_type_t
+ real :: x
+ real, allocatable :: y(:)
+ endtype
+contains
+ subroutine assign_a_type(lhs, rhs)
+ type(a_type_t), intent(inout) :: lhs
+ type(a_type_t), intent(in) :: rhs(:)
+ lhs%x = rhs(1)%x + rhs(2)%x
+ end subroutine
+
+ function add_a_type(lhs, rhs) result( res )
+ type(a_type_t), intent(in) :: lhs
+ type(a_type_t), intent(in) :: rhs
+ class(a_type_t), allocatable :: res(:)
+ allocate (a_type_t :: res(2))
+ allocate (res(1)%y(1))
+ allocate (res(2)%y(1))
+ res(1)%x = lhs%x
+ res(2)%x = rhs%x
+ end function
+end module
+
+program polymorphic_operators_memory_leaks
+ use a_type_m
+ implicit none
+ type(a_type_t) :: a = a_type_t(1) , b = a_type_t(2)
+ call assign_a_type (a, add_a_type(a,b))
+ print *, a%x
+end
+! { dg-final { scan-tree-dump-times "builtin_free" 6 "original" } }
+! { dg-final { scan-tree-dump-times "builtin_malloc" 7 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/class_result_9.f90 b/gcc/testsuite/gfortran.dg/class_result_9.f90
new file mode 100644
index 0000000..10bc139
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/class_result_9.f90
@@ -0,0 +1,45 @@
+! { dg-do run }
+!
+! Test the fix for an additional bug found while fixing PR80477
+!
+! Contributed by Paul Thomas <pault@gcc.gnu.org>
+!
+module a_type_m
+ implicit none
+ type :: a_type_t
+ real :: x
+ real, allocatable :: y(:)
+ endtype
+contains
+ subroutine assign_a_type(lhs, rhs)
+ type(a_type_t), intent(inout) :: lhs
+ type(a_type_t), intent(in) :: rhs(:)
+ lhs%x = rhs(1)%x + rhs(2)%x
+ lhs%y = rhs(1)%y + rhs(2)%y
+ end subroutine
+
+ function add_a_type(lhs, rhs) result( res )
+ type(a_type_t), intent(in) :: lhs
+ type(a_type_t), intent(in) :: rhs
+ class(a_type_t), allocatable :: res(:)
+ allocate (a_type_t :: res(2))
+ allocate (res(1)%y(1), source = [10.0])
+ allocate (res(2)%y(1), source = [20.0])
+ res(1)%x = lhs%x + rhs%x
+ res(2)%x = rhs%x + rhs%x
+ end function
+end module
+
+program polymorphic_operators_memory_leaks
+ use a_type_m
+ implicit none
+ type(a_type_t) :: a = a_type_t(1) , b = a_type_t(2)
+ class(a_type_t), allocatable :: res(:)
+
+ res = add_a_type(a,b) ! Remarkably, this ICEd - found while debugging the PR.
+ call assign_a_type (a, res)
+ if (int (res(1)%x + res(2)%x) .ne. int (a%x)) stop 1
+ if (int (sum (res(1)%y + res(2)%y)) .ne. int (sum (a%y))) stop 1
+ deallocate (a%y)
+ deallocate (res)
+end
diff --git a/gcc/testsuite/gfortran.dg/coarray_lib_alloc_4.f90 b/gcc/testsuite/gfortran.dg/coarray_lib_alloc_4.f90
index c083788..d695faa 100644
--- a/gcc/testsuite/gfortran.dg/coarray_lib_alloc_4.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_lib_alloc_4.f90
@@ -38,7 +38,7 @@ program test_caf_alloc
deallocate(xx)
end
-! { dg-final { scan-tree-dump-times "_gfortran_caf_is_present \\(xx\\.token, 2 - \\(integer\\(kind=4\\)\\) xx\\.dim\\\[0\\\]\\.lbound, &caf_ref\\.\[0-9\]+\\)|_gfortran_caf_is_present \\(xx\\.token, 2 - xx\\.dim\\\[0\\\]\\.lbound, &caf_ref\\.\[0-9\]+\\)" 10 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_is_present \\(xx\\.token, \\(integer\\(kind=4\\)\\) \\(2 - xx\\.dim\\\[0\\\]\\.lbound\\), &caf_ref\\.\[0-9\]+\\)|_gfortran_caf_is_present \\(xx\\.token, 2 - xx\\.dim\\\[0\\\]\\.lbound, &caf_ref\\.\[0-9\]+\\)" 10 "original" } }
! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(\[0-9\]+, 1, &xx\\.token, \\(void \\*\\) &xx, 0B, 0B, 0\\)" 1 "original" } }
! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(\[0-9\]+, 7" 2 "original" } }
! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(\[0-9\]+, 8" 2 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/coarray_lock_7.f90 b/gcc/testsuite/gfortran.dg/coarray_lock_7.f90
index 1478c7a..363fb30 100644
--- a/gcc/testsuite/gfortran.dg/coarray_lock_7.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_lock_7.f90
@@ -35,12 +35,12 @@ end
! { dg-final { scan-tree-dump-times "_gfortran_caf_lock \\(caf_token.., 0, 0, 0B, 0B, 0B, 0\\);" 1 "original" } }
! { dg-final { scan-tree-dump-times "_gfortran_caf_unlock \\(caf_token.., 0, 0, 0B, 0B, 0\\);" 1 "original" } }
-! { dg-final { scan-tree-dump-times "_gfortran_caf_lock \\(caf_token.., \\(3 - \\(integer\\(kind=4\\)\\) parm...dim\\\[0\\\].lbound\\) \\+ \\(integer\\(kind=4\\)\\) \\(MAX_EXPR <parm...dim\\\[0\\\].ubound - parm...dim\\\[0\\\].lbound, -1> \\+ 1\\) \\* \\(3 - \\(integer\\(kind=4\\)\\) parm...dim\\\[1\\\].lbound\\), 0, 0B, &ii, 0B, 0\\);|_gfortran_caf_lock \\(caf_token.1, \\(3 - parm...dim\\\[0\\\].lbound\\) \\+ \\(MAX_EXPR <parm...dim\\\[0\\\].ubound - parm...dim\\\[0\\\].lbound, -1> \\+ 1\\) \\* \\(3 - parm...dim\\\[1\\\].lbound\\), 0, 0B, &ii, 0B, 0\\);" 1 "original" } }
-! { dg-final { scan-tree-dump-times "_gfortran_caf_unlock \\(caf_token.., \\(2 - \\(integer\\(kind=4\\)\\) parm...dim\\\[0\\\].lbound\\) \\+ \\(integer\\(kind=4\\)\\) \\(MAX_EXPR <parm...dim\\\[0\\\].ubound - parm...dim\\\[0\\\].lbound, -1> \\+ 1\\) \\* \\(3 - \\(integer\\(kind=4\\)\\) parm...dim\\\[1\\\].lbound\\), 0, &ii, 0B, 0\\);|_gfortran_caf_unlock \\(caf_token.., \\(2 - parm...dim\\\[0\\\].lbound\\) \\+ \\(MAX_EXPR <parm...dim\\\[0\\\].ubound - parm...dim\\\[0\\\].lbound, -1> \\+ 1\\) \\* \\(3 - parm...dim\\\[1\\\].lbound\\), 0, &ii, 0B, 0\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_lock \\(caf_token.., .*\\(\\(3 - parm...dim\\\[0\\\].lbound\\) \\+ \\(MAX_EXPR <parm...dim\\\[0\\\].ubound - parm...dim\\\[0\\\].lbound, -1> \\+ 1\\) \\* \\(3 - parm...dim\\\[1\\\].lbound\\)\\), 0, 0B, &ii, 0B, 0\\);|_gfortran_caf_lock \\(caf_token.1, \\(3 - parm...dim\\\[0\\\].lbound\\) \\+ \\(MAX_EXPR <parm...dim\\\[0\\\].ubound - parm...dim\\\[0\\\].lbound, -1> \\+ 1\\) \\* \\(3 - parm...dim\\\[1\\\].lbound\\), 0, 0B, &ii, 0B, 0\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_unlock \\(caf_token.., .*\\(\\(2 - parm...dim\\\[0\\\].lbound\\) \\+ \\(MAX_EXPR <parm...dim\\\[0\\\].ubound - parm...dim\\\[0\\\].lbound, -1> \\+ 1\\) \\* \\(3 - parm...dim\\\[1\\\].lbound\\)\\), 0, &ii, 0B, 0\\);|_gfortran_caf_unlock \\(caf_token.., \\(2 - parm...dim\\\[0\\\].lbound\\) \\+ \\(MAX_EXPR <parm...dim\\\[0\\\].ubound - parm...dim\\\[0\\\].lbound, -1> \\+ 1\\) \\* \\(3 - parm...dim\\\[1\\\].lbound\\), 0, &ii, 0B, 0\\);" 1 "original" } }
-! { dg-final { scan-tree-dump-times "_gfortran_caf_lock \\(three.token, 0, 5 - \\(integer\\(kind=4\\)\\) three.dim\\\[0\\\].lbound, &acquired.\[0-9\]+, 0B, 0B, 0\\);|_gfortran_caf_lock \\(three.token, 0, 5 - three.dim\\\[0\\\].lbound, &acquired.\[0-9\]+, 0B, 0B, 0\\);" 1 "original" } }
-! { dg-final { scan-tree-dump-times "_gfortran_caf_unlock \\(three.token, 0, 8 - \\(integer\\(kind=4\\)\\) three.dim\\\[0\\\].lbound, &ii, 0B, 0\\);|_gfortran_caf_unlock \\(three.token, 0, 8 - three.dim\\\[0\\\].lbound, &ii, 0B, 0\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_lock \\(three.token, 0, \\(integer\\(kind=4\\)\\) \\(5 - three.dim\\\[0\\\].lbound\\), &acquired.\[0-9\]+, 0B, 0B, 0\\);|_gfortran_caf_lock \\(three.token, 0, 5 - three.dim\\\[0\\\].lbound, &acquired.\[0-9\]+, 0B, 0B, 0\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_unlock \\(three.token, 0, \\(integer\\(kind=4\\)\\) \\(8 - three.dim\\\[0\\\].lbound\\), &ii, 0B, 0\\);|_gfortran_caf_unlock \\(three.token, 0, 8 - three.dim\\\[0\\\].lbound, &ii, 0B, 0\\);" 1 "original" } }
-! { dg-final { scan-tree-dump-times "_gfortran_caf_lock \\(four.token, 1 - \\(integer\\(kind=4\\)\\) four.dim\\\[0\\\].lbound, 7 - \\(integer\\(kind=4\\)\\) four.dim\\\[1\\\].lbound, &acquired.\[0-9\]+, &ii, 0B, 0\\);|_gfortran_caf_lock \\(four.token, 1 - four.dim\\\[0\\\].lbound, 7 - four.dim\\\[1\\\].lbound, &acquired.\[0-9\]+, &ii, 0B, 0\\);" 1 "original" } }
-! { dg-final { scan-tree-dump-times "_gfortran_caf_unlock \\(four.token, 2 - \\(integer\\(kind=4\\)\\) four.dim\\\[0\\\].lbound, 8 - \\(integer\\(kind=4\\)\\) four.dim\\\[1\\\].lbound, 0B, 0B, 0\\);|_gfortran_caf_unlock \\(four.token, 2 - four.dim\\\[0\\\].lbound, 8 - four.dim\\\[1\\\].lbound, 0B, 0B, 0\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_lock \\(four.token, .*\\(1 - four.dim\\\[0\\\].lbound\\), \\(integer\\(kind=4\\)\\) \\(7 - four.dim\\\[1\\\].lbound\\), &acquired.\[0-9\]+, &ii, 0B, 0\\);|_gfortran_caf_lock \\(four.token, 1 - four.dim\\\[0\\\].lbound, 7 - four.dim\\\[1\\\].lbound, &acquired.\[0-9\]+, &ii, 0B, 0\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_unlock \\(four.token, .*\\(2 - four.dim\\\[0\\\].lbound\\), \\(integer\\(kind=4\\)\\) \\(8 - four.dim\\\[1\\\].lbound\\), 0B, 0B, 0\\);|_gfortran_caf_unlock \\(four.token, 2 - four.dim\\\[0\\\].lbound, 8 - four.dim\\\[1\\\].lbound, 0B, 0B, 0\\);" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/deferred_character_21.f90 b/gcc/testsuite/gfortran.dg/deferred_character_21.f90
new file mode 100644
index 0000000..354c847
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/deferred_character_21.f90
@@ -0,0 +1,29 @@
+! { dg-do compile }
+! { dg-options "-O3" }
+!
+! Tests the fix for PR85954 in which the gimplifier could not determine
+! the space required for the dummy argument data types, when inlining the
+! subroutines.
+!
+! Contributed by G.Steinmetz <gscfq@t-online.de>
+!
+program p
+ character(kind=1,len=:), allocatable :: z(:)
+ allocate (z, source = ["xyz"])
+ print *, allocated(z), size(z), len(z), z
+ call s(z)
+ call t(z)
+contains
+ subroutine s(x)
+ character(kind=1,len=:), allocatable :: x(:)
+ x = ['abcd']
+ print *, allocated(x), size(x), len(x), x
+ end
+ subroutine t(x)
+ character(kind=1,len=:), allocatable :: x(:)
+ associate (y => x)
+ y = ['abc']
+ end associate
+ print *, allocated(x), size(x), len(x), x
+ end
+end
diff --git a/gcc/testsuite/gfortran.dg/deferred_character_22.f90 b/gcc/testsuite/gfortran.dg/deferred_character_22.f90
new file mode 100644
index 0000000..5037886
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/deferred_character_22.f90
@@ -0,0 +1,27 @@
+! { dg-do run }
+!
+! Test the fix for PR77325, which casued an ICE in the gimplifier. The
+! segafults in 'contains_struct_check' were found while diagnosing the PR.
+!
+! Contributed by Gerhard Steinmetz <gerhard.steinmetz.fortran@t-online.de>
+!
+program p
+ character(3), parameter :: a(3) = ['abc', 'def', 'ghi']
+ character(1), parameter :: c(3) = ['a', 'b', 'c']
+ character(:), allocatable :: z(:)
+ z = c([3,2]) ! Vector subscripts caused an iCE in the gimplifier.
+ if (any (z .ne. ['c', 'b'])) stop 1
+ z = c
+ if (any (z .ne. ['a', 'b', 'c'])) stop 2
+ z = c(2:1:-1)
+ if (any (z .ne. ['b', 'a'])) stop 3
+ z = c(3)
+ if (any (z .ne. ['c', 'c'])) stop 4
+ z = a([3,1,2])
+ if (any (z .ne. ['ghi', 'abc', 'def'])) stop 5
+ z = a(1:2)(2:3) ! Substrings caused a segfault in 'contains_struct_check'.
+ if (any (z .ne. ['bc', 'ef'])) stop 6
+ z = a([2,3,1])(2:3) ! ditto
+ if (any (z .ne. ['ef', 'hi', 'bc'])) stop 7
+ deallocate (z)
+end
diff --git a/gcc/testsuite/gfortran.dg/deferred_character_23.f90 b/gcc/testsuite/gfortran.dg/deferred_character_23.f90
new file mode 100644
index 0000000..c018334
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/deferred_character_23.f90
@@ -0,0 +1,22 @@
+! { dg-do run }
+!
+! Tests the fix for PR85603.
+!
+! Contributed by Walt Spector <w6ws@earthlink.net>
+!
+program strlen_bug
+ implicit none
+
+ character(:), allocatable :: strings(:)
+ integer :: maxlen
+
+ strings = [ character(32) :: &
+ 'short', &
+ 'somewhat longer' ]
+ maxlen = maxval (len_trim (strings))
+ if (maxlen .ne. 15) stop 1
+ strings = strings(:)(:maxlen) ! Used to ICE
+ if (any (strings .ne. ['short ','somewhat longer'])) stop 2
+
+ deallocate (strings) ! To check for memory leaks
+end program
diff --git a/gcc/testsuite/gfortran.dg/dtio_1.f90 b/gcc/testsuite/gfortran.dg/dtio_1.f90
index 7e5d166..c6f17d9 100644
--- a/gcc/testsuite/gfortran.dg/dtio_1.f90
+++ b/gcc/testsuite/gfortran.dg/dtio_1.f90
@@ -7,8 +7,8 @@
! to control execution.
! 3) Tests parsing of the optional vlist, passing in and using it to
! generate a user defined format string.
-! 4) Tests passing an iostat or iomsg out of libgfortranthe child procedure back to
-! the parent.
+! 4) Tests passing an iostat or iomsg out of the libgfortran child
+! procedure back to the parent.
!
MODULE p
USE ISO_FORTRAN_ENV
@@ -33,7 +33,6 @@ CONTAINS
INTEGER :: myios
udfmt='(*(g0))'
- iomsg = "SUCCESS"
iostat=0
if (iotype.eq."DT") then
if (size(vlist).ne.0) print *, 36
@@ -64,6 +63,7 @@ CONTAINS
if (iotype.eq."NAMELIST") then
if (size(vlist).ne.0) print *, 59
iostat=6000
+ iomsg = "NAMELIST not implemented in pwf"
endif
END SUBROUTINE pwf
@@ -78,7 +78,6 @@ CONTAINS
INTEGER :: myios
real :: areal
udfmt='(*(g0))'
- iomsg = "SUCCESS"
iostat=0
if (iotype.eq."DT") then
if (size(vlist).ne.0) print *, 36
@@ -109,8 +108,8 @@ CONTAINS
if (iotype.eq."NAMELIST") then
if (size(vlist).ne.0) print *, 59
iostat=6000
+ iomsg = "NAMELIST not implemented in prf"
endif
- !READ (UNIT = UNIT, FMT = *) dtv%name, dtv%age
END SUBROUTINE prf
END MODULE p
@@ -126,12 +125,12 @@ PROGRAM test
chairman%age=62
member%name="George"
member%age=42
- astring = "FAILURE"
+ astring = "SUCCESS"
write (10, "(DT'zeroth',3x, DT'three'(11,4,10),11x,DT'two'(8,2))", &
& iostat=myiostat, iomsg=astring) member, chairman, member
if (myiostat.ne.0) STOP 3
if (astring.ne."SUCCESS") STOP 4
- astring = "FAILURE"
+ astring = "SUCCESS"
write (10, *, iostat=myiostat, iomsg=astring) member, chairman, member
if (myiostat.ne.0) STOP 5
if (astring.ne."SUCCESS") STOP 6
@@ -141,7 +140,7 @@ PROGRAM test
chairman%age=99
member%name="bogus2"
member%age=66
- astring = "FAILURE"
+ astring = "SUCCESS"
read(10,"(DT'zeroth',3x, DT'three'(11,4,10),11x,DT'two'(8,2))") member, chairman, member
if (member%name.ne."George") STOP 7
if (chairman%name.ne." Charlie") STOP 8
@@ -151,12 +150,12 @@ PROGRAM test
chairman%age=99
member%name="bogus2"
member%age=66
- astring = "FAILURE"
+ astring = "SAME"
read (10, *, iostat=myiostat, iomsg=astring) member, chairman, member
! The user defined procedure reads to the end of the line/file, then finalizing the parent
! reads past, so we wrote a blank line above. User needs to address these nuances in their
! procedures. (subject to interpretation)
- if (astring.ne."SUCCESS") STOP 11
+ if (astring.ne."SAME" .or. myiostat.ne.0) STOP 11
if (member%name.ne."George") STOP 12
if (chairman%name.ne."Charlie") STOP 13
if (member%age.ne.42) STOP 14
diff --git a/gcc/testsuite/gfortran.dg/dtio_11.f90 b/gcc/testsuite/gfortran.dg/dtio_11.f90
index 1f148c3..cf93932 100644
--- a/gcc/testsuite/gfortran.dg/dtio_11.f90
+++ b/gcc/testsuite/gfortran.dg/dtio_11.f90
@@ -15,13 +15,13 @@ end
! PR77533 - used to ICE after error
module m2
type t
- type(unknown), pointer :: next ! { dg-error "is a type that has not been declared" }
+ type(unknown), pointer :: next ! { dg-error "has not been declared" }
contains
- procedure :: s
+ procedure :: s ! { dg-error "Non-polymorphic passed-object" }
generic :: write(formatted) => s
end type
contains
- subroutine s(x)
+ subroutine s(x) ! { dg-error "Too few dummy arguments" }
end
end
diff --git a/gcc/testsuite/gfortran.dg/elemental_function_2.f90 b/gcc/testsuite/gfortran.dg/elemental_function_2.f90
new file mode 100644
index 0000000..7836ce8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/elemental_function_2.f90
@@ -0,0 +1,40 @@
+! { dg-do compile }
+!
+! Test the fix for PR87239 in which the call to the elemental function
+! 'gettwo' was being added before the scalarization loop in the assignment.
+! Since the result temporary was being declared in the loop body, this
+! drove the gimplifier crazy. It is sufficient to compile this testcase
+! since it used to ICE.
+!
+! Contributed by Juergen Reuter <juergen.reuter@desy.de>
+!
+module test
+ implicit none
+contains
+
+ elemental function gettwo( s ) result( res )
+ character(*), intent(in) :: s
+ character(len(s)) :: res
+
+ res = s( 1 : 2 )
+ endfunction gettwo
+
+endmodule test
+
+program main
+ use test
+ implicit none
+ character(10) :: inp( 5 )
+ integer :: i
+
+ ! character(10), allocatable :: out(:) ! this works
+ character(:), allocatable :: out(:) ! this was stuffed
+
+ inp = [ 'aaa', 'bbb', 'ccc', 'ddd', 'eee' ]
+
+ out = gettwo( inp )
+
+ do i = 1, size (out, 1)
+ if (trim (out(i)) .ne. inp(i)(1:2)) stop 1
+ end do
+endprogram main
diff --git a/gcc/testsuite/gfortran.dg/elemental_function_3.f90 b/gcc/testsuite/gfortran.dg/elemental_function_3.f90
new file mode 100644
index 0000000..67bdd1e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/elemental_function_3.f90
@@ -0,0 +1,44 @@
+! { dg-do run }
+!
+! Test the fix for PR84109 in which the call to the elemental function
+! 'adjustl' was being added before the scalarization loop in the assignment.
+! Since the result temporary was being declared in the loop body, this
+! drove the gimplifier crazy. It is sufficient to compile this testcase
+! since it used to ICE. This is the intrinsic counterpart to PR87239,
+! which is tested for the absence of an ICE in elemental_function_2.f90.
+! In this fix, a further improvement was to keep scalar calls outside the
+! scalarization loop and this is tested with 'my_adjustl'.
+!
+! Contributed by Willem Vermin <wvermin@gmail.com>
+!
+program prog
+ implicit none
+ character(len=:), allocatable :: c(:)
+ integer :: cnt = 0
+
+ allocate(character(len=20) :: c(10))
+ c = " ab "
+ c = adjustl(c) ! Used to ICE
+ if (trim (c(1)) .ne. "ab") stop 1
+
+ c = my_adjustl (" abcdefg ")
+ if (trim (c(1)) .ne. "abcdefg") stop 2
+ if (cnt .ne. 1) stop 3 ! Outside the scalarization loop
+ if (size (c, 1) .ne. 10) stop 4
+ if (len (c) .ne. 20) stop 5
+
+ cnt = 0
+ c = my_adjustl ([" uv ", " xy "])
+ if (trim (c(2)) .ne. "xy") stop 6
+ if (cnt .ne. size (c, 1)) stop 7 ! Inside the scalarization loop
+ if (size (c, 1) .ne. 2) stop 8
+
+contains
+
+ impure elemental function my_adjustl(arg) result (res)
+ character(*), intent(in) :: arg
+ character(len = len (arg)) :: res
+ res = adjustl (arg)
+ cnt = cnt + 1 ! Test how many calls are made
+ end function
+end program
diff --git a/gcc/testsuite/gfortran.dg/f2003_inquire_1.f03 b/gcc/testsuite/gfortran.dg/f2003_inquire_1.f03
index e51f619..957cdae 100644
--- a/gcc/testsuite/gfortran.dg/f2003_inquire_1.f03
+++ b/gcc/testsuite/gfortran.dg/f2003_inquire_1.f03
@@ -7,10 +7,12 @@ logical :: vpending
open(10, file='mydata_f2003_inquire_1', asynchronous="yes", blank="null", &
& decimal="comma", encoding="utf-8", sign="plus")
+write (10,*, asynchronous="yes", id=vid) 'asdf'
+wait (10)
+
inquire(unit=10, round=sround, sign=ssign, size=vsize, id=vid, &
& pending=vpending, asynchronous=sasynchronous, decimal=sdecimal, &
& encoding=sencoding)
-
if (ssign.ne."PLUS") STOP 1
if (sasynchronous.ne."YES") STOP 2
if (sdecimal.ne."COMMA") STOP 3
diff --git a/gcc/testsuite/gfortran.dg/f2003_io_1.f03 b/gcc/testsuite/gfortran.dg/f2003_io_1.f03
index 8021d79..8c7fb4b 100644
--- a/gcc/testsuite/gfortran.dg/f2003_io_1.f03
+++ b/gcc/testsuite/gfortran.dg/f2003_io_1.f03
@@ -13,6 +13,7 @@ open(10, file='mydata_f2003_io_1', asynchronous="yes", blank="null")
write(10,'(10f8.3)', asynchronous="yes", decimal="comma", id=j) a
rewind(10)
read(10,'(10f8.3)', asynchronous="yes", decimal="comma", blank="zero") b
+wait(10)
if (any(b.ne.23.45)) STOP 1
c = 3.14
@@ -24,6 +25,7 @@ rewind(10)
write(10,'(10f8.3)', asynchronous="yes", decimal="point") a
rewind(10)
read(10,'(10f8.3)', asynchronous="yes", decimal="point") b
+wait (10)
if (any(b.ne.23.45)) STOP 3
wait(unit=10, err=25, iostat=istat, iomsg=msg, end=35, id=j)
diff --git a/gcc/testsuite/gfortran.dg/finalize_33.f90 b/gcc/testsuite/gfortran.dg/finalize_33.f90
new file mode 100644
index 0000000..3857e44
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/finalize_33.f90
@@ -0,0 +1,119 @@
+! { dg-do run }
+! { dg-options "-fdump-tree-original" }
+!
+! Tests the fix for PR87359 in which the finalization of
+! 'source=process%component%extract_mci_template()' in the allocation
+! of 'process%mci' caused invalid reads and freeing of already freed
+! memory. This test is a greatly reduced version of the original code.
+!
+! Contributed by Juergen Reuter <juergen.reuter@desy.de>
+!
+module mci_base
+ implicit none
+ private
+ public :: mci_t
+ public :: mci_midpoint_t
+ public :: cnt
+ integer :: cnt = 0
+ type, abstract :: mci_t
+ integer, dimension(:), allocatable :: chain
+ end type mci_t
+ type, extends (mci_t) :: mci_midpoint_t
+ contains
+ final :: mci_midpoint_final
+ end type mci_midpoint_t
+contains
+ IMPURE ELEMENTAL SUBROUTINE mci_midpoint_final(arg)
+ TYPE(mci_midpoint_t), INTENT(INOUT) :: arg
+ cnt = cnt + 1
+ END SUBROUTINE mci_midpoint_final
+end module mci_base
+
+!!!!!
+
+module process_config
+ use mci_base
+ implicit none
+ private
+ public :: process_component_t
+ type :: process_component_t
+ class(mci_t), allocatable :: mci_template
+ contains
+ procedure :: init => process_component_init
+ procedure :: extract_mci_template => process_component_extract_mci_template
+ end type process_component_t
+
+contains
+
+ subroutine process_component_init (component, mci_template)
+ class(process_component_t), intent(out) :: component
+ class(mci_t), intent(in), allocatable :: mci_template
+ if (allocated (mci_template)) &
+ allocate (component%mci_template, source = mci_template)
+ end subroutine process_component_init
+
+ function process_component_extract_mci_template (component) &
+ result (mci_template)
+ class(mci_t), allocatable :: mci_template
+ class(process_component_t), intent(in) :: component
+ if (allocated (component%mci_template)) &
+ allocate (mci_template, source = component%mci_template)
+ end function process_component_extract_mci_template
+end module process_config
+
+!!!!!
+
+module process
+ use mci_base
+ use process_config
+ implicit none
+ private
+ public :: process_t
+ type :: process_t
+ private
+ type(process_component_t) :: component
+ class(mci_t), allocatable :: mci
+ contains
+ procedure :: init_component => process_init_component
+ procedure :: setup_mci => process_setup_mci
+ end type process_t
+contains
+ subroutine process_init_component &
+ (process, mci_template)
+ class(process_t), intent(inout), target :: process
+ class(mci_t), intent(in), allocatable :: mci_template
+ call process%component%init (mci_template)
+ end subroutine process_init_component
+
+ subroutine process_setup_mci (process)
+ class(process_t), intent(inout) :: process
+ allocate (process%mci, source=process%component%extract_mci_template ())
+ end subroutine process_setup_mci
+
+end module process
+
+!!!!!
+
+program main_ut
+ use mci_base
+ use process, only: process_t
+ implicit none
+ call event_transforms_1 ()
+ if (cnt .ne. 4) stop 2
+contains
+
+ subroutine event_transforms_1 ()
+ class(mci_t), allocatable :: mci_template
+ type(process_t), allocatable, target :: process
+ allocate (process)
+ allocate (mci_midpoint_t :: mci_template)
+ call process%init_component (mci_template)
+ call process%setup_mci () ! generates 1 final call from call to extract_mci_template
+ if (cnt .ne. 1) stop 1
+ end subroutine event_transforms_1 ! generates 3 final calls to mci_midpoint_final:
+ ! (i) process%component%mci_template
+ ! (ii) process%mci
+ ! (iii) mci_template
+end program main_ut
+! { dg-final { scan-tree-dump-times "__builtin_malloc" 17 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_free" 20 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/generic_34.f90 b/gcc/testsuite/gfortran.dg/generic_34.f90
new file mode 100644
index 0000000..1bcbfa0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/generic_34.f90
@@ -0,0 +1,27 @@
+! { dg-do compile }
+!
+! PR 86116: [6/7/8/9 Regression] Ambiguous generic interface not recognised
+!
+! Contributed by martin <mscfd@gmx.net>
+
+module mod
+
+ type :: t
+ end type t
+
+ interface sub
+ module procedure s1
+ module procedure s2
+ end interface
+
+contains
+
+ subroutine s1(x) ! { dg-error "Ambiguous interfaces in generic interface" }
+ type(t) :: x
+ end subroutine
+
+ subroutine s2(x) ! { dg-error "Ambiguous interfaces in generic interface" }
+ class(*), allocatable :: x
+ end subroutine
+
+end
diff --git a/gcc/testsuite/gfortran.dg/generic_35.f90 b/gcc/testsuite/gfortran.dg/generic_35.f90
new file mode 100644
index 0000000..24ac270
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/generic_35.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+!
+! PR 86545: ICE in transfer_expr on invalid WRITE statement
+!
+! Contributed by Janus Weil <janus@gcc.gnu.org>
+
+module m
+
+ type tString
+ character(len=:), allocatable :: cs
+ end type
+
+ interface my_trim
+ module procedure trim_string
+ end interface
+
+contains
+
+ elemental function trim_string(self) result(str)
+ type(tString) :: str
+ class(tString), intent(in) :: self
+ end function
+
+end module
+
+
+program p
+ use m
+ type(tString) :: s
+ write(*,*) my_trim(s) ! { dg-error "cannot have ALLOCATABLE components" }
+end
diff --git a/gcc/testsuite/gfortran.dg/goacc/nested-parallelism.f90 b/gcc/testsuite/gfortran.dg/goacc/nested-parallelism.f90
new file mode 100644
index 0000000..6ebef6a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/nested-parallelism.f90
@@ -0,0 +1,51 @@
+! Verify the invalid gang, worker, vector parallelism error messages.
+
+program np
+ integer, parameter :: n = 100
+ integer :: i, j, k
+
+ !$acc parallel loop gang
+ do i = 1, n
+ !$acc loop gang ! { dg-error "gangs is not allowed inside another loop parallelized across gangs" }
+ do j = 1, n
+ end do
+
+ !$acc loop worker
+ do j = 1, n
+ end do
+
+ !$acc loop vector
+ do j = 1, n
+ end do
+ end do
+
+ !$acc parallel loop worker
+ do i = 1, n
+ !$acc loop gang ! { dg-error "gangs is not allowed inside loop parallelized across workers" }
+ do j = 1, n
+ end do
+
+ !$acc loop worker ! { dg-error "workers is not allowed inside another loop parallelized across workers" }
+ do j = 1, n
+ end do
+
+ !$acc loop vector
+ do j = 1, n
+ end do
+ end do
+
+ !$acc parallel loop vector
+ do i = 1, n
+ !$acc loop gang ! { dg-error "gangs is not allowed inside loop parallelized across vectors" }
+ do j = 1, n
+ end do
+
+ !$acc loop worker ! { dg-error "workers is not allowed inside another loop parallelized across vectors" }
+ do j = 1, n
+ end do
+
+ !$acc loop vector ! { dg-error "vectors is not allowed inside another loop parallelized across vectors" }
+ do j = 1, n
+ end do
+ end do
+end program np
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr47331.f90 b/gcc/testsuite/gfortran.dg/gomp/pr47331.f90
index 71713e0..6c29356 100644
--- a/gcc/testsuite/gfortran.dg/gomp/pr47331.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/pr47331.f90
@@ -1,6 +1,6 @@
! PR fortran/47331
! { dg-do compile }
-! { dg-options "-fopenmp -fwhole-file" }
+! { dg-options "-fopenmp" }
subroutine foo
!$omp parallel
diff --git a/gcc/testsuite/gfortran.dg/implicit_actual.f90 b/gcc/testsuite/gfortran.dg/implicit_actual.f90
index 108c0407..79258c8 100644
--- a/gcc/testsuite/gfortran.dg/implicit_actual.f90
+++ b/gcc/testsuite/gfortran.dg/implicit_actual.f90
@@ -14,7 +14,7 @@ end module global
program snafu
! use global
- implicit type (t3) (z)
+ implicit type (t3) (z) ! { dg-error "has not been declared" }
call foo (zin) ! { dg-error "defined|Type mismatch" }
diff --git a/gcc/testsuite/gfortran.dg/implied_do_io_6.f90 b/gcc/testsuite/gfortran.dg/implied_do_io_6.f90
new file mode 100644
index 0000000..ebc99b2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/implied_do_io_6.f90
@@ -0,0 +1,39 @@
+! { dg-do run }
+! { dg-options "-ffrontend-optimize" }
+! PR 86837 - this was mis-optimized by trying to turn this into an
+! array I/O statement.
+! Original test case by "Pascal".
+
+Program read_loop
+
+ implicit none
+
+ integer :: i, j
+
+ ! number of values per column
+ integer, dimension(3) :: nvalues
+ data nvalues / 1, 2, 4 /
+
+ ! values in a 1D array
+ real, dimension(7) :: one_d
+ data one_d / 1, 11, 12, 21, 22, 23, 24 /
+
+ ! where to store the data back
+ real, dimension(4, 3) :: two_d
+
+ ! 1 - write our 7 values in one block
+ open(unit=10, file="loop.dta", form="unformatted")
+ write(10) one_d
+ close(unit=10)
+
+ ! 2 - read them back in chosen cells of a 2D array
+ two_d = -9
+ open(unit=10, file="loop.dta", form="unformatted", status='old')
+ read(10) ((two_d(i,j), i=1,nvalues(j)), j=1,3)
+ close(unit=10, status='delete')
+
+ ! 4 - print the whole array, just in case
+
+ if (any(reshape(two_d,[12]) /= [1.,-9.,-9.,-9.,11.,12.,-9.,-9.,21.,22.,23.,24.])) call abort
+
+end Program read_loop
diff --git a/gcc/testsuite/gfortran.dg/inline_matmul_13.f90 b/gcc/testsuite/gfortran.dg/inline_matmul_13.f90
index 6338aad..8ccfdd5 100644
--- a/gcc/testsuite/gfortran.dg/inline_matmul_13.f90
+++ b/gcc/testsuite/gfortran.dg/inline_matmul_13.f90
@@ -44,4 +44,4 @@ program main
deallocate(calloc)
end program main
-! { dg-final { scan-tree-dump-times "_gfortran_matmul" 0 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_matmul" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/inline_matmul_15.f90 b/gcc/testsuite/gfortran.dg/inline_matmul_15.f90
index c822248..47da01c 100644
--- a/gcc/testsuite/gfortran.dg/inline_matmul_15.f90
+++ b/gcc/testsuite/gfortran.dg/inline_matmul_15.f90
@@ -9,4 +9,4 @@ program main
call random_number(b)
print *,matmul(a,b)
end program main
-! { dg-output "Fortran runtime error: Dimension of array B incorrect in MATMUL intrinsic.*" }
+! { dg-output "Fortran runtime error: Incorrect extent in argument B in MATMUL intrinsic in dimension 1" }
diff --git a/gcc/testsuite/gfortran.dg/inline_matmul_16.f90 b/gcc/testsuite/gfortran.dg/inline_matmul_16.f90
index 9d54094..580cb1a 100644
--- a/gcc/testsuite/gfortran.dg/inline_matmul_16.f90
+++ b/gcc/testsuite/gfortran.dg/inline_matmul_16.f90
@@ -58,4 +58,4 @@ program main
end do
end do
end program main
-! { dg-final { scan-tree-dump-times "_gfortran_matmul" 0 "optimized" } }
+! { dg-final { scan-tree-dump-times "_gfortran_matmul" 1 "optimized" } }
diff --git a/gcc/testsuite/gfortran.dg/inline_matmul_23.f90 b/gcc/testsuite/gfortran.dg/inline_matmul_23.f90
index 05633bc..bb7e868 100644
--- a/gcc/testsuite/gfortran.dg/inline_matmul_23.f90
+++ b/gcc/testsuite/gfortran.dg/inline_matmul_23.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-Og -fcheck=bounds -fdump-tree-optimized" }
+! { dg-options "-Og -ffrontend-optimize -fcheck=bounds -fdump-tree-optimized" }
! Check that bounds checking is done only before the matrix
! multiplication.
diff --git a/gcc/testsuite/gfortran.dg/intent_optimize_2.f90 b/gcc/testsuite/gfortran.dg/intent_optimize_2.f90
new file mode 100644
index 0000000..47632bb
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/intent_optimize_2.f90
@@ -0,0 +1,26 @@
+! { dg-do compile }
+! { dg-options "-O -fno-inline -fdump-tree-optimized -fdump-tree-original" }
+! PR fortran/41453
+! Check that there is one clobber in the *.original tree, plus that
+! the constant 123456789 has been removed due to the INTENT(OUT).
+
+module x
+implicit none
+contains
+ subroutine foo(a)
+ integer, intent(out) :: a
+ a = 42
+ end subroutine foo
+end module x
+
+program main
+ use x
+ implicit none
+ integer :: a
+ a = 123456789
+ call foo(a)
+ print *,a
+end program main
+
+! { dg-final { scan-tree-dump-times "123456789" 0 "optimized" } }
+! { dg-final { scan-tree-dump-times "CLOBBER" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/intent_out_10.f90 b/gcc/testsuite/gfortran.dg/intent_out_10.f90
new file mode 100644
index 0000000..82e928c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/intent_out_10.f90
@@ -0,0 +1,14 @@
+! { dg-do compile }
+! PR 87395 - this used to ICE
+module mo
+ integer, save :: x
+contains
+ subroutine foo
+ x = 42
+ call bar(x)
+ contains
+ subroutine bar(y)
+ integer, intent(out) :: y
+ end subroutine bar
+ end subroutine foo
+end module mo
diff --git a/gcc/testsuite/gfortran.dg/intent_out_11.f90 b/gcc/testsuite/gfortran.dg/intent_out_11.f90
new file mode 100644
index 0000000..c266385
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/intent_out_11.f90
@@ -0,0 +1,309 @@
+! { dg-do compile }
+! { dg-options "-cpp -fcoarray=lib" }
+! PR 87397 - this used to generate an ICE.
+
+! Coarray Distributed Transpose Test
+!
+! Copyright (c) 2012-2014, Sourcery, Inc.
+! All rights reserved.
+!
+! Redistribution and use in source and binary forms, with or without
+! modification, are permitted provided that the following conditions are met:
+! * Redistributions of source code must retain the above copyright
+! notice, this list of conditions and the following disclaimer.
+! * Redistributions in binary form must reproduce the above copyright
+! notice, this list of conditions and the following disclaimer in the
+! documentation and/or other materials provided with the distribution.
+! * Neither the name of the Sourcery, Inc., nor the
+! names of its contributors may be used to endorse or promote products
+! derived from this software without specific prior written permission.
+!
+! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+! ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+! WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+! DISCLAIMED. IN NO EVENT SHALL SOURCERY, INC., BE LIABLE FOR ANY
+! DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+! (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+! ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+! (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+!
+! Robodoc header:
+!****m* dist_transpose/run_size
+! NAME
+! run_size
+! SYNOPSIS
+! Encapsulate problem state, wall-clock timer interface, integer broadcasts, and a data copy.
+!******
+!================== test transposes with integer x,y,z values ===============================
+module run_size
+ use iso_fortran_env
+ implicit none
+
+ integer(int64), codimension[*] :: nx, ny, nz
+ integer(int64), codimension[*] :: my, mx, first_y, last_y, first_x, last_x
+ integer(int64) :: my_node, num_nodes
+ real(real64), codimension[*] :: tran_time
+
+
+contains
+
+!****s* run_size/broadcast_int
+! NAME
+! broadcast_int
+! SYNOPSIS
+! Broadcast a scalar coarray integer from image 1 to all other images.
+!******
+ subroutine broadcast_int( variable )
+ integer(int64), codimension[*] :: variable
+ integer(int64) :: i
+ if( my_node == 1 ) then
+ do i = 2, num_nodes; variable[i] = variable; end do
+ end if
+ end subroutine broadcast_int
+
+subroutine copy3( A,B, n1, sA1, sB1, n2, sA2, sB2, n3, sA3, sB3 )
+ implicit none
+ complex, intent(in) :: A(0:*)
+ complex, intent(out) :: B(0:*)
+ integer(int64), intent(in) :: n1, sA1, sB1
+ integer(int64), intent(in) :: n2, sA2, sB2
+ integer(int64), intent(in) :: n3, sA3, sB3
+ integer(int64) i,j,k
+
+ do k=0,n3-1
+ do j=0,n2-1
+ do i=0,n1-1
+ B(i*sB1+j*sB2+k*sB3) = A(i*sA1+j*sA2+k*sA3)
+ end do
+ end do
+ end do
+end subroutine copy3
+
+end module run_size
+
+!****e* dist_transpose/coarray_distributed_transpose
+! NAME
+! coarray_distributed_transpose
+! SYNOPSIS
+! This program tests the transpose routines used in Fourier-spectral simulations of homogeneous turbulence.
+! The data is presented to the physics routines as groups of y-z or x-z planes distributed among the images.
+! The (out-of-place) transpose routines do the x <--> y transposes required and consist of transposes within
+! data blocks (intra-image) and a transpose of the distribution of these blocks among the images (inter-image).
+!
+! Two methods are tested here:
+! RECEIVE: receive block from other image and transpose it
+! SEND: transpose block and send it to other image
+!
+! This code is the coarray analog of mpi_distributed_transpose.
+!******
+
+program coarray_distributed_transpose
+ !(***********************************************************************************************************
+ ! m a i n p r o g r a m
+ !***********************************************************************************************************)
+ use run_size
+ implicit none
+
+ complex, allocatable :: u(:,:,:,:)[:] ! u(nz,4,first_x:last_x,ny)[*] !(*-- ny = my * num_nodes --*)
+ complex, allocatable :: ur(:,:,:,:)[:] !ur(nz,4,first_y:last_y,nx/2)[*] !(*-- nx/2 = mx * num_nodes --*)
+ complex, allocatable :: bufr_X_Y(:,:,:,:)
+ complex, allocatable :: bufr_Y_X(:,:,:,:)
+ integer(int64) :: x, y, z, msg_size, iter
+
+ num_nodes = num_images()
+ my_node = this_image()
+
+ if( my_node == 1 ) then
+ !write(6,*) "nx,ny,nz : "; read(5,*) nx, ny, nz
+ nx=32; ny=32; nz=32
+ call broadcast_int( nx ); call broadcast_int( ny ); call broadcast_int( nz );
+ end if
+ sync all !-- other nodes wait for broadcast!
+
+
+ if ( mod(ny,num_nodes) == 0) then; my = ny / num_nodes
+ else; write(6,*) "node ", my_node, " ny not multiple of num_nodes"; error stop
+ end if
+
+ if ( mod(nx/2,num_nodes) == 0) then; mx = nx/2 / num_nodes
+ else; write(6,*) "node ", my_node, "nx/2 not multiple of num_nodes"; error stop
+ end if
+
+ first_y = (my_node-1)*my + 1; last_y = (my_node-1)*my + my
+ first_x = (my_node-1)*mx + 1; last_x = (my_node-1)*mx + mx
+
+ allocate ( u(nz , 4 , first_x:last_x , ny) [*] ) !(*-- y-z planes --*)
+ allocate ( ur(nz , 4 , first_y:last_y , nx/2)[*] ) !(*-- x-z planes --*)
+ allocate ( bufr_X_Y(nz,4,mx,my) )
+ allocate ( bufr_Y_X(nz,4,my,mx) )
+
+ msg_size = nz*4*mx*my !-- message size (complex data items)
+
+!--------- initialize data u (mx y-z planes per image) ----------
+
+ do x = first_x, last_x
+ do y = 1, ny
+ do z = 1, nz
+ u(z,1,x,y) = x
+ u(z,2,x,y) = y
+ u(z,3,x,y) = z
+ end do
+ end do
+ end do
+
+ tran_time = 0
+ do iter = 1, 2 !--- 2 transform pairs per second-order time step
+
+!--------- transpose data u -> ur (mx y-z planes to my x-z planes per image) --------
+
+ ur = 0
+
+ call transpose_X_Y
+
+!--------- test data ur (my x-z planes per image) ----------
+
+ do x = 1, nx/2
+ do y = first_y, last_y
+ do z = 1, nz
+ if ( real(ur(z,1,y,x)) /= x .or. real(ur(z,2,y,x)) /= y .or. real(ur(z,3,y,x)) /= z )then
+ write(6,fmt="(A,i3,3(6X,A,f7.3,i4))") "transpose_X_Y failed: image ", my_node &
+ , " X ",real(ur(z,1,y,x)),x, " Y ",real(ur(z,2,y,x)),y, " Z ", real(ur(z,3,y,x)),z
+ stop
+ end if
+ end do
+ end do
+ end do
+
+!--------- transpose data ur -> u (my x-z planes to mx y-z planes per image) --------
+
+ u = 0
+ call transpose_Y_X
+
+!--------- test data u (mx y-z planes per image) ----------
+
+ do x = first_x, last_x
+ do y = 1, ny
+ do z = 1, nz
+ if ( real(u(z,1,x,y)) /= x .or. real(u(z,2,x,y)) /= y .or. real(u(z,3,x,y)) /= z )then
+ write(6,fmt="(A,i3,3(6X,A,f7.3,i4))") "transpose_Y_X failed: image ", my_node &
+ , " X ",real(u(z,1,x,y)),x, " Y ",real(u(z,2,x,y)),y, " Z ", real(u(z,3,x,y)),z
+ stop
+ end if
+ end do
+ end do
+ end do
+ end do
+
+ sync all
+ if( my_node == 1 ) write(6,fmt="(A,f8.3)") "test passed: tran_time ", tran_time
+
+ deallocate ( bufr_X_Y ); deallocate ( bufr_Y_X )
+
+!========================= end of main executable =============================
+
+contains
+
+!------------- out-of-place transpose data_s --> data_r ----------------------------
+
+ subroutine transpose_X_Y
+
+ use run_size
+ implicit none
+
+ integer(int64) :: i,stage
+ real(real64) :: tmp
+
+ sync all !-- wait for other nodes to finish compute
+ call cpu_time(tmp)
+ tran_time = tran_time - tmp
+
+ call copy3 ( u(1,1,first_x,1+(my_node-1)*my) & !-- intra-node transpose
+ , ur(1,1,first_y,1+(my_node-1)*mx) & !-- no inter-node transpose needed
+ , nz*3, 1_8, 1_8 & !-- note: only 3 of 4 words needed
+ , mx, nz*4, nz*4*my &
+ , my, nz*4*mx, nz*4 )
+
+#define RECEIVE
+#ifdef RECEIVE
+
+ do stage = 1, num_nodes-1
+ i = 1 + mod( my_node-1+stage, num_nodes )
+ bufr_X_Y(:,:,:,:) = u(:,:,:,1+(my_node-1)*my:my_node*my)[i] !-- inter-node transpose to buffer
+ call copy3 ( bufr_X_Y, ur(1,1,first_y,1+(i-1)*mx) & !-- intra-node transpose from buffer
+ , nz*3, 1_8, 1_8 & !-- note: only 3 of 4 words needed
+ , mx, nz*4, nz*4*my &
+ , my, nz*4*mx, nz*4 )
+ end do
+
+#else
+
+ do stage = 1, num_nodes-1
+ i = 1 + mod( my_node-1+stage, num_nodes )
+ call copy3 ( u(1,1,first_x,1+(i-1)*my), bufr_Y_X & !-- intra-node transpose to buffer
+ , nz*3, 1_8, 1_8 &
+ , mx, nz*4, nz*4*my &
+ , my, nz*4*mx, nz*4 )
+ ur(:,:,:,1+(my_node-1)*mx:my_node*mx)[i] = bufr_Y_X(:,:,:,:) !-- inter-node transpose from buffer
+ end do
+
+#endif
+
+ sync all !-- wait for other nodes to finish transpose
+ call cpu_time(tmp)
+ tran_time = tran_time + tmp
+
+ end subroutine transpose_X_Y
+
+!------------- out-of-place transpose data_r --> data_s ----------------------------
+
+subroutine transpose_Y_X
+ use run_size
+ implicit none
+
+ integer(int64) :: i, stage
+ real(real64) :: tmp
+
+ sync all !-- wait for other nodes to finish compute
+ call cpu_time(tmp)
+ tran_time = tran_time - tmp
+
+ call copy3 ( ur(1,1,first_y,1+(my_node-1)*mx) & !-- intra-node transpose
+ , u(1,1,first_x,1+(my_node-1)*my) & !-- no inter-node transpose needed
+ , nz*4, 1_8, 1_8 & !-- note: all 4 words needed
+ , my, nz*4, nz*4*mx &
+ , mx, nz*4*my, nz*4 )
+
+#define RECEIVE
+#ifdef RECEIVE
+
+ do stage = 1, num_nodes-1
+ i = 1 + mod( my_node-1+stage, num_nodes )
+ bufr_Y_X(:,:,:,:) = ur(:,:,:,1+(my_node-1)*mx:my_node*mx)[i] !-- inter-node transpose to buffer
+ call copy3 ( bufr_Y_X, u(1,1,first_x,1+(i-1)*my) & !-- intra-node transpose from buffer
+ , nz*4, 1_8, 1_8 &
+ , my, nz*4, nz*4*mx &
+ , mx, nz*4*my, nz*4 )
+ end do
+
+#else
+
+ do stage = 1, num_nodes-1
+ i = 1 + mod( my_node-1+stage, num_nodes )
+ call copy3 ( ur(1,1,first_y,1+(i-1)*mx), bufr_X_Y & !-- intra-node transpose from buffer
+ , nz*4, 1_8, 1_8 &
+ , my, nz*4, nz*4*mx &
+ , mx, nz*4*my, nz*4 )
+ u(:,:,:,1+(my_node-1)*my:my_node*my)[i] = bufr_X_Y(:,:,:,:) !-- inter-node transpose from buffer
+ end do
+
+#endif
+
+ sync all !-- wait for other nodes to finish transpose
+ call cpu_time(tmp)
+ tran_time = tran_time + tmp
+
+ end subroutine transpose_Y_X
+
+
+end program coarray_distributed_transpose
diff --git a/gcc/testsuite/gfortran.dg/intent_out_12.f90 b/gcc/testsuite/gfortran.dg/intent_out_12.f90
new file mode 100644
index 0000000..e838bcb
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/intent_out_12.f90
@@ -0,0 +1,23 @@
+! { dg-do run }
+! PR fortran/87401 - this used to segfault at runtime.
+! Test case by Janus Weil.
+
+program assoc_intent_out
+
+ implicit none
+
+ real :: r
+
+ associate(o => r)
+ call sub(o)
+ end associate
+
+contains
+
+ subroutine sub(out)
+ real, intent(out) :: out
+ out = 0.0
+ end subroutine
+
+end
+
diff --git a/gcc/testsuite/gfortran.dg/interface_assignment_6.f90 b/gcc/testsuite/gfortran.dg/interface_assignment_6.f90
new file mode 100644
index 0000000..81171b4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/interface_assignment_6.f90
@@ -0,0 +1,30 @@
+! { dg-do compile }
+!
+! PR 45521: [F08] GENERIC resolution with ALLOCATABLE/POINTER and PROCEDURE
+!
+! Contributed by Janus Weil <janus@gcc.gnu.org>
+
+module inteface_assignment_6
+
+ type :: t
+ end type
+
+ ! this was rejected as ambiguous, but is valid in F08
+ interface assignment(=)
+ procedure testAlloc
+ procedure testPtr
+ end interface
+
+contains
+
+ subroutine testAlloc(obj, val)
+ type(t), allocatable, intent(out) :: obj
+ integer, intent(in) :: val
+ end subroutine
+
+ subroutine testPtr(obj, val)
+ type(t), pointer, intent(out) :: obj
+ integer, intent(in) :: val
+ end subroutine
+
+end
diff --git a/gcc/testsuite/gfortran.dg/iso_c_binding_only_2.f90 b/gcc/testsuite/gfortran.dg/iso_c_binding_only_2.f90
new file mode 100644
index 0000000..03fafe3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/iso_c_binding_only_2.f90
@@ -0,0 +1,14 @@
+! { dg-do compile }
+!
+! PR 87172: [9 Regression] Spurious "Derived type 'c_funptr' at (1) has not been declared" error after r263782
+!
+! Contributed by Dominique d'Humieres <dominiq@lps.ens.fr>
+
+module m1
+ use iso_c_binding, only: c_funptr
+end module
+
+module m2
+ use m1
+ use iso_c_binding
+end module
diff --git a/gcc/testsuite/gfortran.dg/lto/20091016-1_0.f90 b/gcc/testsuite/gfortran.dg/lto/20091016-1_0.f90
index 5e96e88..812ae9b 100644
--- a/gcc/testsuite/gfortran.dg/lto/20091016-1_0.f90
+++ b/gcc/testsuite/gfortran.dg/lto/20091016-1_0.f90
@@ -1,5 +1,5 @@
! { dg-lto-do link }
-! { dg-lto-options {{-flto -g -fPIC -r -nostdlib} {-O -flto -g -fPIC -r -nostdlib}} }
+! { dg-lto-options {{-flto -g -fPIC -r} {-O -flto -g -fPIC -r}} }
! { dg-extra-ld-options "-flinker-output=nolto-rel" }
FUNCTION makenumberstring(x)
diff --git a/gcc/testsuite/gfortran.dg/lto/pr79108_0.f90 b/gcc/testsuite/gfortran.dg/lto/pr79108_0.f90
index 58412af..9c87850 100644
--- a/gcc/testsuite/gfortran.dg/lto/pr79108_0.f90
+++ b/gcc/testsuite/gfortran.dg/lto/pr79108_0.f90
@@ -1,6 +1,6 @@
! { dg-lto-do link }
! { dg-lto-options {{ -Ofast -flto --param ggc-min-expand=0 --param ggc-min-heapsize=0 }} }
-! { dg-extra-ld-options "-r -nostdlib" }
+! { dg-extra-ld-options "-r" }
MODULE Errorcheck_mod
CONTAINS
diff --git a/gcc/testsuite/gfortran.dg/matmul_19.f90 b/gcc/testsuite/gfortran.dg/matmul_19.f90
new file mode 100644
index 0000000..c4549240
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/matmul_19.f90
@@ -0,0 +1,25 @@
+! { dg-do run }
+! { dg-options "-finline-matmul-limit=0" }
+! PR 86704 - this used to segfault.
+
+program testmaticovenasobeni
+implicit none
+
+ character(len=10) :: line
+ write (unit=line,fmt=*) testmatmul(120,1,3)
+
+ contains
+
+ function testmatmul(m,n,o)
+ integer, intent(in) :: m,n,o
+ real :: A(n,m),B(n,o),C(m,o)
+ logical :: testmatmul
+
+ call random_number(A)
+ call random_number(B)
+
+ C=matmul(transpose(A),B)
+ testmatmul=.true.
+ end function
+
+end program testmaticovenasobeni
diff --git a/gcc/testsuite/gfortran.dg/matmul_5.f90 b/gcc/testsuite/gfortran.dg/matmul_5.f90
index 5f14028..79de7bf 100644
--- a/gcc/testsuite/gfortran.dg/matmul_5.f90
+++ b/gcc/testsuite/gfortran.dg/matmul_5.f90
@@ -9,4 +9,4 @@ program main
call random_number(b)
print *,matmul(a,b)
end program main
-! { dg-output "Fortran runtime error: dimension of array B incorrect in MATMUL intrinsic.*" }
+! { dg-output "Fortran runtime error: Incorrect extent in argument B in MATMUL intrinsic in dimension 1" }
diff --git a/gcc/testsuite/gfortran.dg/matmul_blas_1.f b/gcc/testsuite/gfortran.dg/matmul_blas_1.f
new file mode 100644
index 0000000..6a88981
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/matmul_blas_1.f
@@ -0,0 +1,240 @@
+C { dg-do run }
+C { dg-options "-fcheck=bounds -fdump-tree-optimized -fblas-matmul-limit=1 -O -fexternal-blas" }
+C { dg-additional-sources blas_gemm_routines.f }
+C Test calling of BLAS routines
+
+ program main
+ call sub_s
+ call sub_d
+ call sub_c
+ call sub_z
+ end
+
+ subroutine sub_d
+ implicit none
+ real(8), dimension(3,2) :: a
+ real(8), dimension(2,3) :: at
+ real(8), dimension(2,4) :: b
+ real(8), dimension(4,2) :: bt
+ real(8), dimension(3,4) :: c
+ real(8), dimension(3,4) :: cres
+ real(8), dimension(:,:), allocatable :: c_alloc
+ data a / 2., -3., 5., -7., 11., -13./
+ data b /17., -23., 29., -31., 37., -39., 41., -47./
+ data cres /195., -304., 384., 275., -428., 548., 347., -540.,
+ & 692., 411., -640., 816./
+
+ c = matmul(a,b)
+ if (any (c /= cres)) stop 31
+
+ at = transpose(a)
+ c = (1.2,-2.2)
+ c = matmul(transpose(at), b)
+ if (any (c /= cres)) stop 32
+
+ bt = transpose(b)
+ c = (1.2,-2.1)
+ c = matmul(a, transpose(bt))
+ if (any (c /= cres)) stop 33
+
+ c_alloc = matmul(a,b)
+ if (any (c /= cres)) stop 34
+
+ at = transpose(a)
+ deallocate (c_alloc)
+ c = matmul(transpose(at), b)
+ if (any (c /= cres)) stop 35
+
+ bt = transpose(b)
+ allocate (c_alloc(20,20))
+ c = (1.2,-2.1)
+ c = matmul(a, transpose(bt))
+ if (any (c /= cres)) stop 36
+
+ end
+
+ subroutine sub_s
+ implicit none
+ real, dimension(3,2) :: a
+ real, dimension(2,3) :: at
+ real, dimension(2,4) :: b
+ real, dimension(4,2) :: bt
+ real, dimension(3,4) :: c
+ real, dimension(3,4) :: cres
+ real, dimension(:,:), allocatable :: c_alloc
+ data a / 2., -3., 5., -7., 11., -13./
+ data b /17., -23., 29., -31., 37., -39., 41., -47./
+ data cres /195., -304., 384., 275., -428., 548., 347., -540.,
+ & 692., 411., -640., 816./
+
+ c = matmul(a,b)
+ if (any (c /= cres)) stop 21
+
+ at = transpose(a)
+ c = (1.2,-2.2)
+ c = matmul(transpose(at), b)
+ if (any (c /= cres)) stop 22
+
+ bt = transpose(b)
+ c = (1.2,-2.1)
+ c = matmul(a, transpose(bt))
+ if (any (c /= cres)) stop 23
+
+ c_alloc = matmul(a,b)
+ if (any (c /= cres)) stop 24
+
+ at = transpose(a)
+ deallocate (c_alloc)
+ c = matmul(transpose(at), b)
+ if (any (c /= cres)) stop 25
+
+ bt = transpose(b)
+ allocate (c_alloc(20,20))
+ c = (1.2,-2.1)
+ c = matmul(a, transpose(bt))
+ if (any (c /= cres)) stop 26
+
+ end
+
+ subroutine sub_c
+ implicit none
+ complex, dimension(3,2) :: a
+ complex, dimension(2,3) :: at, ah
+ complex, dimension(2,4) :: b
+ complex, dimension(4,2) :: bt, bh
+ complex, dimension(3,4) :: c
+ complex, dimension(3,4) :: cres
+ complex, dimension(:,:), allocatable :: c_alloc
+
+ data a / (2.,-3.), (-5.,7.), (11.,-13.), (17.,19), (-23., -29),
+ & (-31., 37.)/
+
+ data b / (-41., 43.), (-47., 53.), (-59.,-61.), (-67., 71),
+ & ( 73.,79. ), (83.,-89.), (97.,-101.), (-107.,-109.)/
+ data cres /(-1759.,217.), (2522.,-358.), (-396.,-2376.),
+ & (-2789.,-11.),
+ & (4322.,202.), (-1992.,-4584.), (3485.,3.), (-5408.,-244.),
+ & (2550.,5750.), (143.,-4379.), (-478.,6794.), (7104.,-2952.) /
+
+ c = matmul(a,b)
+ if (any (c /= cres)) stop 1
+
+ at = transpose(a)
+ c = (1.2,-2.2)
+ c = matmul(transpose(at), b)
+ if (any (c /= cres)) stop 2
+
+ bt = transpose(b)
+ c = (1.2,-2.1)
+ c = matmul(a, transpose(bt))
+ if (any (c /= cres)) stop 3
+
+ ah = transpose(conjg(a))
+ c = (1.2,-2.2)
+ c = matmul(conjg(transpose(ah)), b)
+ if (any (c /= cres)) stop 4
+
+ bh = transpose(conjg(b))
+ c = (1.2,-2.2)
+ c = matmul(a, transpose(conjg(bh)))
+ if (any (c /= cres)) stop 5
+
+ c_alloc = matmul(a,b)
+ if (any (c /= cres)) stop 6
+
+ at = transpose(a)
+ deallocate (c_alloc)
+ c = matmul(transpose(at), b)
+ if (any (c /= cres)) stop 7
+
+ bt = transpose(b)
+ allocate (c_alloc(20,20))
+ c = (1.2,-2.1)
+ c = matmul(a, transpose(bt))
+ if (any (c /= cres)) stop 8
+
+ ah = transpose(conjg(a))
+ c = (1.2,-2.2)
+ c = matmul(conjg(transpose(ah)), b)
+ if (any (c /= cres)) stop 9
+
+ deallocate (c_alloc)
+ allocate (c_alloc(0,0))
+ bh = transpose(conjg(b))
+ c = (1.2,-2.2)
+ c = matmul(a, transpose(conjg(bh)))
+ if (any (c /= cres)) stop 10
+
+ end
+
+ subroutine sub_z
+ implicit none
+ complex(8), dimension(3,2) :: a
+ complex(8), dimension(2,3) :: at, ah
+ complex(8), dimension(2,4) :: b
+ complex(8), dimension(4,2) :: bt, bh
+ complex(8), dimension(3,4) :: c
+ complex(8), dimension(3,4) :: cres
+ complex(8), dimension(:,:), allocatable :: c_alloc
+
+ data a / (2.,-3.), (-5._8,7.), (11.,-13.), (17.,19),
+ & (-23., -29), (-31., 37.)/
+
+ data b / (-41., 43.), (-47., 53.), (-59.,-61.), (-67., 71),
+ & ( 73.,79. ), (83.,-89.), (97.,-101.), (-107.,-109.)/
+ data cres /(-1759.,217.), (2522.,-358.), (-396.,-2376.),
+ & (-2789.,-11.),
+ & (4322.,202.), (-1992.,-4584.), (3485.,3.), (-5408.,-244.),
+ & (2550.,5750.), (143.,-4379.), (-478.,6794.), (7104.,-2952.) /
+
+ c = matmul(a,b)
+ if (any (c /= cres)) stop 11
+
+ at = transpose(a)
+ c = (1.2,-2.2)
+ c = matmul(transpose(at), b)
+ if (any (c /= cres)) stop 12
+
+ bt = transpose(b)
+ c = (1.2,-2.1)
+ c = matmul(a, transpose(bt))
+ if (any (c /= cres)) stop 13
+
+ ah = transpose(conjg(a))
+ c = (1.2,-2.2)
+ c = matmul(conjg(transpose(ah)), b)
+ if (any (c /= cres)) stop 14
+
+ bh = transpose(conjg(b))
+ c = (1.2,-2.2)
+ c = matmul(a, transpose(conjg(bh)))
+ if (any (c /= cres)) stop 15
+
+ c_alloc = matmul(a,b)
+ if (any (c /= cres)) stop 16
+
+ at = transpose(a)
+ deallocate (c_alloc)
+ c = matmul(transpose(at), b)
+ if (any (c /= cres)) stop 17
+
+ bt = transpose(b)
+ allocate (c_alloc(20,20))
+ c = (1.2,-2.1)
+ c = matmul(a, transpose(bt))
+ if (any (c /= cres)) stop 18
+
+ ah = transpose(conjg(a))
+ c = (1.2,-2.2)
+ c = matmul(conjg(transpose(ah)), b)
+ if (any (c /= cres)) stop 19
+
+ deallocate (c_alloc)
+ allocate (c_alloc(0,0))
+ bh = transpose(conjg(b))
+ c = (1.2,-2.2)
+ c = matmul(a, transpose(conjg(bh)))
+ if (any (c /= cres)) stop 20
+
+ end
+! { dg-final { scan-tree-dump-times "_gfortran_matmul" 0 "optimized" } }
diff --git a/gcc/testsuite/gfortran.dg/matmul_bounds_10.f90 b/gcc/testsuite/gfortran.dg/matmul_bounds_10.f90
index 6608b49..3899246 100644
--- a/gcc/testsuite/gfortran.dg/matmul_bounds_10.f90
+++ b/gcc/testsuite/gfortran.dg/matmul_bounds_10.f90
@@ -13,4 +13,4 @@ program main
allocate(ret(4,3))
ret = matmul(a,transpose(b)) ! This should throw an error.
end program main
-! { dg-output "Fortran runtime error: Incorrect extent in return array in MATMUL intrinsic for dimension 1: is 4, should be 3" }
+! { dg-output "Fortran runtime error: Array bound mismatch for dimension 1 of array.*" }
diff --git a/gcc/testsuite/gfortran.dg/matmul_bounds_11.f90 b/gcc/testsuite/gfortran.dg/matmul_bounds_11.f90
index 9209760..ee52a7b 100644
--- a/gcc/testsuite/gfortran.dg/matmul_bounds_11.f90
+++ b/gcc/testsuite/gfortran.dg/matmul_bounds_11.f90
@@ -11,5 +11,5 @@ program main
res = matmul(a,b)
print *,res
end program main
-! { dg-output "Fortran runtime error: Dimension of array B incorrect in MATMUL intrinsic.*" }
+! { dg-output "Fortran runtime error: Incorrect extent in argument B in MATMUL intrinsic in dimension 1: is 3, should be 2" }
diff --git a/gcc/testsuite/gfortran.dg/matmul_bounds_13.f90 b/gcc/testsuite/gfortran.dg/matmul_bounds_13.f90
new file mode 100644
index 0000000..154b133
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/matmul_bounds_13.f90
@@ -0,0 +1,13 @@
+! { dg-do run }
+! { dg-options "-fcheck=bounds" }
+! { dg-shouldfail "Fortran runtime error: Incorrect extent in argument B in MATMUL intrinsic in dimension 1" }
+program main
+ real, dimension(:,:), allocatable :: a, b, c
+ character(len=100) :: line
+ allocate (a(3,2))
+ allocate (b(2,4))
+ call random_number(a)
+ call random_number(b)
+ write (unit=line, fmt=*) matmul(a,transpose(b))
+end program main
+! { dg-output "Fortran runtime error: Incorrect extent in argument B in MATMUL intrinsic in dimension 1" }
diff --git a/gcc/testsuite/gfortran.dg/matmul_bounds_14.f b/gcc/testsuite/gfortran.dg/matmul_bounds_14.f
new file mode 100644
index 0000000..4c8a515
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/matmul_bounds_14.f
@@ -0,0 +1,16 @@
+C { dg-do run }
+C { dg-options "-fno-realloc-lhs -fdump-tree-optimized -fcheck=bounds -fblas-matmul-limit=1 -O -fexternal-blas" }
+C { dg-shouldfail "Fortran runtime error: Array bound mismatch for dimension 2 of array." }
+C { dg-additional-sources blas_gemm_routines.f }
+
+ program main
+ real, dimension(3,2) :: a
+ real, dimension(2,3) :: b
+ real, dimension(:,:), allocatable :: ret
+ a = 1.0
+ b = 2.3
+ allocate(ret(3,2))
+ ret = matmul(a,b) ! This should throw an error.
+ end
+! { dg-output "Fortran runtime error: Array bound mismatch for dimension 2 of array.*" }
+! { dg-final { scan-tree-dump-times "_gfortran_matmul" 0 "optimized" } }
diff --git a/gcc/testsuite/gfortran.dg/matmul_bounds_15.f b/gcc/testsuite/gfortran.dg/matmul_bounds_15.f
new file mode 100644
index 0000000..db4627a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/matmul_bounds_15.f
@@ -0,0 +1,19 @@
+C { dg-do run }
+C { dg-options "-fdump-tree-optimized -fcheck=bounds -fblas-matmul-limit=1 -O -fexternal-blas" }
+C { dg-shouldfail "Fortran runtime error: Incorrect extent in argument B in MATMUL intrinsic in dimension 1.*" }
+C { dg-additional-sources blas_gemm_routines.f }
+ program main
+ character(len=20) :: line
+ integer :: n, m
+ real, dimension(3,2) :: a
+ real, dimension(:,:), allocatable :: b
+ real, dimension(:,:), allocatable :: ret
+ a = 1.0
+ line = '3 3'
+ read (unit=line,fmt=*) n, m
+ allocate (b(n,m))
+ b = 2.3
+ ret = matmul(a,b) ! This should throw an error.
+ end
+! { dg-output "Fortran runtime error: Incorrect extent in argument B in MATMUL intrinsic in dimension 1.*" }
+! { dg-final { scan-tree-dump-times "_gfortran_matmul" 0 "optimized" } }
diff --git a/gcc/testsuite/gfortran.dg/matmul_bounds_16.f b/gcc/testsuite/gfortran.dg/matmul_bounds_16.f
new file mode 100644
index 0000000..50e91ae
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/matmul_bounds_16.f
@@ -0,0 +1,20 @@
+C { dg-do run }
+C { dg-options "-fdump-tree-optimized -fcheck=bounds -fblas-matmul-limit=1 -O -fexternal-blas" }
+C { dg-shouldfail "Fortran runtime error: Incorrect extent in argument B in MATMUL intrinsic in dimension 1" }
+C { dg-additional-sources blas_gemm_routines.f }
+
+ program main
+ character(len=20) :: line
+ integer :: n, m
+ real, dimension(3,2) :: a
+ real, dimension(:,:), allocatable :: b
+ real, dimension(:,:), allocatable :: ret
+ a = 1.0
+ line = '4 3'
+ read (unit=line,fmt=*) n, m
+ allocate (b(n,m))
+ b = 2.3
+ ret = matmul(transpose(a),b) ! This should throw an error.
+ end
+! { dg-output "Fortran runtime error: Incorrect extent in argument B in MATMUL intrinsic in dimension 1.*" }
+! { dg-final { scan-tree-dump-times "_gfortran_matmul" 0 "optimized" } }
diff --git a/gcc/testsuite/gfortran.dg/matmul_bounds_2.f90 b/gcc/testsuite/gfortran.dg/matmul_bounds_2.f90
index 978751e7..7a1deb3 100644
--- a/gcc/testsuite/gfortran.dg/matmul_bounds_2.f90
+++ b/gcc/testsuite/gfortran.dg/matmul_bounds_2.f90
@@ -13,4 +13,4 @@ program main
allocate(ret(3,2))
ret = matmul(a,b) ! This should throw an error.
end program main
-! { dg-output "Fortran runtime error: Incorrect extent in return array in MATMUL intrinsic for dimension 2: is 2, should be 3" }
+! { dg-output "Fortran runtime error: Array bound mismatch for dimension 2 of array.*" }
diff --git a/gcc/testsuite/gfortran.dg/matmul_bounds_3.f90 b/gcc/testsuite/gfortran.dg/matmul_bounds_3.f90
index 4b80f8c..8c8ae434 100644
--- a/gcc/testsuite/gfortran.dg/matmul_bounds_3.f90
+++ b/gcc/testsuite/gfortran.dg/matmul_bounds_3.f90
@@ -13,4 +13,4 @@ program main
allocate(ret(2,3))
ret = matmul(a,b) ! This should throw an error.
end program main
-! { dg-output "Fortran runtime error: Incorrect extent in return array in MATMUL intrinsic for dimension 1: is 2, should be 3" }
+! { dg-output "Fortran runtime error: Array bound mismatch for dimension 1 of array" }
diff --git a/gcc/testsuite/gfortran.dg/matmul_bounds_4.f90 b/gcc/testsuite/gfortran.dg/matmul_bounds_4.f90
index 94add6c..2dac29f 100644
--- a/gcc/testsuite/gfortran.dg/matmul_bounds_4.f90
+++ b/gcc/testsuite/gfortran.dg/matmul_bounds_4.f90
@@ -13,4 +13,4 @@ program main
allocate(ret(3))
ret = matmul(a,b) ! This should throw an error.
end program main
-! { dg-output "Fortran runtime error: Incorrect extent in return array in MATMUL intrinsic: is 3, should be 2" }
+! { dg-output "Fortran runtime error: Array bound mismatch for dimension 1 of array" }
diff --git a/gcc/testsuite/gfortran.dg/matmul_bounds_5.f90 b/gcc/testsuite/gfortran.dg/matmul_bounds_5.f90
index 5261e8e4..d2013ea 100644
--- a/gcc/testsuite/gfortran.dg/matmul_bounds_5.f90
+++ b/gcc/testsuite/gfortran.dg/matmul_bounds_5.f90
@@ -13,4 +13,4 @@ program main
allocate(ret(3))
ret = matmul(a,b) ! This should throw an error.
end program main
-! { dg-output "Fortran runtime error: Incorrect extent in return array in MATMUL intrinsic: is 3, should be 2" }
+! { dg-output "Fortran runtime error: Array bound mismatch for dimension 1 of array" }
diff --git a/gcc/testsuite/gfortran.dg/matmul_bounds_8.f90 b/gcc/testsuite/gfortran.dg/matmul_bounds_8.f90
index 2764cf3..11f5887 100644
--- a/gcc/testsuite/gfortran.dg/matmul_bounds_8.f90
+++ b/gcc/testsuite/gfortran.dg/matmul_bounds_8.f90
@@ -13,4 +13,4 @@ program main
allocate(ret(3,2))
ret = matmul(a,transpose(b)) ! This should throw an error.
end program main
-! { dg-output "Fortran runtime error: Incorrect extent in return array in MATMUL intrinsic for dimension 2: is 2, should be 3" }
+! { dg-output "Fortran runtime error: Array bound mismatch for dimension 2 of array" }
diff --git a/gcc/testsuite/gfortran.dg/max_fmax_aarch64.f90 b/gcc/testsuite/gfortran.dg/max_expr.f90
index b818241..c00ad62 100644
--- a/gcc/testsuite/gfortran.dg/max_fmax_aarch64.f90
+++ b/gcc/testsuite/gfortran.dg/max_expr.f90
@@ -1,4 +1,4 @@
-! { dg-do compile { target aarch64*-*-* } }
+! { dg-do compile }
! { dg-options "-O2 -fdump-tree-optimized" }
subroutine foo (a, b, c, d, e, f, g, h)
@@ -12,4 +12,4 @@ subroutine foof (a, b, c, d, e, f, g, h)
end subroutine
-! { dg-final { scan-tree-dump-times "\.FMAX " 14 "optimized" } }
+! { dg-final { scan-tree-dump-times "MAX_EXPR " 14 "optimized" } }
diff --git a/gcc/testsuite/gfortran.dg/min_fmin_aarch64.f90 b/gcc/testsuite/gfortran.dg/min_expr.f90
index 009869b..5f32d50 100644
--- a/gcc/testsuite/gfortran.dg/min_fmin_aarch64.f90
+++ b/gcc/testsuite/gfortran.dg/min_expr.f90
@@ -1,4 +1,4 @@
-! { dg-do compile { target aarch64*-*-* } }
+! { dg-do compile }
! { dg-options "-O2 -fdump-tree-optimized" }
subroutine foo (a, b, c, d, e, f, g, h)
@@ -12,4 +12,4 @@ subroutine foof (a, b, c, d, e, f, g, h)
a = min (a, b, c, d, e, f, g, h)
end subroutine
-! { dg-final { scan-tree-dump-times "\.FMIN " 14 "optimized" } }
+! { dg-final { scan-tree-dump-times "MIN_EXPR " 14 "optimized" } }
diff --git a/gcc/testsuite/gfortran.dg/modulo_check.f90 b/gcc/testsuite/gfortran.dg/modulo_check.f90
new file mode 100644
index 0000000..8819a2f8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/modulo_check.f90
@@ -0,0 +1,8 @@
+! { dg-do compile }
+! Test checks on modulo with p == 0
+program p
+ logical :: a(2) = (modulo([2,3],0) == 0) ! { dg-error "shall not be zero" }
+ integer :: b = count(modulo([2,3],0) == 0) ! { dg-error "shall not be zero" }
+ integer :: c = all(modulo([2,3],0) == 0) ! { dg-error "shall not be zero" }
+ integer :: d = any(modulo([2,3],0) == 0) ! { dg-error "shall not be zero" }
+end program
diff --git a/gcc/testsuite/gfortran.dg/nan_1.f90 b/gcc/testsuite/gfortran.dg/nan_1.f90
index e64b4ce..1b39cc1 100644
--- a/gcc/testsuite/gfortran.dg/nan_1.f90
+++ b/gcc/testsuite/gfortran.dg/nan_1.f90
@@ -66,35 +66,12 @@ program test
if (isinf(-nan) .or. isinf(-large) .or. .not. isinf(-inf)) STOP 4
! Check that MIN and MAX behave correctly
- if (max(2.0, nan) /= 2.0) STOP 5
- if (min(2.0, nan) /= 2.0) STOP 6
- if (max(nan, 2.0) /= 2.0) STOP 7
- if (min(nan, 2.0) /= 2.0) STOP 8
-
- if (max(2.d0, nan) /= 2.d0) STOP 9! { dg-warning "Extension: Different type kinds" }
- if (min(2.d0, nan) /= 2.d0) STOP 10! { dg-warning "Extension: Different type kinds" }
- if (max(nan, 2.d0) /= 2.d0) STOP 11! { dg-warning "Extension: Different type kinds" }
- if (min(nan, 2.d0) /= 2.d0) STOP 12! { dg-warning "Extension: Different type kinds" }
if (.not. isnan(min(nan,nan))) STOP 13
if (.not. isnan(max(nan,nan))) STOP 14
! Same thing, with more arguments
- if (max(3.0, 2.0, nan) /= 3.0) STOP 15
- if (min(3.0, 2.0, nan) /= 2.0) STOP 16
- if (max(3.0, nan, 2.0) /= 3.0) STOP 17
- if (min(3.0, nan, 2.0) /= 2.0) STOP 18
- if (max(nan, 3.0, 2.0) /= 3.0) STOP 19
- if (min(nan, 3.0, 2.0) /= 2.0) STOP 20
-
- if (max(3.d0, 2.d0, nan) /= 3.d0) STOP 21! { dg-warning "Extension: Different type kinds" }
- if (min(3.d0, 2.d0, nan) /= 2.d0) STOP 22! { dg-warning "Extension: Different type kinds" }
- if (max(3.d0, nan, 2.d0) /= 3.d0) STOP 23! { dg-warning "Extension: Different type kinds" }
- if (min(3.d0, nan, 2.d0) /= 2.d0) STOP 24! { dg-warning "Extension: Different type kinds" }
- if (max(nan, 3.d0, 2.d0) /= 3.d0) STOP 25! { dg-warning "Extension: Different type kinds" }
- if (min(nan, 3.d0, 2.d0) /= 2.d0) STOP 26! { dg-warning "Extension: Different type kinds" }
-
if (.not. isnan(min(nan,nan,nan))) STOP 27
if (.not. isnan(max(nan,nan,nan))) STOP 28
if (.not. isnan(min(nan,nan,nan,nan))) STOP 29
@@ -105,20 +82,8 @@ program test
! Large values, INF and NaNs
if (.not. isinf(max(large, inf))) STOP 33
if (isinf(min(large, inf))) STOP 34
- if (.not. isinf(max(nan, large, inf))) STOP 35
- if (isinf(min(nan, large, inf))) STOP 36
- if (.not. isinf(max(large, nan, inf))) STOP 37
- if (isinf(min(large, nan, inf))) STOP 38
- if (.not. isinf(max(large, inf, nan))) STOP 39
- if (isinf(min(large, inf, nan))) STOP 40
if (.not. isinf(min(-large, -inf))) STOP 41
if (isinf(max(-large, -inf))) STOP 42
- if (.not. isinf(min(nan, -large, -inf))) STOP 43
- if (isinf(max(nan, -large, -inf))) STOP 44
- if (.not. isinf(min(-large, nan, -inf))) STOP 45
- if (isinf(max(-large, nan, -inf))) STOP 46
- if (.not. isinf(min(-large, -inf, nan))) STOP 47
- if (isinf(max(-large, -inf, nan))) STOP 48
end program test
diff --git a/gcc/testsuite/gfortran.dg/pointer_array_10.f90 b/gcc/testsuite/gfortran.dg/pointer_array_10.f90
new file mode 100644
index 0000000..4e7b140
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pointer_array_10.f90
@@ -0,0 +1,27 @@
+! { dg-do run }
+!
+! Test the fix for PR87336, in which the 'span' field of the array
+! descriptor, passed to 'show', was not set.
+!
+! Contributed by Juergen Reuter <juergen.reuter@desy.de> following
+! a posting to clf by 'Spectrum'.
+!
+program main
+ implicit none
+ integer, target :: a( 2:4 )
+
+ a = [2,3,4]
+! print *, "a [before] = ", a
+ call show( a )
+! print *, "a [after] = ", a
+ if (any (a .ne. [200,300,400])) stop 1
+
+contains
+ subroutine show( arr )
+ integer, pointer, intent(in) :: arr(:)
+! print *, "arr = ", arr
+! print *, "bounds = ", lbound(arr), ubound(arr)
+ arr(:) = [200,300,400]
+! print *, "arr2= ", arr
+ end subroutine show
+ end program
diff --git a/gcc/testsuite/gfortran.dg/pr40999.f b/gcc/testsuite/gfortran.dg/pr40999.f
index b6fa85a..7ebb632 100644
--- a/gcc/testsuite/gfortran.dg/pr40999.f
+++ b/gcc/testsuite/gfortran.dg/pr40999.f
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-O3 -fwhole-file" }
+! { dg-options "-O3" }
SUBROUTINE ZLARFG( ALPHA )
COMPLEX*16 ZLADIV
diff --git a/gcc/testsuite/gfortran.dg/pr41011.f b/gcc/testsuite/gfortran.dg/pr41011.f
index 4ad4a8f..83e85fb 100644
--- a/gcc/testsuite/gfortran.dg/pr41011.f
+++ b/gcc/testsuite/gfortran.dg/pr41011.f
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-O3 -fwhole-file" }
+! { dg-options "-O3" }
CALL UVSET(NX,NY,NZ,HVAR,ZET,NP,DZ,DKM,UM,VM,UG,VG,TM,DCDX, ! { dg-warning "Rank mismatch" }
*ITY,ISH,NSMT,F)
CALL DCTDX(NX,NY,NX1,NFILT,C(MLAG),DCDX(MLAG),HELP,HELPA,
diff --git a/gcc/testsuite/gfortran.dg/pr42051.f03 b/gcc/testsuite/gfortran.dg/pr42051.f03
index 7a5be63..8f30e32 100644
--- a/gcc/testsuite/gfortran.dg/pr42051.f03
+++ b/gcc/testsuite/gfortran.dg/pr42051.f03
@@ -1,5 +1,4 @@
! { dg-do compile }
-! { dg-options "-fno-whole-file" }
!
! PR fortran/42051
! PR fortran/44064
diff --git a/gcc/testsuite/gfortran.dg/pr46804.f90 b/gcc/testsuite/gfortran.dg/pr46804.f90
index 9297b73..38e4a7e4 100644
--- a/gcc/testsuite/gfortran.dg/pr46804.f90
+++ b/gcc/testsuite/gfortran.dg/pr46804.f90
@@ -1,6 +1,6 @@
! PR rtl-optimization/46804
! { dg-do run }
-! { dg-options "-O -fPIC -fexpensive-optimizations -fgcse -foptimize-register-move -fpeel-loops -fno-tree-loop-optimize" }
+! { dg-options "-O -fPIC -fexpensive-optimizations -fgcse -fpeel-loops -fno-tree-loop-optimize" }
program main
integer, parameter :: n1 = 2, n2 = 3, n3 = 4, slen = 3
diff --git a/gcc/testsuite/gfortran.dg/pr83149_1.f90 b/gcc/testsuite/gfortran.dg/pr83149_1.f90
index 3a8f5d5..5b00996 100644
--- a/gcc/testsuite/gfortran.dg/pr83149_1.f90
+++ b/gcc/testsuite/gfortran.dg/pr83149_1.f90
@@ -1,6 +1,5 @@
! Compiled with pr83149.f90
! { dg-do run }
-! { dg-options "-fno-whole-file" }
! { dg-compile-aux-modules "pr83149.f90" }
! { dg-additional-sources pr83149.f90 }
!
diff --git a/gcc/testsuite/gfortran.dg/pr83149_b.f90 b/gcc/testsuite/gfortran.dg/pr83149_b.f90
index f67ffd9..9013617 100644
--- a/gcc/testsuite/gfortran.dg/pr83149_b.f90
+++ b/gcc/testsuite/gfortran.dg/pr83149_b.f90
@@ -1,6 +1,5 @@
! Compiled with pr83149_a.f90
! { dg-do run }
-! { dg-options "-fno-whole-file" }
! { dg-compile-aux-modules "pr83149_a.f90" }
! { dg-additional-sources pr83149_a.f90 }
!
diff --git a/gcc/testsuite/gfortran.dg/pr86328.f90 b/gcc/testsuite/gfortran.dg/pr86328.f90
new file mode 100644
index 0000000..dfa0e06
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr86328.f90
@@ -0,0 +1,49 @@
+! { dg-do run }
+!
+! Test the fix for PR86328 in which temporaries were not being
+! assigned for array component references.
+!
+! Contributed by Martin <mscfd@gmx.net>
+!
+program ptr_alloc
+
+ type :: t
+ class(*), allocatable :: val
+ end type
+
+ type :: list
+ type(t), dimension(:), pointer :: ll
+ end type
+
+ integer :: i
+ type(list) :: a
+
+ allocate(a%ll(1:2))
+ do i = 1,2
+ allocate(a%ll(i)%val, source=i)
+ end do
+
+ do i = 1,2
+ call rrr(a, i)
+ end do
+
+ do i = 1,2
+ deallocate(a%ll(i)%val)
+ end do
+ deallocate (a%ll)
+contains
+
+ subroutine rrr(a, i)
+ type(list), intent(in) :: a
+ class(*), allocatable :: c
+ integer :: i
+
+ allocate(c, source=a%ll(i)%val)
+ select type (c)
+ type is (integer)
+ if (c .ne. i) stop 1
+ end select
+
+ end subroutine
+
+end
diff --git a/gcc/testsuite/gfortran.dg/pr86760.f90 b/gcc/testsuite/gfortran.dg/pr86760.f90
new file mode 100644
index 0000000..e75b47c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr86760.f90
@@ -0,0 +1,57 @@
+! { dg-do run }
+!
+! Test the fix for PR86760 in which temporaries were not being
+! assigned for array component references.
+!
+! Contributed by Chris Hansen <hansec@uw.edu>
+!
+MODULE test_nesting_mod
+ IMPLICIT NONE
+ TYPE :: test_obj1
+ CONTAINS
+ PROCEDURE :: destroy
+ END TYPE
+
+ TYPE :: obj_ptr
+ CLASS(test_obj1), POINTER :: f => NULL()
+ END TYPE
+
+ TYPE :: obj_container
+ TYPE(obj_ptr), POINTER, DIMENSION(:) :: v => NULL()
+ END TYPE
+
+ integer :: ctr = 0
+
+CONTAINS
+
+ SUBROUTINE destroy(self)
+ CLASS(test_obj1), INTENT(INOUT):: self
+ ctr = ctr + 1
+ END SUBROUTINE
+
+ SUBROUTINE container_destroy(self)
+ type(obj_container), INTENT(INOUT) :: self
+ INTEGER :: i
+ DO i=1,ubound(self%v,1)
+ CALL self%v(i)%f%destroy()
+ END DO
+ END SUBROUTINE
+
+END MODULE
+
+
+PROGRAM test_nesting_ptr
+ USE test_nesting_mod
+ IMPLICIT NONE
+ INTEGER :: i
+ INTEGER, PARAMETER :: n = 2
+ TYPE(obj_container) :: var
+
+ ALLOCATE(var%v(n))
+ DO i=1,n
+ ALLOCATE(test_obj1::var%v(i)%f)
+ END DO
+ CALL container_destroy(var)
+
+ if (ctr .ne. 2) stop 1
+END
diff --git a/gcc/testsuite/gfortran.dg/pr87117.f90 b/gcc/testsuite/gfortran.dg/pr87117.f90
new file mode 100644
index 0000000..afca653
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr87117.f90
@@ -0,0 +1,14 @@
+! { dg-do compile }
+! { dg-options "-O" }
+program p
+ real(4) :: a, b
+ integer(4) :: n, m
+ equivalence (a, n)
+ a = 1024.0
+ m = 8
+ a = 1024.0
+ b = set_exponent(a, m)
+ n = 8
+ a = f(a, n)
+ b = set_exponent(a, m)
+end
diff --git a/gcc/testsuite/gfortran.dg/pr87217.f b/gcc/testsuite/gfortran.dg/pr87217.f
new file mode 100644
index 0000000..163a276
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr87217.f
@@ -0,0 +1,32 @@
+! { dg-do compile }
+! { dg-options "-O3" }
+ implicit real*8 (a-h,o-z)
+ common clop6(3),dps(6),aml6(6,6)
+ dimension y1(3)
+ dimension dclo(3)
+ dimension dx(3),dy(3)
+ save
+ do 80 ii=1,itco
+ y1(3)=dps(1)
+ do 40 l=1,3
+ dy(l)=clop6(l)-y1(l)
+ 40 continue
+ dczp=abs(dy(3))
+ if(dcx.le.c1m10.and.dcz.le.c1m10.and.dcxp.le.c1m10.and.dczp
+ + .le.c1m10.and.dcy.le.c1m10.and.dcyp.le.c1m10) goto 90
+ 80 continue
+ write(6) itco
+ ii=itco
+ 90 continue
+ if(ii.ne.itco) then
+ do 65 k=1,3
+ do 55 j=1,3
+ jj=2*j
+ kk=2*k
+ dclo(k)=aml6(kk-1,jj-1)*dx(j)+dclo(k)
+ dclo(k)=aml6(kk-1,jj)*dy(j)+dclo(k)
+ 55 continue
+ 65 continue
+ endif
+ end
+
diff --git a/gcc/testsuite/gfortran.dg/predict-1.f90 b/gcc/testsuite/gfortran.dg/predict-1.f90
index a3feea9..5360c61 100644
--- a/gcc/testsuite/gfortran.dg/predict-1.f90
+++ b/gcc/testsuite/gfortran.dg/predict-1.f90
@@ -14,4 +14,4 @@ end do
end subroutine test
-! { dg-final { scan-tree-dump-times "Fortran loop preheader heuristics of edge\[^:\]*: 1.0%" 2 "profile_estimate" } }
+! { dg-final { scan-tree-dump-times "Fortran loop preheader heuristics of edge\[^:\]*: 1.00%" 2 "profile_estimate" } }
diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_comp_52.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_comp_52.f90
new file mode 100644
index 0000000..631c018
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/proc_ptr_comp_52.f90
@@ -0,0 +1,33 @@
+! { dg-do compile }
+!
+! PR 85395: [F03] private clause contained in derived type acquires spurious scope
+!
+! Contributed by <cfd@mnet-mail.de>
+
+module defs
+ implicit none
+
+ type :: base
+ contains
+ private
+ end type
+
+ type :: options
+ procedure(), pointer, nopass :: ptr
+ end type
+
+ type :: t
+ private
+ procedure(), pointer, nopass, public :: ptr
+ end type
+end module
+
+
+program p
+ use defs
+ implicit none
+ type(options) :: self
+ type(t) :: dt
+ self%ptr => null()
+ dt%ptr => null()
+end
diff --git a/gcc/testsuite/gfortran.dg/promotion_2.f90 b/gcc/testsuite/gfortran.dg/promotion_2.f90
index 7e3c6c9..83fc062 100644
--- a/gcc/testsuite/gfortran.dg/promotion_2.f90
+++ b/gcc/testsuite/gfortran.dg/promotion_2.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-fdefault-real-8 -fexternal-blas -fdump-tree-original -finline-matmul-limit=0" }
+! { dg-options "-fdefault-real-8 -fexternal-blas -fblas-matmul-limit=1 -fdump-tree-original -finline-matmul-limit=0" }
!
! PR fortran/54463
!
@@ -8,8 +8,9 @@
program test
implicit none
real, dimension(3,3) :: A
+ call random_number(a)
A = matmul(A,A)
end program test
-! { dg-final { scan-tree-dump-times "sgemm_" 0 "original" } }
-! { dg-final { scan-tree-dump-times "dgemm_" 1 "original" } }
+! { dg-final { scan-tree-dump-times "sgemm" 0 "original" } }
+! { dg-final { scan-tree-dump-times "dgemm" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/reassoc_4.f b/gcc/testsuite/gfortran.dg/reassoc_4.f
index b155cba..07b4aff 100644
--- a/gcc/testsuite/gfortran.dg/reassoc_4.f
+++ b/gcc/testsuite/gfortran.dg/reassoc_4.f
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-O3 -ffast-math -fdump-tree-reassoc1 --param max-completely-peeled-insns=400" }
+! { dg-options "-O3 -ffast-math -fdump-tree-reassoc1 --param max-completely-peeled-insns=200" }
! { dg-additional-options "--param max-completely-peel-times=16" { target spu-*-* } }
subroutine anisonl(w,vo,anisox,s,ii1,jj1,weight)
integer ii1,jj1,i1,iii1,j1,jjj1,k1,l1,m1,n1
diff --git a/gcc/testsuite/gfortran.dg/select_type_43.f90 b/gcc/testsuite/gfortran.dg/select_type_43.f90
new file mode 100644
index 0000000..3bb71c3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/select_type_43.f90
@@ -0,0 +1,48 @@
+! { dg-do run }
+!
+! Tests the fix for PR87277 - runtime segfault as indicated.
+!
+! Contributed by Andrew Baldwin on clf.
+!
+ MODULE INTS_TYPE_MODULE
+ TYPE INTS_TYPE
+ INTEGER, ALLOCATABLE :: INTS(:)
+ END TYPE INTS_TYPE
+ CONTAINS
+ SUBROUTINE ALLOCATE_INTS_TYPE (IT_OBJ)
+ CLASS (INTS_TYPE), POINTER, INTENT (OUT) :: IT_OBJ
+
+ ALLOCATE (INTS_TYPE :: IT_OBJ)
+
+ SELECT TYPE (IT_OBJ)
+ TYPE IS (INTS_TYPE)
+ CALL ALLOCATE_ARRAY (IT_OBJ%INTS) ! Sefaulted at runtime here.
+ if (.not.allocated (IT_OBJ%INTS)) stop 1
+ if (any (IT_OBJ%INTS .ne. [1,2,3,4])) stop 2
+ END SELECT
+
+ RETURN
+ END SUBROUTINE ALLOCATE_INTS_TYPE
+
+ SUBROUTINE ALLOCATE_ARRAY (ALLOC_ARR)
+ INTEGER, ALLOCATABLE, INTENT (OUT) :: ALLOC_ARR(:)
+ INTEGER :: I
+
+ ALLOCATE (ALLOC_ARR(4))
+
+ DO I = 1, SIZE(ALLOC_ARR)
+ ALLOC_ARR(I) = I
+ END DO
+
+ RETURN
+ END SUBROUTINE ALLOCATE_ARRAY
+ END MODULE INTS_TYPE_MODULE
+
+ PROGRAM MFE
+ USE INTS_TYPE_MODULE
+ IMPLICIT NONE
+
+ CLASS (INTS_TYPE), POINTER :: IT_OBJ
+
+ CALL ALLOCATE_INTS_TYPE (IT_OBJ)
+ END PROGRAM MFE
diff --git a/gcc/testsuite/gfortran.dg/short_circuiting_2.f90 b/gcc/testsuite/gfortran.dg/short_circuiting_2.f90
new file mode 100644
index 0000000..765c8e7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/short_circuiting_2.f90
@@ -0,0 +1,28 @@
+! { dg-do run }
+! { dg-options "-O0" }
+!
+! PR 57160: short-circuit IF only with -ffrontend-optimize
+!
+! this checks that short-circuiting is not done with -O0
+!
+! Contributed by Janus Weil <janus@gcc.gnu.org>
+
+program short_circuit
+
+ integer, save :: i = 0
+ logical :: flag
+
+ flag = .false.
+ flag = check() .and. flag
+ flag = flag .and. check()
+
+ if (i /= 2) stop 1
+
+contains
+
+ logical function check()
+ i = i + 1
+ check = .true.
+ end function
+
+end
diff --git a/gcc/testsuite/gfortran.dg/short_circuiting_3.f90 b/gcc/testsuite/gfortran.dg/short_circuiting_3.f90
new file mode 100644
index 0000000..069f3f8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/short_circuiting_3.f90
@@ -0,0 +1,28 @@
+! { dg-do run }
+! { dg-options "-O3" }
+!
+! PR 57160: short-circuit IF only with -ffrontend-optimize
+!
+! this checks that short-circuiting is done with -O3
+!
+! Contributed by Janus Weil <janus@gcc.gnu.org>
+
+program short_circuit
+
+ integer, save :: i = 0
+ logical :: flag
+
+ flag = .false.
+ flag = check() .and. flag
+ flag = flag .and. check()
+
+ if (i /= 1) stop 1
+
+contains
+
+ logical function check()
+ i = i + 1
+ check = .true.
+ end function
+
+end
diff --git a/gcc/testsuite/gfortran.dg/submodule_32.f08 b/gcc/testsuite/gfortran.dg/submodule_32.f08
new file mode 100644
index 0000000..529015b8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/submodule_32.f08
@@ -0,0 +1,62 @@
+! { dg-do run }
+!
+! Test the fix for PR86863, where the Type Bound Procedures were
+! not flagged as subroutines thereby causing an error at the call
+! statements.
+!
+! Contributed by Damian Rouson <damian@sourceryinstitute.org>
+!
+module foo
+ implicit none
+ integer :: flag = 0
+ type bar
+ contains
+ procedure, nopass :: foobar
+ procedure, nopass :: barfoo
+ end type
+contains
+ subroutine foobar
+ flag = 1
+ end subroutine
+ subroutine barfoo
+ flag = 0
+ end subroutine
+end module
+
+module foobartoo
+ implicit none
+ interface
+ module subroutine set(object)
+ use foo
+ implicit none
+ type(bar) object
+ end subroutine
+ module subroutine unset(object)
+ use foo
+ implicit none
+ type(bar) object
+ end subroutine
+ end interface
+contains
+ module procedure unset
+ use foo, only : bar
+ call object%barfoo
+ end procedure
+end module
+
+submodule(foobartoo) subfoobar
+contains
+ module procedure set
+ use foo, only : bar
+ call object%foobar
+ end procedure
+end submodule
+
+ use foo
+ use foobartoo
+ type(bar) :: obj
+ call set(obj)
+ if (flag .ne. 1) stop 1
+ call unset(obj)
+ if (flag .ne. 0) stop 2
+end
diff --git a/gcc/testsuite/gfortran.dg/transfer_class_3.f90 b/gcc/testsuite/gfortran.dg/transfer_class_3.f90
new file mode 100644
index 0000000..90082d7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/transfer_class_3.f90
@@ -0,0 +1,18 @@
+! { dg-do run }
+!
+! Test the fix for PR66679.
+!
+! Contributed by Miha Polajnar <polajnar.miha@gmail.com>
+!
+program main
+ implicit none
+ class(*), allocatable :: vec(:)
+ integer :: var, ans(2)
+ allocate(vec(2),source=[1_4, 2_4])
+
+! This worked correctly.
+ if (any (transfer(vec,[var],2) .ne. [1_4, 2_4])) stop 1
+
+! This caused an ICE.
+ if (any ([transfer(vec(1),[var]), transfer(vec(2),[var])] .ne. [1_4, 2_4])) stop 2
+end program main
diff --git a/gcc/testsuite/gfortran.dg/transpose_optimization_2.f90 b/gcc/testsuite/gfortran.dg/transpose_optimization_2.f90
index 84b5a9e56..4748da1 100644
--- a/gcc/testsuite/gfortran.dg/transpose_optimization_2.f90
+++ b/gcc/testsuite/gfortran.dg/transpose_optimization_2.f90
@@ -60,5 +60,5 @@ end
!
! The check below for temporaries gave 14 and 33 for "parm" and "atmp".
!
-! { dg-final { scan-tree-dump-times "parm" 66 "original" } }
+! { dg-final { scan-tree-dump-times "parm" 72 "original" } }
! { dg-final { scan-tree-dump-times "atmp" 12 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/typebound_call_30.f90 b/gcc/testsuite/gfortran.dg/typebound_call_30.f90
new file mode 100644
index 0000000..3ca63bd
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/typebound_call_30.f90
@@ -0,0 +1,32 @@
+! { dg-do compile }
+!
+! PR 86830: [8/9 Regression] Contiguous array pointer function result not recognized as contiguous
+!
+! Contributed by <only_for_nouse@gmx.de>
+
+module m
+ implicit none
+
+ type :: t1
+ contains
+ procedure :: get_ptr
+ end type
+
+ type :: t2
+ class(t1), allocatable :: c
+ end type
+
+contains
+
+ function get_ptr(this)
+ class(t1) :: this
+ real, dimension(:), contiguous, pointer :: get_ptr
+ end function
+
+ subroutine test()
+ real, dimension(:), contiguous, pointer:: ptr
+ type(t2) :: x
+ ptr => x%c%get_ptr()
+ end subroutine
+
+end module
diff --git a/gcc/testsuite/gfortran.dg/typebound_proc_12.f90 b/gcc/testsuite/gfortran.dg/typebound_proc_12.f90
index 4612d49..ea43dab 100644
--- a/gcc/testsuite/gfortran.dg/typebound_proc_12.f90
+++ b/gcc/testsuite/gfortran.dg/typebound_proc_12.f90
@@ -5,7 +5,7 @@
! Contributed by Joost VandeVondele <jv244@cam.ac.uk>
!
TYPE a
- TYPE(b), DIMENSION(:), POINTER :: c ! { dg-error "type that has not been declared" }
+ TYPE(b), DIMENSION(:), POINTER :: c ! { dg-error "has not been declared" }
END TYPE
TYPE(a), POINTER :: d
CALL X(d%c%e) ! { dg-error "before it is defined" }
diff --git a/gcc/testsuite/gfortran.dg/use_rename_9.f90 b/gcc/testsuite/gfortran.dg/use_rename_9.f90
new file mode 100644
index 0000000..a26df9e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/use_rename_9.f90
@@ -0,0 +1,19 @@
+! { dg-do compile }
+!
+! Test the fix for PR86906, in which a spurious error was generated
+! by 'config' in the subroutine having the same symbol name as the
+! renamed 'foo_config'.
+!
+! Contributed by Damian Rouson <damian@sourceryinstitute.org>
+!
+module foo
+ type config
+ end type
+end module
+ use foo, only: foo_config => config
+contains
+ subroutine cap
+ integer config
+ type(foo_config) extra
+ end subroutine
+end
diff --git a/gcc/testsuite/gfortran.dg/vect/vect-8-epilogue.F90 b/gcc/testsuite/gfortran.dg/vect/vect-8-epilogue.F90
new file mode 100644
index 0000000..2a09539
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/vect/vect-8-epilogue.F90
@@ -0,0 +1,6 @@
+! { dg-do compile }
+! { dg-require-effective-target vect_double }
+! { dg-additional-options "-finline-matmul-limit=0 --param vect-epilogues-nomask=1" }
+! { dg-additional-options "-mstrict-align" { target { aarch64*-*-* } } }
+
+#include "vect-8.f90"
diff --git a/gcc/testsuite/gfortran.dg/whole_file_1.f90 b/gcc/testsuite/gfortran.dg/whole_file_1.f90
index 598c9d3..bceb250 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_1.f90
+++ b/gcc/testsuite/gfortran.dg/whole_file_1.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-fwhole-file" }
+! { dg-options "" }
! Tests the fix for PR22571 in which the derived types in a, b
! c and d were not detected to be different. In e and f, they
! are the same because they are sequence types.
diff --git a/gcc/testsuite/gfortran.dg/whole_file_10.f90 b/gcc/testsuite/gfortran.dg/whole_file_10.f90
index fb100bb..4d47d9d 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_10.f90
+++ b/gcc/testsuite/gfortran.dg/whole_file_10.f90
@@ -1,5 +1,4 @@
! { dg-do compile }
-! { dg-options "-fwhole-file" }
! Test the fix for the fifth problem in PR40011, where the
! entries were not resolved, resulting in a segfault.
!
diff --git a/gcc/testsuite/gfortran.dg/whole_file_11.f90 b/gcc/testsuite/gfortran.dg/whole_file_11.f90
index d01b210..9574849 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_11.f90
+++ b/gcc/testsuite/gfortran.dg/whole_file_11.f90
@@ -1,5 +1,4 @@
! { dg-do compile }
-! { dg-options "-fwhole-file" }
!
! Tests the fix PR40011 comment 16 in which the derived type lists in
! different program units were getting mixed up.
diff --git a/gcc/testsuite/gfortran.dg/whole_file_12.f90 b/gcc/testsuite/gfortran.dg/whole_file_12.f90
index 150ac5f..23ea102 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_12.f90
+++ b/gcc/testsuite/gfortran.dg/whole_file_12.f90
@@ -1,5 +1,4 @@
! { dg-do compile }
-! { dg-options "-fwhole-file" }
!
! Tests the fix PR40011 comment 17 in which the explicit interface was
! being ignored and the missing argument was not correctly handled, which
diff --git a/gcc/testsuite/gfortran.dg/whole_file_13.f90 b/gcc/testsuite/gfortran.dg/whole_file_13.f90
index d0a954f..ffa31c8 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_13.f90
+++ b/gcc/testsuite/gfortran.dg/whole_file_13.f90
@@ -1,5 +1,4 @@
! { dg-do run }
-! { dg-options "-fwhole-file -O3" }
! Check that the TYPE_CANONICAL is being correctly set
! for the derived types, when whole file compiling.
! (based on import.f90)
diff --git a/gcc/testsuite/gfortran.dg/whole_file_14.f90 b/gcc/testsuite/gfortran.dg/whole_file_14.f90
index 030e8cd..52c2e7a 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_14.f90
+++ b/gcc/testsuite/gfortran.dg/whole_file_14.f90
@@ -1,5 +1,5 @@
! { dg-do run }
-! { dg-options "-fwhole-file -O3" }
+! { dg-options "-O3" }
! Check that the derived types are correctly substituted when
! whole file compiling.
!
diff --git a/gcc/testsuite/gfortran.dg/whole_file_15.f90 b/gcc/testsuite/gfortran.dg/whole_file_15.f90
index 9988757..fd9f62d 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_15.f90
+++ b/gcc/testsuite/gfortran.dg/whole_file_15.f90
@@ -1,5 +1,4 @@
! { dg-do compile }
-! { dg-options "-fwhole-file" }
! Test the fix for PR43450 in which the use of 'replica_env_type'
! caused an ICE in ep_types
!
diff --git a/gcc/testsuite/gfortran.dg/whole_file_16.f90 b/gcc/testsuite/gfortran.dg/whole_file_16.f90
index 6c910f4..c45251e 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_16.f90
+++ b/gcc/testsuite/gfortran.dg/whole_file_16.f90
@@ -1,5 +1,4 @@
! { dg-do compile }
-! { dg-options "-fwhole-file" }
!
! PR fortran/31346
!
diff --git a/gcc/testsuite/gfortran.dg/whole_file_17.f90 b/gcc/testsuite/gfortran.dg/whole_file_17.f90
index a2a9d15..d0e07dd 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_17.f90
+++ b/gcc/testsuite/gfortran.dg/whole_file_17.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-pedantic -fwhole-file" }
+! { dg-options "-pedantic" }
!
! PR fortran/30668
!
diff --git a/gcc/testsuite/gfortran.dg/whole_file_18.f90 b/gcc/testsuite/gfortran.dg/whole_file_18.f90
index c483c7d..9d0229a 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_18.f90
+++ b/gcc/testsuite/gfortran.dg/whole_file_18.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-fwhole-file -Wno-unused-dummy-argument" }
+! { dg-options "-Wno-unused-dummy-argument" }
!
! PR fortran/34260
!
diff --git a/gcc/testsuite/gfortran.dg/whole_file_19.f90 b/gcc/testsuite/gfortran.dg/whole_file_19.f90
index cd69f92..184e028 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_19.f90
+++ b/gcc/testsuite/gfortran.dg/whole_file_19.f90
@@ -1,5 +1,4 @@
! { dg-do compile }
-! { dg-options "-fwhole-file" }
! Test the fix for pr40011 comment #42, in which the subroutine
! would just get lost with -fwhole-file.
!
diff --git a/gcc/testsuite/gfortran.dg/whole_file_2.f90 b/gcc/testsuite/gfortran.dg/whole_file_2.f90
index c5255a9..60163f4 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_2.f90
+++ b/gcc/testsuite/gfortran.dg/whole_file_2.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-fwhole-file" }
+! { dg-options "" }
! Tests the fix for PR26227 in which the interface mismatches
! below were not detected.
!
diff --git a/gcc/testsuite/gfortran.dg/whole_file_20.f03 b/gcc/testsuite/gfortran.dg/whole_file_20.f03
index b3f77e4..fd53422 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_20.f03
+++ b/gcc/testsuite/gfortran.dg/whole_file_20.f03
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-fwhole-file -fcoarray=single" }
+! { dg-options "-fcoarray=single" }
!
! Procedures with dummy arguments that are coarrays or polymorphic
! must have an explicit interface in the calling routine.
diff --git a/gcc/testsuite/gfortran.dg/whole_file_3.f90 b/gcc/testsuite/gfortran.dg/whole_file_3.f90
index 242280c..9b4f5a7 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_3.f90
+++ b/gcc/testsuite/gfortran.dg/whole_file_3.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-fwhole-file" }
+! { dg-options "" }
! Tests the fix for PR26227 in which the interface mismatches
! below were not detected.
!
diff --git a/gcc/testsuite/gfortran.dg/whole_file_4.f90 b/gcc/testsuite/gfortran.dg/whole_file_4.f90
index 671bc2d..2dfb33d 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_4.f90
+++ b/gcc/testsuite/gfortran.dg/whole_file_4.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-fwhole-file -std=legacy" }
+! { dg-options "-std=legacy" }
! Tests the fix for PR24886 in which the mismatch between the
! character lengths of the actual and formal arguments of
! 'foo' was not detected.
diff --git a/gcc/testsuite/gfortran.dg/whole_file_5.f90 b/gcc/testsuite/gfortran.dg/whole_file_5.f90
index fa4f06d..61612d4 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_5.f90
+++ b/gcc/testsuite/gfortran.dg/whole_file_5.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-O3 -fwhole-file -fdump-tree-optimized" }
+! { dg-options "-O3 -fdump-tree-optimized" }
! { dg-add-options bind_pic_locally }
!
! Check that inlining of functions declared BEFORE usage works.
diff --git a/gcc/testsuite/gfortran.dg/whole_file_6.f90 b/gcc/testsuite/gfortran.dg/whole_file_6.f90
index 771215d..fb961f3 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_6.f90
+++ b/gcc/testsuite/gfortran.dg/whole_file_6.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-O3 -fwhole-file -fdump-tree-optimized" }
+! { dg-options "-O3 -fdump-tree-optimized" }
! { dg-add-options bind_pic_locally }
!
! Check that inlining of functions declared AFTER usage works.
diff --git a/gcc/testsuite/gfortran.dg/whole_file_7.f90 b/gcc/testsuite/gfortran.dg/whole_file_7.f90
index 32253043..80609ca 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_7.f90
+++ b/gcc/testsuite/gfortran.dg/whole_file_7.f90
@@ -1,5 +1,4 @@
! { dg-do compile }
-! { dg-options "-fwhole-file" }
! Test the fixes for the first two problems in PR40011
!
! Contributed by Dominique d'Humieres <dominiq@lps.ens.fr>
diff --git a/gcc/testsuite/gfortran.dg/whole_file_8.f90 b/gcc/testsuite/gfortran.dg/whole_file_8.f90
index 6ea319a..db05c99 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_8.f90
+++ b/gcc/testsuite/gfortran.dg/whole_file_8.f90
@@ -1,5 +1,4 @@
! { dg-do compile }
-! { dg-options "-fwhole-file" }
! Test the fix for the third problem in PR40011, where false
! type/rank mismatches were found in the main program calls.
!
diff --git a/gcc/testsuite/gfortran.dg/whole_file_9.f90 b/gcc/testsuite/gfortran.dg/whole_file_9.f90
index 64dce42..17e7059 100644
--- a/gcc/testsuite/gfortran.dg/whole_file_9.f90
+++ b/gcc/testsuite/gfortran.dg/whole_file_9.f90
@@ -1,5 +1,4 @@
! { dg-do compile }
-! { dg-options "-fwhole-file" }
! Test the fix for the fourth problem in PR40011, where the
! entries were not resolved, resulting in a segfault.
!
diff --git a/gcc/testsuite/gnat.dg/access5.adb b/gcc/testsuite/gnat.dg/access5.adb
new file mode 100644
index 0000000..1369ea0
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/access5.adb
@@ -0,0 +1,5 @@
+-- { dg-do compile }
+
+package body Access5 is
+ procedure Dummy is null;
+end;
diff --git a/gcc/testsuite/gnat.dg/access5.ads b/gcc/testsuite/gnat.dg/access5.ads
new file mode 100644
index 0000000..81ab3b3
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/access5.ads
@@ -0,0 +1,10 @@
+package Access5 is
+ type Vec;
+ type Ptr is access all Vec;
+ type Vec is array (1..3) of Ptr;
+ function F return Ptr;
+ pragma Import (Ada, F);
+ Tail : Vec := (F, F, F);
+
+ procedure Dummy;
+end;
diff --git a/gcc/testsuite/gnat.dg/dinst.adb b/gcc/testsuite/gnat.dg/dinst.adb
new file mode 100644
index 0000000..460e6c5
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/dinst.adb
@@ -0,0 +1,20 @@
+-- { dg-do compile { target *-*-gnu* } }
+-- { dg-options "-gnateS -gdwarf -g -O -gno-column-info" }
+-- { dg-final { scan-assembler "loc \[0-9] 5 \[0-9]( is_stmt \[0-9])? discriminator 1\n" } } */
+-- { dg-final { scan-assembler-not "loc \[0-9] 5 \[0-9]( is_stmt \[0-9])? discriminator 2\n" } } */
+-- { dg-final { scan-assembler "loc \[0-9] 5 \[0-9]( is_stmt \[0-9])? discriminator 3\n" } } */
+-- { dg-final { scan-assembler "loc \[0-9] 5 \[0-9]( is_stmt \[0-9])? discriminator 4\n" } } */
+
+
+with DInst_Pkg;
+procedure DInst is
+ package I1 is new DInst_Pkg; -- instance 1
+ package I2 is new DInst_Pkg; -- instance 2
+ package I3 is new DInst_Pkg; -- instance 3
+ package I4 is new DInst_Pkg; -- instance 4
+begin
+ I1.Foo;
+ -- I2.Foo;
+ I3.Foo;
+ I4.Foo;
+end;
diff --git a/gcc/testsuite/gnat.dg/dinst_pkg.adb b/gcc/testsuite/gnat.dg/dinst_pkg.adb
new file mode 100644
index 0000000..09a9bae
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/dinst_pkg.adb
@@ -0,0 +1,7 @@
+with Ada.Text_IO; use Ada.Text_IO;
+package body DInst_Pkg is
+ procedure Foo is
+ begin
+ Put_Line ("hello there");
+ end;
+end;
diff --git a/gcc/testsuite/gnat.dg/dinst_pkg.ads b/gcc/testsuite/gnat.dg/dinst_pkg.ads
new file mode 100644
index 0000000..d22afdb
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/dinst_pkg.ads
@@ -0,0 +1,4 @@
+generic
+package DInst_Pkg is
+ procedure Foo;
+end;
diff --git a/gcc/testsuite/gnat.dg/dynhash.adb b/gcc/testsuite/gnat.dg/dynhash.adb
new file mode 100644
index 0000000..79e1b98
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/dynhash.adb
@@ -0,0 +1,750 @@
+-- { dg-do run }
+
+with Ada.Text_IO; use Ada.Text_IO;
+with GNAT.Dynamic_HTables; use GNAT.Dynamic_HTables;
+
+procedure Dynhash is
+ function Hash (Key : Integer) return Bucket_Range_Type;
+
+ package DHT is new Dynamic_HTable
+ (Key_Type => Integer,
+ Value_Type => Integer,
+ No_Value => 0,
+ Expansion_Threshold => 1.3,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ Equivalent_Keys => "=",
+ Hash => Hash);
+ use DHT;
+
+ function Create_And_Populate
+ (Low_Key : Integer;
+ High_Key : Integer;
+ Init_Size : Bucket_Range_Type) return Instance;
+ -- Create a hash table with initial size Init_Size and populate it with
+ -- key-value pairs where both keys and values are in the range Low_Key
+ -- .. High_Key.
+
+ procedure Check_Empty
+ (Caller : String;
+ T : Instance;
+ Low_Key : Integer;
+ High_Key : Integer);
+ -- Ensure that
+ --
+ -- * The key-value pairs count of hash table T is 0.
+ -- * All values for the keys in range Low_Key .. High_Key are 0.
+
+ procedure Check_Keys
+ (Caller : String;
+ Iter : in out Iterator;
+ Low_Key : Integer;
+ High_Key : Integer);
+ -- Ensure that iterator Iter visits every key in the range Low_Key ..
+ -- High_Key exactly once.
+
+ procedure Check_Locked_Mutations (Caller : String; T : in out Instance);
+ -- Ensure that all mutation operations of hash table T are locked
+
+ procedure Check_Size
+ (Caller : String;
+ T : Instance;
+ Exp_Count : Pair_Count_Type);
+ -- Ensure that the count of key-value pairs of hash table T matches
+ -- expected count Exp_Count. Emit an error if this is not the case.
+
+ procedure Test_Create (Init_Size : Bucket_Range_Type);
+ -- Verify that all dynamic hash table operations fail on a non-created
+ -- table of size Init_Size.
+
+ procedure Test_Delete_Get_Put_Size
+ (Low_Key : Integer;
+ High_Key : Integer;
+ Exp_Count : Pair_Count_Type;
+ Init_Size : Bucket_Range_Type);
+ -- Verify that
+ --
+ -- * Put properly inserts values in the hash table.
+ -- * Get properly retrieves all values inserted in the table.
+ -- * Delete properly deletes values.
+ -- * The size of the hash table properly reflects the number of key-value
+ -- pairs.
+ --
+ -- Low_Key and High_Key denote the range of keys to be inserted, retrieved,
+ -- and deleted. Exp_Count is the expected count of key-value pairs n the
+ -- hash table. Init_Size denotes the initial size of the table.
+
+ procedure Test_Iterate
+ (Low_Key : Integer;
+ High_Key : Integer;
+ Init_Size : Bucket_Range_Type);
+ -- Verify that iterators
+ --
+ -- * Properly visit each key exactly once.
+ -- * Mutation operations are properly locked and unlocked during
+ -- iteration.
+ --
+ -- Low_Key and High_Key denote the range of keys to be inserted, retrieved,
+ -- and deleted. Init_Size denotes the initial size of the table.
+
+ procedure Test_Iterate_Empty (Init_Size : Bucket_Range_Type);
+ -- Verify that an iterator over an empty hash table
+ --
+ -- * Does not visit any key
+ -- * Mutation operations are properly locked and unlocked during
+ -- iteration.
+ --
+ -- Init_Size denotes the initial size of the table.
+
+ procedure Test_Iterate_Forced
+ (Low_Key : Integer;
+ High_Key : Integer;
+ Init_Size : Bucket_Range_Type);
+ -- Verify that an iterator that is forcefully advanced by just Next
+ --
+ -- * Properly visit each key exactly once.
+ -- * Mutation operations are properly locked and unlocked during
+ -- iteration.
+ --
+ -- Low_Key and High_Key denote the range of keys to be inserted, retrieved,
+ -- and deleted. Init_Size denotes the initial size of the table.
+
+ procedure Test_Replace
+ (Low_Val : Integer;
+ High_Val : Integer;
+ Init_Size : Bucket_Range_Type);
+ -- Verify that Put properly updates the value of a particular key. Low_Val
+ -- and High_Val denote the range of values to be updated. Init_Size denotes
+ -- the initial size of the table.
+
+ procedure Test_Reset
+ (Low_Key : Integer;
+ High_Key : Integer;
+ Init_Size : Bucket_Range_Type);
+ -- Verify that Reset properly destroy and recreats a hash table. Low_Key
+ -- and High_Key denote the range of keys to be inserted in the hash table.
+ -- Init_Size denotes the initial size of the table.
+
+ -------------------------
+ -- Create_And_Populate --
+ -------------------------
+
+ function Create_And_Populate
+ (Low_Key : Integer;
+ High_Key : Integer;
+ Init_Size : Bucket_Range_Type) return Instance
+ is
+ T : Instance;
+
+ begin
+ T := Create (Init_Size);
+
+ for Key in Low_Key .. High_Key loop
+ Put (T, Key, Key);
+ end loop;
+
+ return T;
+ end Create_And_Populate;
+
+ -----------------
+ -- Check_Empty --
+ -----------------
+
+ procedure Check_Empty
+ (Caller : String;
+ T : Instance;
+ Low_Key : Integer;
+ High_Key : Integer)
+ is
+ Val : Integer;
+
+ begin
+ Check_Size
+ (Caller => Caller,
+ T => T,
+ Exp_Count => 0);
+
+ for Key in Low_Key .. High_Key loop
+ Val := Get (T, Key);
+
+ if Val /= 0 then
+ Put_Line ("ERROR: " & Caller & ": wrong value");
+ Put_Line ("expected: 0");
+ Put_Line ("got :" & Val'Img);
+ end if;
+ end loop;
+ end Check_Empty;
+
+ ----------------
+ -- Check_Keys --
+ ----------------
+
+ procedure Check_Keys
+ (Caller : String;
+ Iter : in out Iterator;
+ Low_Key : Integer;
+ High_Key : Integer)
+ is
+ type Bit_Vector is array (Low_Key .. High_Key) of Boolean;
+ pragma Pack (Bit_Vector);
+
+ Count : Natural;
+ Key : Integer;
+ Seen : Bit_Vector := (others => False);
+
+ begin
+ -- Compute the number of outstanding keys that have to be iterated on
+
+ Count := High_Key - Low_Key + 1;
+
+ while Has_Next (Iter) loop
+ Next (Iter, Key);
+
+ if Seen (Key) then
+ Put_Line
+ ("ERROR: " & Caller & ": Check_Keys: duplicate key" & Key'Img);
+ else
+ Seen (Key) := True;
+ Count := Count - 1;
+ end if;
+ end loop;
+
+ -- In the end, all keys must have been iterated on
+
+ if Count /= 0 then
+ for Key in Seen'Range loop
+ if not Seen (Key) then
+ Put_Line
+ ("ERROR: " & Caller & ": Check_Keys: missing key" & Key'Img);
+ end if;
+ end loop;
+ end if;
+ end Check_Keys;
+
+ ----------------------------
+ -- Check_Locked_Mutations --
+ ----------------------------
+
+ procedure Check_Locked_Mutations (Caller : String; T : in out Instance) is
+ begin
+ begin
+ Delete (T, 1);
+ Put_Line ("ERROR: " & Caller & ": Delete: no exception raised");
+ exception
+ when Table_Locked =>
+ null;
+ when others =>
+ Put_Line ("ERROR: " & Caller & ": Delete: unexpected exception");
+ end;
+
+ begin
+ Destroy (T);
+ Put_Line ("ERROR: " & Caller & ": Destroy: no exception raised");
+ exception
+ when Table_Locked =>
+ null;
+ when others =>
+ Put_Line ("ERROR: " & Caller & ": Destroy: unexpected exception");
+ end;
+
+ begin
+ Put (T, 1, 1);
+ Put_Line ("ERROR: " & Caller & ": Put: no exception raised");
+ exception
+ when Table_Locked =>
+ null;
+ when others =>
+ Put_Line ("ERROR: " & Caller & ": Put: unexpected exception");
+ end;
+
+ begin
+ Reset (T);
+ Put_Line ("ERROR: " & Caller & ": Reset: no exception raised");
+ exception
+ when Table_Locked =>
+ null;
+ when others =>
+ Put_Line ("ERROR: " & Caller & ": Reset: unexpected exception");
+ end;
+ end Check_Locked_Mutations;
+
+ ----------------
+ -- Check_Size --
+ ----------------
+
+ procedure Check_Size
+ (Caller : String;
+ T : Instance;
+ Exp_Count : Pair_Count_Type)
+ is
+ Count : constant Pair_Count_Type := Size (T);
+
+ begin
+ if Count /= Exp_Count then
+ Put_Line ("ERROR: " & Caller & ": Size: wrong value");
+ Put_Line ("expected:" & Exp_Count'Img);
+ Put_Line ("got :" & Count'Img);
+ end if;
+ end Check_Size;
+
+ ----------
+ -- Hash --
+ ----------
+
+ function Hash (Key : Integer) return Bucket_Range_Type is
+ begin
+ return Bucket_Range_Type (Key);
+ end Hash;
+
+ -----------------
+ -- Test_Create --
+ -----------------
+
+ procedure Test_Create (Init_Size : Bucket_Range_Type) is
+ Count : Pair_Count_Type;
+ Iter : Iterator;
+ T : Instance;
+ Val : Integer;
+
+ begin
+ -- Ensure that every routine defined in the API fails on a hash table
+ -- which has not been created yet.
+
+ begin
+ Delete (T, 1);
+ Put_Line ("ERROR: Test_Create: Delete: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Create: Delete: unexpected exception");
+ end;
+
+ begin
+ Destroy (T);
+ Put_Line ("ERROR: Test_Create: Destroy: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Create: Destroy: unexpected exception");
+ end;
+
+ begin
+ Val := Get (T, 1);
+ Put_Line ("ERROR: Test_Create: Get: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Create: Get: unexpected exception");
+ end;
+
+ begin
+ Iter := Iterate (T);
+ Put_Line ("ERROR: Test_Create: Iterate: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Create: Iterate: unexpected exception");
+ end;
+
+ begin
+ Put (T, 1, 1);
+ Put_Line ("ERROR: Test_Create: Put: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Create: Put: unexpected exception");
+ end;
+
+ begin
+ Reset (T);
+ Put_Line ("ERROR: Test_Create: Reset: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Create: Reset: unexpected exception");
+ end;
+
+ begin
+ Count := Size (T);
+ Put_Line ("ERROR: Test_Create: Size: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Create: Size: unexpected exception");
+ end;
+
+ -- Test create
+
+ T := Create (Init_Size);
+
+ -- Clean up the hash table to prevent memory leaks
+
+ Destroy (T);
+ end Test_Create;
+
+ ------------------------------
+ -- Test_Delete_Get_Put_Size --
+ ------------------------------
+
+ procedure Test_Delete_Get_Put_Size
+ (Low_Key : Integer;
+ High_Key : Integer;
+ Exp_Count : Pair_Count_Type;
+ Init_Size : Bucket_Range_Type)
+ is
+ Exp_Val : Integer;
+ T : Instance;
+ Val : Integer;
+
+ begin
+ T := Create_And_Populate (Low_Key, High_Key, Init_Size);
+
+ -- Ensure that its size matches an expected value
+
+ Check_Size
+ (Caller => "Test_Delete_Get_Put_Size",
+ T => T,
+ Exp_Count => Exp_Count);
+
+ -- Ensure that every value for the range of keys exists
+
+ for Key in Low_Key .. High_Key loop
+ Val := Get (T, Key);
+
+ if Val /= Key then
+ Put_Line ("ERROR: Test_Delete_Get_Put_Size: Get: wrong value");
+ Put_Line ("expected:" & Key'Img);
+ Put_Line ("got :" & Val'Img);
+ end if;
+ end loop;
+
+ -- Delete values whose keys are divisible by 10
+
+ for Key in Low_Key .. High_Key loop
+ if Key mod 10 = 0 then
+ Delete (T, Key);
+ end if;
+ end loop;
+
+ -- Ensure that all values whose keys were not deleted still exist
+
+ for Key in Low_Key .. High_Key loop
+ if Key mod 10 = 0 then
+ Exp_Val := 0;
+ else
+ Exp_Val := Key;
+ end if;
+
+ Val := Get (T, Key);
+
+ if Val /= Exp_Val then
+ Put_Line ("ERROR: Test_Delete_Get_Put_Size: Get: wrong value");
+ Put_Line ("expected:" & Exp_Val'Img);
+ Put_Line ("got :" & Val'Img);
+ end if;
+ end loop;
+
+ -- Delete all values
+
+ for Key in Low_Key .. High_Key loop
+ Delete (T, Key);
+ end loop;
+
+ -- Ensure that the hash table is empty
+
+ Check_Empty
+ (Caller => "Test_Delete_Get_Put_Size",
+ T => T,
+ Low_Key => Low_Key,
+ High_Key => High_Key);
+
+ -- Clean up the hash table to prevent memory leaks
+
+ Destroy (T);
+ end Test_Delete_Get_Put_Size;
+
+ ------------------
+ -- Test_Iterate --
+ ------------------
+
+ procedure Test_Iterate
+ (Low_Key : Integer;
+ High_Key : Integer;
+ Init_Size : Bucket_Range_Type)
+ is
+ Iter_1 : Iterator;
+ Iter_2 : Iterator;
+ T : Instance;
+
+ begin
+ T := Create_And_Populate (Low_Key, High_Key, Init_Size);
+
+ -- Obtain an iterator. This action must lock all mutation operations of
+ -- the hash table.
+
+ Iter_1 := Iterate (T);
+
+ -- Ensure that every mutation routine defined in the API fails on a hash
+ -- table with at least one outstanding iterator.
+
+ Check_Locked_Mutations
+ (Caller => "Test_Iterate",
+ T => T);
+
+ -- Obtain another iterator
+
+ Iter_2 := Iterate (T);
+
+ -- Ensure that every mutation is still locked
+
+ Check_Locked_Mutations
+ (Caller => "Test_Iterate",
+ T => T);
+
+ -- Ensure that all keys are iterable. Note that this does not unlock the
+ -- mutation operations of the hash table because Iter_2 is not exhausted
+ -- yet.
+
+ Check_Keys
+ (Caller => "Test_Iterate",
+ Iter => Iter_1,
+ Low_Key => Low_Key,
+ High_Key => High_Key);
+
+ Check_Locked_Mutations
+ (Caller => "Test_Iterate",
+ T => T);
+
+ -- Ensure that all keys are iterable. This action unlocks all mutation
+ -- operations of the hash table because all outstanding iterators have
+ -- been exhausted.
+
+ Check_Keys
+ (Caller => "Test_Iterate",
+ Iter => Iter_2,
+ Low_Key => Low_Key,
+ High_Key => High_Key);
+
+ -- Ensure that all mutation operations are once again callable
+
+ Delete (T, Low_Key);
+ Put (T, Low_Key, Low_Key);
+ Reset (T);
+
+ -- Clean up the hash table to prevent memory leaks
+
+ Destroy (T);
+ end Test_Iterate;
+
+ ------------------------
+ -- Test_Iterate_Empty --
+ ------------------------
+
+ procedure Test_Iterate_Empty (Init_Size : Bucket_Range_Type) is
+ Iter : Iterator;
+ Key : Integer;
+ T : Instance;
+
+ begin
+ T := Create_And_Populate (0, -1, Init_Size);
+
+ -- Obtain an iterator. This action must lock all mutation operations of
+ -- the hash table.
+
+ Iter := Iterate (T);
+
+ -- Ensure that every mutation routine defined in the API fails on a hash
+ -- table with at least one outstanding iterator.
+
+ Check_Locked_Mutations
+ (Caller => "Test_Iterate_Empty",
+ T => T);
+
+ -- Attempt to iterate over the keys
+
+ while Has_Next (Iter) loop
+ Next (Iter, Key);
+
+ Put_Line ("ERROR: Test_Iterate_Empty: key" & Key'Img & " exists");
+ end loop;
+
+ -- Ensure that all mutation operations are once again callable
+
+ Delete (T, 1);
+ Put (T, 1, 1);
+ Reset (T);
+
+ -- Clean up the hash table to prevent memory leaks
+
+ Destroy (T);
+ end Test_Iterate_Empty;
+
+ -------------------------
+ -- Test_Iterate_Forced --
+ -------------------------
+
+ procedure Test_Iterate_Forced
+ (Low_Key : Integer;
+ High_Key : Integer;
+ Init_Size : Bucket_Range_Type)
+ is
+ Iter : Iterator;
+ Key : Integer;
+ T : Instance;
+
+ begin
+ T := Create_And_Populate (Low_Key, High_Key, Init_Size);
+
+ -- Obtain an iterator. This action must lock all mutation operations of
+ -- the hash table.
+
+ Iter := Iterate (T);
+
+ -- Ensure that every mutation routine defined in the API fails on a hash
+ -- table with at least one outstanding iterator.
+
+ Check_Locked_Mutations
+ (Caller => "Test_Iterate_Forced",
+ T => T);
+
+ -- Forcibly advance the iterator until it raises an exception
+
+ begin
+ for Guard in Low_Key .. High_Key + 1 loop
+ Next (Iter, Key);
+ end loop;
+
+ Put_Line
+ ("ERROR: Test_Iterate_Forced: Iterator_Exhausted not raised");
+ exception
+ when Iterator_Exhausted =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Iterate_Forced: unexpected exception");
+ end;
+
+ -- Ensure that all mutation operations are once again callable
+
+ Delete (T, Low_Key);
+ Put (T, Low_Key, Low_Key);
+ Reset (T);
+
+ -- Clean up the hash table to prevent memory leaks
+
+ Destroy (T);
+ end Test_Iterate_Forced;
+
+ ------------------
+ -- Test_Replace --
+ ------------------
+
+ procedure Test_Replace
+ (Low_Val : Integer;
+ High_Val : Integer;
+ Init_Size : Bucket_Range_Type)
+ is
+ Key : constant Integer := 1;
+ T : Instance;
+ Val : Integer;
+
+ begin
+ T := Create (Init_Size);
+
+ -- Ensure the Put properly updates values with the same key
+
+ for Exp_Val in Low_Val .. High_Val loop
+ Put (T, Key, Exp_Val);
+
+ Val := Get (T, Key);
+
+ if Val /= Exp_Val then
+ Put_Line ("ERROR: Test_Replace: Get: wrong value");
+ Put_Line ("expected:" & Exp_Val'Img);
+ Put_Line ("got :" & Val'Img);
+ end if;
+ end loop;
+
+ -- Clean up the hash table to prevent memory leaks
+
+ Destroy (T);
+ end Test_Replace;
+
+ ----------------
+ -- Test_Reset --
+ ----------------
+
+ procedure Test_Reset
+ (Low_Key : Integer;
+ High_Key : Integer;
+ Init_Size : Bucket_Range_Type)
+ is
+ T : Instance;
+
+ begin
+ T := Create_And_Populate (Low_Key, High_Key, Init_Size);
+
+ -- Reset the contents of the hash table
+
+ Reset (T);
+
+ -- Ensure that the hash table is empty
+
+ Check_Empty
+ (Caller => "Test_Reset",
+ T => T,
+ Low_Key => Low_Key,
+ High_Key => High_Key);
+
+ -- Clean up the hash table to prevent memory leaks
+
+ Destroy (T);
+ end Test_Reset;
+
+-- Start of processing for Operations
+
+begin
+ Test_Create (Init_Size => 1);
+ Test_Create (Init_Size => 100);
+
+ Test_Delete_Get_Put_Size
+ (Low_Key => 1,
+ High_Key => 1,
+ Exp_Count => 1,
+ Init_Size => 1);
+
+ Test_Delete_Get_Put_Size
+ (Low_Key => 1,
+ High_Key => 1000,
+ Exp_Count => 1000,
+ Init_Size => 32);
+
+ Test_Iterate
+ (Low_Key => 1,
+ High_Key => 32,
+ Init_Size => 32);
+
+ Test_Iterate_Empty (Init_Size => 32);
+
+ Test_Iterate_Forced
+ (Low_Key => 1,
+ High_Key => 32,
+ Init_Size => 32);
+
+ Test_Replace
+ (Low_Val => 1,
+ High_Val => 10,
+ Init_Size => 32);
+
+ Test_Reset
+ (Low_Key => 1,
+ High_Key => 1000,
+ Init_Size => 100);
+end Dynhash;
diff --git a/gcc/testsuite/gnat.dg/elab6.adb b/gcc/testsuite/gnat.dg/elab6.adb
new file mode 100644
index 0000000..83b8fbc
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/elab6.adb
@@ -0,0 +1,8 @@
+-- { dg-do compile }
+-- { dg-options "-gnatE" }
+
+package body Elab6 is
+ procedure Force_Body is null;
+
+ package Inst is new Elab6_Pkg;
+end Elab6;
diff --git a/gcc/testsuite/gnat.dg/elab6.ads b/gcc/testsuite/gnat.dg/elab6.ads
new file mode 100644
index 0000000..3dac0d1
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/elab6.ads
@@ -0,0 +1,6 @@
+with Elab6_Pkg;
+
+generic
+package Elab6 is
+ procedure Force_Body;
+end Elab6;
diff --git a/gcc/testsuite/gnat.dg/elab6_pkg.adb b/gcc/testsuite/gnat.dg/elab6_pkg.adb
new file mode 100644
index 0000000..b6a360d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/elab6_pkg.adb
@@ -0,0 +1,17 @@
+package body Elab6_Pkg is
+ protected Prot_Obj is
+ entry Ent;
+ end Prot_Obj;
+
+ procedure Call_Ent is
+ begin
+ Prot_Obj.Ent;
+ end Call_Ent;
+
+ protected body Prot_Obj is
+ entry Ent when True is
+ begin
+ null;
+ end Ent;
+ end Prot_Obj;
+end Elab6_Pkg;
diff --git a/gcc/testsuite/gnat.dg/elab6_pkg.ads b/gcc/testsuite/gnat.dg/elab6_pkg.ads
new file mode 100644
index 0000000..f6343b0
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/elab6_pkg.ads
@@ -0,0 +1,4 @@
+generic
+package Elab6_Pkg is
+ procedure Call_Ent;
+end Elab6_Pkg;
diff --git a/gcc/testsuite/gnat.dg/enum4.adb b/gcc/testsuite/gnat.dg/enum4.adb
new file mode 100644
index 0000000..e8d743e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/enum4.adb
@@ -0,0 +1,59 @@
+-- { dg-do run }
+
+procedure Enum4 is
+
+ procedure Assert (Expected, Actual : String) is
+ begin
+ if Expected /= Actual then
+ raise Program_Error;
+ end if;
+ end Assert;
+
+ procedure Test_1 is
+ type Test_Enum is (Enum_1, Enum_2);
+ for Test_Enum use (Enum_1=> 8, Enum_2=> 12);
+
+ Enum_Values : constant array (Test_Enum) of Natural := (8, 12);
+
+ type Test_Enum_Rep is range 1..12;
+ Tmp_Test_Enum_Rep : Test_Enum_Rep;
+ begin
+ Tmp_Test_Enum_Rep := Test_Enum'Enum_Rep (Test_Enum'First);
+ Assert (" 8", Tmp_Test_Enum_Rep'Img);
+
+ for Enum in Test_Enum loop
+ Tmp_Test_Enum_Rep := Test_Enum'Enum_Rep (Enum);
+ Assert (Enum_Values (Enum)'Img, Tmp_Test_Enum_Rep'Img);
+ end loop;
+ end Test_1;
+
+ procedure Test_2 is
+ type Test_Enum is (Enum_1);
+ for Test_Enum use (Enum_1=> 2);
+
+ type Test_Enum_Rep_Full is range 0..2;
+ subtype Test_Enum_Rep_Short is
+ Test_Enum_Rep_Full range 2..Test_Enum_Rep_Full'Last;
+
+ Tmp_Test_Enum_Rep_Full : Test_Enum_Rep_Full;
+ Tmp_Test_Enum_Rep_Short : Test_Enum_Rep_Short;
+
+ begin
+ Tmp_Test_Enum_Rep_Short := Test_Enum'Enum_Rep (Test_Enum'First);
+ Assert (" 2", Tmp_Test_Enum_Rep_Short'Img);
+
+ for Enum in Test_Enum loop
+ Tmp_Test_Enum_Rep_Full := Test_Enum'Enum_Rep (Enum);
+ Assert (" 2", Tmp_Test_Enum_Rep_Short'Img);
+ end loop;
+
+ for Enum in Test_Enum range Test_Enum'First .. Test_Enum'Last loop
+ Tmp_Test_Enum_Rep_Short := Test_Enum'Enum_Rep(Enum); -- Test #2
+ Assert (" 2", Tmp_Test_Enum_Rep_Short'Img);
+ end loop;
+ end Test_2;
+
+begin
+ Test_1;
+ Test_2;
+end;
diff --git a/gcc/testsuite/gnat.dg/expr_func5.adb b/gcc/testsuite/gnat.dg/expr_func5.adb
new file mode 100644
index 0000000..34c4eb3
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/expr_func5.adb
@@ -0,0 +1,10 @@
+-- { dg-do compile }
+
+procedure Expr_Func5 is
+ type T is (B);
+ function F return T is (B);
+ type R (W : T := F) is null record;
+ V : R;
+begin
+ null;
+end Expr_Func5;
diff --git a/gcc/testsuite/gnat.dg/expr_func6.adb b/gcc/testsuite/gnat.dg/expr_func6.adb
new file mode 100644
index 0000000..7223fa0
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/expr_func6.adb
@@ -0,0 +1,7 @@
+-- { dg-do compile }
+
+package body Expr_Func6 is
+
+ procedure Dummy is null;
+
+end Expr_Func6;
diff --git a/gcc/testsuite/gnat.dg/expr_func6.ads b/gcc/testsuite/gnat.dg/expr_func6.ads
new file mode 100644
index 0000000..462bde1
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/expr_func6.ads
@@ -0,0 +1,17 @@
+pragma Assertion_Policy (Check);
+
+package Expr_Func6 is
+
+ type Monolean is (Nottrue);
+
+ function Basic_Function return Monolean;
+ function Fancy_Function_With_Contract return Boolean
+ with Pre => Basic_Function = Nottrue;
+
+ function Fancy_Function_With_Contract return Boolean is (False);
+
+ function Basic_Function return Monolean is (Nottrue);
+
+ procedure Dummy;
+
+end Expr_Func6;
diff --git a/gcc/testsuite/gnat.dg/expr_func7.adb b/gcc/testsuite/gnat.dg/expr_func7.adb
new file mode 100644
index 0000000..048af62
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/expr_func7.adb
@@ -0,0 +1,5 @@
+-- { dg-do compile }
+
+package body Expr_Func7 is
+ procedure Dummy is null;
+end Expr_Func7;
diff --git a/gcc/testsuite/gnat.dg/expr_func7.ads b/gcc/testsuite/gnat.dg/expr_func7.ads
new file mode 100644
index 0000000..47fc6f8
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/expr_func7.ads
@@ -0,0 +1,20 @@
+package Expr_Func7 is
+
+ type Abstract_Food is tagged null record;
+ type Abstract_Food_Access is access Abstract_Food'Class;
+
+ type Fruit is new Abstract_Food with record
+ Worm : Boolean;
+ end record;
+
+ type Bananas is tagged record
+ Inside : Abstract_Food_Access;
+ end record;
+
+ function Has_Worm
+ (B : Bananas) return Boolean is (Fruit (B.Inside.all).Worm);
+
+ Cool : Bananas;
+
+ procedure Dummy;
+end Expr_Func7;
diff --git a/gcc/testsuite/gnat.dg/linkedlist.adb b/gcc/testsuite/gnat.dg/linkedlist.adb
new file mode 100644
index 0000000..53a272f
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/linkedlist.adb
@@ -0,0 +1,1184 @@
+-- { dg-do run }
+
+with Ada.Text_IO; use Ada.Text_IO;
+with GNAT.Lists; use GNAT.Lists;
+
+procedure Linkedlist is
+ package Integer_Lists is new Doubly_Linked_List
+ (Element_Type => Integer,
+ "=" => "=");
+ use Integer_Lists;
+
+ procedure Check_Empty
+ (Caller : String;
+ L : Instance;
+ Low_Elem : Integer;
+ High_Elem : Integer);
+ -- Ensure that none of the elements in the range Low_Elem .. High_Elem are
+ -- present in list L, and that the list's length is 0.
+
+ procedure Check_Locked_Mutations (Caller : String; L : in out Instance);
+ -- Ensure that all mutation operations of list L are locked
+
+ procedure Check_Present
+ (Caller : String;
+ L : Instance;
+ Low_Elem : Integer;
+ High_Elem : Integer);
+ -- Ensure that all elements in the range Low_Elem .. High_Elem are present
+ -- in list L.
+
+ procedure Check_Unlocked_Mutations (Caller : String; L : in out Instance);
+ -- Ensure that all mutation operations of list L are unlocked
+
+ procedure Populate_With_Append
+ (L : Instance;
+ Low_Elem : Integer;
+ High_Elem : Integer);
+ -- Add elements in the range Low_Elem .. High_Elem in that order in list L
+
+ procedure Test_Append;
+ -- Verify that Append properly inserts at the tail of a list
+
+ procedure Test_Contains
+ (Low_Elem : Integer;
+ High_Elem : Integer);
+ -- Verify that Contains properly identifies that elements in the range
+ -- Low_Elem .. High_Elem are within a list.
+
+ procedure Test_Create;
+ -- Verify that all list operations fail on a non-created list
+
+ procedure Test_Delete
+ (Low_Elem : Integer;
+ High_Elem : Integer);
+ -- Verify that Delete properly removes elements in the range Low_Elem ..
+ -- High_Elem from a list.
+
+ procedure Test_Delete_First
+ (Low_Elem : Integer;
+ High_Elem : Integer);
+ -- Verify that Delete properly removes elements in the range Low_Elem ..
+ -- High_Elem from the head of a list.
+
+ procedure Test_Delete_Last
+ (Low_Elem : Integer;
+ High_Elem : Integer);
+ -- Verify that Delete properly removes elements in the range Low_Elem ..
+ -- High_Elem from the tail of a list.
+
+ procedure Test_First;
+ -- Verify that First properly returns the head of a list
+
+ procedure Test_Insert_After;
+ -- Verify that Insert_After properly adds an element after some other
+ -- element.
+
+ procedure Test_Insert_Before;
+ -- Vefity that Insert_Before properly adds an element before some other
+ -- element.
+
+ procedure Test_Is_Empty;
+ -- Verify that Is_Empty properly returns this status of a list
+
+ procedure Test_Iterate;
+ -- Verify that iterators properly manipulate mutation operations
+
+ procedure Test_Iterate_Empty;
+ -- Verify that iterators properly manipulate mutation operations of an
+ -- empty list.
+
+ procedure Test_Iterate_Forced
+ (Low_Elem : Integer;
+ High_Elem : Integer);
+ -- Verify that an iterator that is forcefully advanced by Next properly
+ -- unlocks the mutation operations of a list.
+
+ procedure Test_Last;
+ -- Verify that Last properly returns the tail of a list
+
+ procedure Test_Length;
+ -- Verify that Length returns the correct length of a list
+
+ procedure Test_Prepend;
+ -- Verify that Prepend properly inserts at the head of a list
+
+ procedure Test_Replace;
+ -- Verify that Replace properly substitutes old elements with new ones
+
+ -----------------
+ -- Check_Empty --
+ -----------------
+
+ procedure Check_Empty
+ (Caller : String;
+ L : Instance;
+ Low_Elem : Integer;
+ High_Elem : Integer)
+ is
+ Len : constant Element_Count_Type := Length (L);
+
+ begin
+ for Elem in Low_Elem .. High_Elem loop
+ if Contains (L, Elem) then
+ Put_Line ("ERROR: " & Caller & ": extra element" & Elem'Img);
+ end if;
+ end loop;
+
+ if Len /= 0 then
+ Put_Line ("ERROR: " & Caller & ": wrong length");
+ Put_Line ("expected: 0");
+ Put_Line ("got :" & Len'Img);
+ end if;
+ end Check_Empty;
+
+ ----------------------------
+ -- Check_Locked_Mutations --
+ ----------------------------
+
+ procedure Check_Locked_Mutations (Caller : String; L : in out Instance) is
+ begin
+ begin
+ Append (L, 1);
+ Put_Line ("ERROR: " & Caller & ": Append: no exception raised");
+ exception
+ when List_Locked =>
+ null;
+ when others =>
+ Put_Line ("ERROR: " & Caller & ": Append: unexpected exception");
+ end;
+
+ begin
+ Delete (L, 1);
+ Put_Line ("ERROR: " & Caller & ": Delete: no exception raised");
+ exception
+ when List_Empty =>
+ null;
+ when List_Locked =>
+ null;
+ when others =>
+ Put_Line ("ERROR: " & Caller & ": Delete: unexpected exception");
+ end;
+
+ begin
+ Delete_First (L);
+ Put_Line ("ERROR: " & Caller & ": Delete_First: no exception raised");
+ exception
+ when List_Empty =>
+ null;
+ when List_Locked =>
+ null;
+ when others =>
+ Put_Line
+ ("ERROR: " & Caller & ": Delete_First: unexpected exception");
+ end;
+
+ begin
+ Delete_Last (L);
+ Put_Line ("ERROR: " & Caller & ": Delete_List: no exception raised");
+ exception
+ when List_Empty =>
+ null;
+ when List_Locked =>
+ null;
+ when others =>
+ Put_Line
+ ("ERROR: " & Caller & ": Delete_Last: unexpected exception");
+ end;
+
+ begin
+ Destroy (L);
+ Put_Line ("ERROR: " & Caller & ": Destroy: no exception raised");
+ exception
+ when List_Locked =>
+ null;
+ when others =>
+ Put_Line ("ERROR: " & Caller & ": Destroy: unexpected exception");
+ end;
+
+ begin
+ Insert_After (L, 1, 2);
+ Put_Line ("ERROR: " & Caller & ": Insert_After: no exception raised");
+ exception
+ when List_Locked =>
+ null;
+ when others =>
+ Put_Line
+ ("ERROR: " & Caller & ": Insert_After: unexpected exception");
+ end;
+
+ begin
+ Insert_Before (L, 1, 2);
+ Put_Line
+ ("ERROR: " & Caller & ": Insert_Before: no exception raised");
+ exception
+ when List_Locked =>
+ null;
+ when others =>
+ Put_Line
+ ("ERROR: " & Caller & ": Insert_Before: unexpected exception");
+ end;
+
+ begin
+ Prepend (L, 1);
+ Put_Line ("ERROR: " & Caller & ": Prepend: no exception raised");
+ exception
+ when List_Locked =>
+ null;
+ when others =>
+ Put_Line ("ERROR: " & Caller & ": Prepend: unexpected exception");
+ end;
+
+ begin
+ Replace (L, 1, 2);
+ Put_Line ("ERROR: " & Caller & ": Replace: no exception raised");
+ exception
+ when List_Locked =>
+ null;
+ when others =>
+ Put_Line ("ERROR: " & Caller & ": Replace: unexpected exception");
+ end;
+ end Check_Locked_Mutations;
+
+ -------------------
+ -- Check_Present --
+ -------------------
+
+ procedure Check_Present
+ (Caller : String;
+ L : Instance;
+ Low_Elem : Integer;
+ High_Elem : Integer)
+ is
+ Elem : Integer;
+ Iter : Iterator;
+
+ begin
+ Iter := Iterate (L);
+ for Exp_Elem in Low_Elem .. High_Elem loop
+ Next (Iter, Elem);
+
+ if Elem /= Exp_Elem then
+ Put_Line ("ERROR: " & Caller & ": Check_Present: wrong element");
+ Put_Line ("expected:" & Exp_Elem'Img);
+ Put_Line ("got :" & Elem'Img);
+ end if;
+ end loop;
+
+ -- At this point all elements should have been accounted for. Check for
+ -- extra elements.
+
+ while Has_Next (Iter) loop
+ Next (Iter, Elem);
+ Put_Line
+ ("ERROR: " & Caller & ": Check_Present: extra element" & Elem'Img);
+ end loop;
+
+ exception
+ when Iterator_Exhausted =>
+ Put_Line
+ ("ERROR: "
+ & Caller
+ & "Check_Present: incorrect number of elements");
+ end Check_Present;
+
+ ------------------------------
+ -- Check_Unlocked_Mutations --
+ ------------------------------
+
+ procedure Check_Unlocked_Mutations (Caller : String; L : in out Instance) is
+ begin
+ Append (L, 1);
+ Append (L, 2);
+ Append (L, 3);
+ Delete (L, 1);
+ Delete_First (L);
+ Delete_Last (L);
+ Insert_After (L, 2, 3);
+ Insert_Before (L, 2, 1);
+ Prepend (L, 0);
+ Replace (L, 3, 4);
+ end Check_Unlocked_Mutations;
+
+ --------------------------
+ -- Populate_With_Append --
+ --------------------------
+
+ procedure Populate_With_Append
+ (L : Instance;
+ Low_Elem : Integer;
+ High_Elem : Integer)
+ is
+ begin
+ for Elem in Low_Elem .. High_Elem loop
+ Append (L, Elem);
+ end loop;
+ end Populate_With_Append;
+
+ -----------------
+ -- Test_Append --
+ -----------------
+
+ procedure Test_Append is
+ L : Instance := Create;
+
+ begin
+ Append (L, 1);
+ Append (L, 2);
+ Append (L, 3);
+ Append (L, 4);
+ Append (L, 5);
+
+ Check_Present
+ (Caller => "Test_Append",
+ L => L,
+ Low_Elem => 1,
+ High_Elem => 5);
+
+ Destroy (L);
+ end Test_Append;
+
+ -------------------
+ -- Test_Contains --
+ -------------------
+
+ procedure Test_Contains
+ (Low_Elem : Integer;
+ High_Elem : Integer)
+ is
+ Low_Bogus : constant Integer := Low_Elem - 1;
+ High_Bogus : constant Integer := High_Elem + 1;
+
+ L : Instance := Create;
+
+ begin
+ Populate_With_Append (L, Low_Elem, High_Elem);
+
+ -- Ensure that the elements are contained in the list
+
+ for Elem in Low_Elem .. High_Elem loop
+ if not Contains (L, Elem) then
+ Put_Line
+ ("ERROR: Test_Contains: element" & Elem'Img & " not in list");
+ end if;
+ end loop;
+
+ -- Ensure that arbitrary elements which were not inserted in the list
+ -- are not contained in the list.
+
+ if Contains (L, Low_Bogus) then
+ Put_Line
+ ("ERROR: Test_Contains: element" & Low_Bogus'Img & " in list");
+ end if;
+
+ if Contains (L, High_Bogus) then
+ Put_Line
+ ("ERROR: Test_Contains: element" & High_Bogus'Img & " in list");
+ end if;
+
+ Destroy (L);
+ end Test_Contains;
+
+ -----------------
+ -- Test_Create --
+ -----------------
+
+ procedure Test_Create is
+ Count : Element_Count_Type;
+ Flag : Boolean;
+ Iter : Iterator;
+ L : Instance;
+ Val : Integer;
+
+ begin
+ -- Ensure that every routine defined in the API fails on a list which
+ -- has not been created yet.
+
+ begin
+ Append (L, 1);
+ Put_Line ("ERROR: Test_Create: Append: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Create: Append: unexpected exception");
+ end;
+
+ begin
+ Flag := Contains (L, 1);
+ Put_Line ("ERROR: Test_Create: Contains: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Create: Contains: unexpected exception");
+ end;
+
+ begin
+ Delete (L, 1);
+ Put_Line ("ERROR: Test_Create: Delete: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Create: Delete: unexpected exception");
+ end;
+
+ begin
+ Delete_First (L);
+ Put_Line ("ERROR: Test_Create: Delete_First: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line
+ ("ERROR: Test_Create: Delete_First: unexpected exception");
+ end;
+
+ begin
+ Delete_Last (L);
+ Put_Line ("ERROR: Test_Create: Delete_Last: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Create: Delete_Last: unexpected exception");
+ end;
+
+ begin
+ Val := First (L);
+ Put_Line ("ERROR: Test_Create: First: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Create: First: unexpected exception");
+ end;
+
+ begin
+ Insert_After (L, 1, 2);
+ Put_Line ("ERROR: Test_Create: Insert_After: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line
+ ("ERROR: Test_Create: Insert_After: unexpected exception");
+ end;
+
+ begin
+ Insert_Before (L, 1, 2);
+ Put_Line ("ERROR: Test_Create: Insert_Before: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line
+ ("ERROR: Test_Create: Insert_Before: unexpected exception");
+ end;
+
+ begin
+ Flag := Is_Empty (L);
+ Put_Line ("ERROR: Test_Create: Is_Empty: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Create: Is_Empty: unexpected exception");
+ end;
+
+ begin
+ Iter := Iterate (L);
+ Put_Line ("ERROR: Test_Create: Iterate: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Create: Iterate: unexpected exception");
+ end;
+
+ begin
+ Val := Last (L);
+ Put_Line ("ERROR: Test_Create: Last: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Create: Last: unexpected exception");
+ end;
+
+ begin
+ Count := Length (L);
+ Put_Line ("ERROR: Test_Create: Length: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Create: Length: unexpected exception");
+ end;
+
+ begin
+ Prepend (L, 1);
+ Put_Line ("ERROR: Test_Create: Prepend: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Create: Prepend: unexpected exception");
+ end;
+
+ begin
+ Replace (L, 1, 2);
+ Put_Line ("ERROR: Test_Create: Replace: no exception raised");
+ exception
+ when Not_Created =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Create: Replace: unexpected exception");
+ end;
+ end Test_Create;
+
+ -----------------
+ -- Test_Delete --
+ -----------------
+
+ procedure Test_Delete
+ (Low_Elem : Integer;
+ High_Elem : Integer)
+ is
+ Iter : Iterator;
+ L : Instance := Create;
+
+ begin
+ Populate_With_Append (L, Low_Elem, High_Elem);
+
+ -- Delete the first element, which is technically the head
+
+ Delete (L, Low_Elem);
+
+ -- Ensure that all remaining elements except for the head are present in
+ -- the list.
+
+ Check_Present
+ (Caller => "Test_Delete",
+ L => L,
+ Low_Elem => Low_Elem + 1,
+ High_Elem => High_Elem);
+
+ -- Delete the last element, which is technically the tail
+
+ Delete (L, High_Elem);
+
+ -- Ensure that all remaining elements except for the head and tail are
+ -- present in the list.
+
+ Check_Present
+ (Caller => "Test_Delete",
+ L => L,
+ Low_Elem => Low_Elem + 1,
+ High_Elem => High_Elem - 1);
+
+ -- Delete all even elements
+
+ for Elem in Low_Elem + 1 .. High_Elem - 1 loop
+ if Elem mod 2 = 0 then
+ Delete (L, Elem);
+ end if;
+ end loop;
+
+ -- Ensure that all remaining elements except the head, tail, and even
+ -- elements are present in the list.
+
+ for Elem in Low_Elem + 1 .. High_Elem - 1 loop
+ if Elem mod 2 /= 0 and then not Contains (L, Elem) then
+ Put_Line ("ERROR: Test_Delete: missing element" & Elem'Img);
+ end if;
+ end loop;
+
+ -- Delete all odd elements
+
+ for Elem in Low_Elem + 1 .. High_Elem - 1 loop
+ if Elem mod 2 /= 0 then
+ Delete (L, Elem);
+ end if;
+ end loop;
+
+ -- At this point the list should be completely empty
+
+ Check_Empty
+ (Caller => "Test_Delete",
+ L => L,
+ Low_Elem => Low_Elem,
+ High_Elem => High_Elem);
+
+ -- Try to delete an element. This operation should raise List_Empty.
+
+ begin
+ Delete (L, Low_Elem);
+ Put_Line ("ERROR: Test_Delete: List_Empty not raised");
+ exception
+ when List_Empty =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Delete: unexpected exception");
+ end;
+
+ Destroy (L);
+ end Test_Delete;
+
+ -----------------------
+ -- Test_Delete_First --
+ -----------------------
+
+ procedure Test_Delete_First
+ (Low_Elem : Integer;
+ High_Elem : Integer)
+ is
+ L : Instance := Create;
+
+ begin
+ Populate_With_Append (L, Low_Elem, High_Elem);
+
+ -- Delete the head of the list, and verify that the remaining elements
+ -- are still present in the list.
+
+ for Elem in Low_Elem .. High_Elem loop
+ Delete_First (L);
+
+ Check_Present
+ (Caller => "Test_Delete_First",
+ L => L,
+ Low_Elem => Elem + 1,
+ High_Elem => High_Elem);
+ end loop;
+
+ -- At this point the list should be completely empty
+
+ Check_Empty
+ (Caller => "Test_Delete_First",
+ L => L,
+ Low_Elem => Low_Elem,
+ High_Elem => High_Elem);
+
+ -- Try to delete an element. This operation should raise List_Empty.
+
+ begin
+ Delete_First (L);
+ Put_Line ("ERROR: Test_Delete_First: List_Empty not raised");
+ exception
+ when List_Empty =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Delete_First: unexpected exception");
+ end;
+
+ Destroy (L);
+ end Test_Delete_First;
+
+ ----------------------
+ -- Test_Delete_Last --
+ ----------------------
+
+ procedure Test_Delete_Last
+ (Low_Elem : Integer;
+ High_Elem : Integer)
+ is
+ L : Instance := Create;
+
+ begin
+ Populate_With_Append (L, Low_Elem, High_Elem);
+
+ -- Delete the tail of the list, and verify that the remaining elements
+ -- are still present in the list.
+
+ for Elem in reverse Low_Elem .. High_Elem loop
+ Delete_Last (L);
+
+ Check_Present
+ (Caller => "Test_Delete_Last",
+ L => L,
+ Low_Elem => Low_Elem,
+ High_Elem => Elem - 1);
+ end loop;
+
+ -- At this point the list should be completely empty
+
+ Check_Empty
+ (Caller => "Test_Delete_Last",
+ L => L,
+ Low_Elem => Low_Elem,
+ High_Elem => High_Elem);
+
+ -- Try to delete an element. This operation should raise List_Empty.
+
+ begin
+ Delete_Last (L);
+ Put_Line ("ERROR: Test_Delete_Last: List_Empty not raised");
+ exception
+ when List_Empty =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Delete_First: unexpected exception");
+ end;
+
+ Destroy (L);
+ end Test_Delete_Last;
+
+ ----------------
+ -- Test_First --
+ ----------------
+
+ procedure Test_First is
+ Elem : Integer;
+ L : Instance := Create;
+
+ begin
+ -- Try to obtain the head. This operation should raise List_Empty.
+
+ begin
+ Elem := First (L);
+ Put_Line ("ERROR: Test_First: List_Empty not raised");
+ exception
+ when List_Empty =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_First: unexpected exception");
+ end;
+
+ Populate_With_Append (L, 1, 2);
+
+ -- Obtain the head
+
+ Elem := First (L);
+
+ if Elem /= 1 then
+ Put_Line ("ERROR: Test_First: wrong element");
+ Put_Line ("expected: 1");
+ Put_Line ("got :" & Elem'Img);
+ end if;
+
+ Destroy (L);
+ end Test_First;
+
+ -----------------------
+ -- Test_Insert_After --
+ -----------------------
+
+ procedure Test_Insert_After is
+ L : Instance := Create;
+
+ begin
+ -- Try to insert after a non-inserted element, in an empty list
+
+ Insert_After (L, 1, 2);
+
+ -- At this point the list should be completely empty
+
+ Check_Empty
+ (Caller => "Test_Insert_After",
+ L => L,
+ Low_Elem => 0,
+ High_Elem => -1);
+
+ Append (L, 1); -- 1
+
+ Insert_After (L, 1, 3); -- 1, 3
+ Insert_After (L, 1, 2); -- 1, 2, 3
+ Insert_After (L, 3, 4); -- 1, 2, 3, 4
+
+ -- Try to insert after a non-inserted element, in a full list
+
+ Insert_After (L, 10, 11);
+
+ Check_Present
+ (Caller => "Test_Insert_After",
+ L => L,
+ Low_Elem => 1,
+ High_Elem => 4);
+
+ Destroy (L);
+ end Test_Insert_After;
+
+ ------------------------
+ -- Test_Insert_Before --
+ ------------------------
+
+ procedure Test_Insert_Before is
+ L : Instance := Create;
+
+ begin
+ -- Try to insert before a non-inserted element, in an empty list
+
+ Insert_Before (L, 1, 2);
+
+ -- At this point the list should be completely empty
+
+ Check_Empty
+ (Caller => "Test_Insert_Before",
+ L => L,
+ Low_Elem => 0,
+ High_Elem => -1);
+
+ Append (L, 4); -- 4
+
+ Insert_Before (L, 4, 2); -- 2, 4
+ Insert_Before (L, 2, 1); -- 1, 2, 4
+ Insert_Before (L, 4, 3); -- 1, 2, 3, 4
+
+ -- Try to insert before a non-inserted element, in a full list
+
+ Insert_Before (L, 10, 11);
+
+ Check_Present
+ (Caller => "Test_Insert_Before",
+ L => L,
+ Low_Elem => 1,
+ High_Elem => 4);
+
+ Destroy (L);
+ end Test_Insert_Before;
+
+ -------------------
+ -- Test_Is_Empty --
+ -------------------
+
+ procedure Test_Is_Empty is
+ L : Instance := Create;
+
+ begin
+ if not Is_Empty (L) then
+ Put_Line ("ERROR: Test_Is_Empty: list is not empty");
+ end if;
+
+ Append (L, 1);
+
+ if Is_Empty (L) then
+ Put_Line ("ERROR: Test_Is_Empty: list is empty");
+ end if;
+
+ Delete_First (L);
+
+ if not Is_Empty (L) then
+ Put_Line ("ERROR: Test_Is_Empty: list is not empty");
+ end if;
+
+ Destroy (L);
+ end Test_Is_Empty;
+
+ ------------------
+ -- Test_Iterate --
+ ------------------
+
+ procedure Test_Iterate is
+ Elem : Integer;
+ Iter_1 : Iterator;
+ Iter_2 : Iterator;
+ L : Instance := Create;
+
+ begin
+ Populate_With_Append (L, 1, 5);
+
+ -- Obtain an iterator. This action must lock all mutation operations of
+ -- the list.
+
+ Iter_1 := Iterate (L);
+
+ -- Ensure that every mutation routine defined in the API fails on a list
+ -- with at least one outstanding iterator.
+
+ Check_Locked_Mutations
+ (Caller => "Test_Iterate",
+ L => L);
+
+ -- Obtain another iterator
+
+ Iter_2 := Iterate (L);
+
+ -- Ensure that every mutation is still locked
+
+ Check_Locked_Mutations
+ (Caller => "Test_Iterate",
+ L => L);
+
+ -- Exhaust the first itertor
+
+ while Has_Next (Iter_1) loop
+ Next (Iter_1, Elem);
+ end loop;
+
+ -- Ensure that every mutation is still locked
+
+ Check_Locked_Mutations
+ (Caller => "Test_Iterate",
+ L => L);
+
+ -- Exhaust the second itertor
+
+ while Has_Next (Iter_2) loop
+ Next (Iter_2, Elem);
+ end loop;
+
+ -- Ensure that all mutation operations are once again callable
+
+ Check_Unlocked_Mutations
+ (Caller => "Test_Iterate",
+ L => L);
+
+ Destroy (L);
+ end Test_Iterate;
+
+ ------------------------
+ -- Test_Iterate_Empty --
+ ------------------------
+
+ procedure Test_Iterate_Empty is
+ Elem : Integer;
+ Iter : Iterator;
+ L : Instance := Create;
+
+ begin
+ -- Obtain an iterator. This action must lock all mutation operations of
+ -- the list.
+
+ Iter := Iterate (L);
+
+ -- Ensure that every mutation routine defined in the API fails on a list
+ -- with at least one outstanding iterator.
+
+ Check_Locked_Mutations
+ (Caller => "Test_Iterate_Empty",
+ L => L);
+
+ -- Attempt to iterate over the elements
+
+ while Has_Next (Iter) loop
+ Next (Iter, Elem);
+
+ Put_Line
+ ("ERROR: Test_Iterate_Empty: element" & Elem'Img & " exists");
+ end loop;
+
+ -- Ensure that all mutation operations are once again callable
+
+ Check_Unlocked_Mutations
+ (Caller => "Test_Iterate_Empty",
+ L => L);
+
+ Destroy (L);
+ end Test_Iterate_Empty;
+
+ -------------------------
+ -- Test_Iterate_Forced --
+ -------------------------
+
+ procedure Test_Iterate_Forced
+ (Low_Elem : Integer;
+ High_Elem : Integer)
+ is
+ Elem : Integer;
+ Iter : Iterator;
+ L : Instance := Create;
+
+ begin
+ Populate_With_Append (L, Low_Elem, High_Elem);
+
+ -- Obtain an iterator. This action must lock all mutation operations of
+ -- the list.
+
+ Iter := Iterate (L);
+
+ -- Ensure that every mutation routine defined in the API fails on a list
+ -- with at least one outstanding iterator.
+
+ Check_Locked_Mutations
+ (Caller => "Test_Iterate_Forced",
+ L => L);
+
+ -- Forcibly advance the iterator until it raises an exception
+
+ begin
+ for Guard in Low_Elem .. High_Elem + 1 loop
+ Next (Iter, Elem);
+ end loop;
+
+ Put_Line
+ ("ERROR: Test_Iterate_Forced: Iterator_Exhausted not raised");
+ exception
+ when Iterator_Exhausted =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Iterate_Forced: unexpected exception");
+ end;
+
+ -- Ensure that all mutation operations are once again callable
+
+ Check_Unlocked_Mutations
+ (Caller => "Test_Iterate_Forced",
+ L => L);
+
+ Destroy (L);
+ end Test_Iterate_Forced;
+
+ ---------------
+ -- Test_Last --
+ ---------------
+
+ procedure Test_Last is
+ Elem : Integer;
+ L : Instance := Create;
+
+ begin
+ -- Try to obtain the tail. This operation should raise List_Empty.
+
+ begin
+ Elem := First (L);
+ Put_Line ("ERROR: Test_Last: List_Empty not raised");
+ exception
+ when List_Empty =>
+ null;
+ when others =>
+ Put_Line ("ERROR: Test_Last: unexpected exception");
+ end;
+
+ Populate_With_Append (L, 1, 2);
+
+ -- Obtain the tail
+
+ Elem := Last (L);
+
+ if Elem /= 2 then
+ Put_Line ("ERROR: Test_Last: wrong element");
+ Put_Line ("expected: 2");
+ Put_Line ("got :" & Elem'Img);
+ end if;
+
+ Destroy (L);
+ end Test_Last;
+
+ -----------------
+ -- Test_Length --
+ -----------------
+
+ procedure Test_Length is
+ L : Instance := Create;
+ Len : Element_Count_Type;
+
+ begin
+ Len := Length (L);
+
+ if Len /= 0 then
+ Put_Line ("ERROR: Test_Length: wrong length");
+ Put_Line ("expected: 0");
+ Put_Line ("got :" & Len'Img);
+ end if;
+
+ Populate_With_Append (L, 1, 2);
+ Len := Length (L);
+
+ if Len /= 2 then
+ Put_Line ("ERROR: Test_Length: wrong length");
+ Put_Line ("expected: 2");
+ Put_Line ("got :" & Len'Img);
+ end if;
+
+ Populate_With_Append (L, 3, 6);
+ Len := Length (L);
+
+ if Len /= 6 then
+ Put_Line ("ERROR: Test_Length: wrong length");
+ Put_Line ("expected: 6");
+ Put_Line ("got :" & Len'Img);
+ end if;
+
+ Destroy (L);
+ end Test_Length;
+
+ ------------------
+ -- Test_Prepend --
+ ------------------
+
+ procedure Test_Prepend is
+ L : Instance := Create;
+
+ begin
+ Prepend (L, 5);
+ Prepend (L, 4);
+ Prepend (L, 3);
+ Prepend (L, 2);
+ Prepend (L, 1);
+
+ Check_Present
+ (Caller => "Test_Prepend",
+ L => L,
+ Low_Elem => 1,
+ High_Elem => 5);
+
+ Destroy (L);
+ end Test_Prepend;
+
+ ------------------
+ -- Test_Replace --
+ ------------------
+
+ procedure Test_Replace is
+ L : Instance := Create;
+
+ begin
+ Populate_With_Append (L, 1, 5);
+
+ Replace (L, 3, 8);
+ Replace (L, 1, 6);
+ Replace (L, 4, 9);
+ Replace (L, 5, 10);
+ Replace (L, 2, 7);
+
+ Replace (L, 11, 12);
+
+ Check_Present
+ (Caller => "Test_Replace",
+ L => L,
+ Low_Elem => 6,
+ High_Elem => 10);
+
+ Destroy (L);
+ end Test_Replace;
+
+-- Start of processing for Operations
+
+begin
+ Test_Append;
+
+ Test_Contains
+ (Low_Elem => 1,
+ High_Elem => 5);
+
+ Test_Create;
+
+ Test_Delete
+ (Low_Elem => 1,
+ High_Elem => 10);
+
+ Test_Delete_First
+ (Low_Elem => 1,
+ High_Elem => 5);
+
+ Test_Delete_Last
+ (Low_Elem => 1,
+ High_Elem => 5);
+
+ Test_First;
+ Test_Insert_After;
+ Test_Insert_Before;
+ Test_Is_Empty;
+ Test_Iterate;
+ Test_Iterate_Empty;
+
+ Test_Iterate_Forced
+ (Low_Elem => 1,
+ High_Elem => 5);
+
+ Test_Last;
+ Test_Length;
+ Test_Prepend;
+ Test_Replace;
+end Linkedlist;
diff --git a/gcc/testsuite/gnat.dg/prot6.adb b/gcc/testsuite/gnat.dg/prot6.adb
new file mode 100644
index 0000000..f33b0a2
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/prot6.adb
@@ -0,0 +1,20 @@
+-- { dg-do compile }
+-- { dg-options "-gnatc" }
+
+package body Prot6 is
+
+ protected body My_Type is
+
+ procedure Set (D : Integer) is
+ begin
+ I := D;
+ end Set;
+
+ function Get return Integer is
+ begin
+ return I;
+ end Get;
+ end My_Type;
+
+ procedure Dummy is null;
+end Prot6;
diff --git a/gcc/testsuite/gnat.dg/prot6.ads b/gcc/testsuite/gnat.dg/prot6.ads
new file mode 100644
index 0000000..d8e27e0
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/prot6.ads
@@ -0,0 +1,31 @@
+package Prot6 is
+
+ generic
+ type TD is private;
+ type TI is synchronized interface;
+ package Set_Get is
+ type T is synchronized interface and TI;
+
+ procedure Set (E : in out T; D : TD) is abstract;
+ function Get (E : T) return TD is abstract;
+ end Set_Get;
+
+ type My_Type_Interface is synchronized interface;
+
+ package Set_Get_Integer is
+ new Set_Get (TD => Integer,
+ TI => My_Type_Interface);
+ use Set_Get_Integer;
+
+ protected type My_Type is
+ new Set_Get_Integer.T with
+
+ overriding procedure Set (D : Integer);
+ overriding function Get return Integer;
+ private
+ I : Integer;
+ end My_Type;
+
+ procedure Dummy;
+
+end Prot6;
diff --git a/gcc/testsuite/gnat.dg/rep_clause7.adb b/gcc/testsuite/gnat.dg/rep_clause7.adb
new file mode 100644
index 0000000..222b8f5
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/rep_clause7.adb
@@ -0,0 +1,29 @@
+procedure Rep_Clause7 is
+
+ subtype Msg is String (1 .. 3);
+
+ type Root is tagged record
+ B : Boolean;
+ M : Msg;
+ end record;
+ for Root use record
+ B at 0 range 64 .. 64;
+ M at 0 range 65 .. 88;
+ end record;
+
+ type Ext is new Root with null record;
+
+ procedure Inner (T : Msg) is
+ begin
+ null;
+ end;
+
+ pragma Warnings (Off);
+ T1 : Root;
+ T2 : Ext;
+ pragma Warnings (On);
+
+begin
+ Inner (T1.M);
+ Inner (T2.M);
+end;
diff --git a/gcc/testsuite/gnat.dg/spark2.adb b/gcc/testsuite/gnat.dg/spark2.adb
new file mode 100644
index 0000000..cb6c3b8
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/spark2.adb
@@ -0,0 +1,12 @@
+-- { dg-do compile }
+
+package body SPARK2 with SPARK_Mode is
+ function Factorial (N : Natural) return Natural is
+ begin
+ if N = 0 then
+ return 1;
+ else
+ return N * Factorial (N - 1);
+ end if;
+ end Factorial;
+end SPARK2;
diff --git a/gcc/testsuite/gnat.dg/spark2.ads b/gcc/testsuite/gnat.dg/spark2.ads
new file mode 100644
index 0000000..c60b1e2
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/spark2.ads
@@ -0,0 +1,16 @@
+package SPARK2 with SPARK_Mode is
+
+ function Expon (Value, Exp : Natural) return Natural is
+ (if Exp = 0 then 1
+ else Value * Expon (Value, Exp - 1))
+ with Ghost,
+ Pre => Value <= Max_Factorial_Number and Exp <= Max_Factorial_Number,
+ Annotate => (GNATprove, Terminating); -- CRASH!
+
+ Max_Factorial_Number : constant := 6;
+
+ function Factorial (N : Natural) return Natural with
+ Pre => N < Max_Factorial_Number,
+ Post => Factorial'Result <= Expon (Max_Factorial_Number, N);
+
+end SPARK2;
diff --git a/gcc/testsuite/gnat.dg/task1.adb b/gcc/testsuite/gnat.dg/task1.adb
new file mode 100644
index 0000000..1f1d1e9
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/task1.adb
@@ -0,0 +1,5 @@
+-- { dg-do assemble }
+
+package body Task1 is
+ procedure Dummy is null;
+end Task1;
diff --git a/gcc/testsuite/gnat.dg/task1.ads b/gcc/testsuite/gnat.dg/task1.ads
new file mode 100644
index 0000000..8908915
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/task1.ads
@@ -0,0 +1,10 @@
+with Task1_Pkg; use Task1_Pkg;
+
+package Task1 is
+ TAB : constant Typ_Task_Par_Tab := (others => (Dummy => FALSE));
+
+ T1 : Typ_Task (TAB (1).Dummy);
+ T2 : Typ_Task (TAB (2).Dummy);
+
+ procedure Dummy;
+end Task1;
diff --git a/gcc/testsuite/gnat.dg/task1_pkg.adb b/gcc/testsuite/gnat.dg/task1_pkg.adb
new file mode 100644
index 0000000..abd0a36
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/task1_pkg.adb
@@ -0,0 +1,11 @@
+package body Task1_Pkg is
+ task body Typ_Task is
+ begin
+ loop
+ null;
+ end loop;
+ end Typ_Task;
+
+begin
+ null;
+end Task1_Pkg;
diff --git a/gcc/testsuite/gnat.dg/task1_pkg.ads b/gcc/testsuite/gnat.dg/task1_pkg.ads
new file mode 100644
index 0000000..183d239
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/task1_pkg.ads
@@ -0,0 +1,10 @@
+package Task1_Pkg is
+ subtype Typ_Bool is boolean;
+
+ type Typ_Task_Par is record
+ Dummy : Typ_Bool;
+ end record;
+
+ type Typ_Task_Par_Tab is array (1 .. 33) of aliased Typ_Task_Par;
+ task type Typ_Task (dummy : Typ_Bool);
+end Task1_Pkg;
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug273.go b/gcc/testsuite/go.test/test/fixedbugs/bug273.go
index c04f211..7305c60 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug273.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug273.go
@@ -8,13 +8,15 @@
package main
+import "unsafe"
+
var bug = false
var minus1 = -1
var five = 5
-var big int64 = 10 | 1<<32
+var big int64 = 10 | 1<<40
-type block [1<<19]byte
+type block [1 << 19]byte
var g1 []block
@@ -48,9 +50,10 @@ func bigcap() {
g1 = make([]block, 10, big)
}
-type cblock [1<<16-1]byte
+type cblock [1<<16 - 1]byte
var g4 chan cblock
+
func badchancap() {
g4 = make(chan cblock, minus1)
}
@@ -60,7 +63,8 @@ func bigchancap() {
}
func overflowchan() {
- g4 = make(chan cblock, 1<<30)
+ const ptrSize = unsafe.Sizeof(uintptr(0))
+ g4 = make(chan cblock, 1<<(30*(ptrSize/4)))
}
func main() {
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4085b.go b/gcc/testsuite/go.test/test/fixedbugs/issue4085b.go
index 63aca23..6bf315f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/issue4085b.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4085b.go
@@ -1,6 +1,6 @@
// run
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -15,22 +15,31 @@ type T []int
func main() {
n := -1
- shouldPanic("len out of range", func() {_ = make(T, n)})
- shouldPanic("cap out of range", func() {_ = make(T, 0, n)})
+ shouldPanic("len out of range", func() { _ = make(T, n) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, n) })
+ shouldPanic("len out of range", func() { _ = make(T, int64(n)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, int64(n)) })
var t *byte
if unsafe.Sizeof(t) == 8 {
- n = 1<<20
- n <<= 20
- shouldPanic("len out of range", func() {_ = make(T, n)})
- shouldPanic("cap out of range", func() {_ = make(T, 0, n)})
- n <<= 20
- shouldPanic("len out of range", func() {_ = make(T, n)})
- shouldPanic("cap out of range", func() {_ = make(T, 0, n)})
+ var n2 int64 = 1 << 50
+ shouldPanic("len out of range", func() { _ = make(T, int(n2)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, int(n2)) })
+ n2 = 1<<63 - 1
+ shouldPanic("len out of range", func() { _ = make(T, int(n2)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, int(n2)) })
} else {
n = 1<<31 - 1
- shouldPanic("len out of range", func() {_ = make(T, n)})
- shouldPanic("cap out of range", func() {_ = make(T, 0, n)})
+ shouldPanic("len out of range", func() { _ = make(T, n) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, n) })
+ shouldPanic("len out of range", func() { _ = make(T, int64(n)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, int64(n)) })
}
+
+ // Test make in append panics since the gc compiler optimizes makes in appends.
+ shouldPanic("len out of range", func() { _ = append(T{}, make(T, n)...) })
+ shouldPanic("cap out of range", func() { _ = append(T{}, make(T, 0, n)...) })
+ shouldPanic("len out of range", func() { _ = append(T{}, make(T, int64(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(T{}, make(T, 0, int64(n))...) })
}
func shouldPanic(str string, f func()) {
@@ -44,6 +53,6 @@ func shouldPanic(str string, f func()) {
panic("got panic " + s + ", want " + str)
}
}()
-
+
f()
}
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
index f5e6bef..24d0b00 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -299,9 +299,11 @@ proc gcc-dg-test-1 { target_compile prog do_what extra_tool_flags } {
foreach x [split $finalcode "\n"] {
set finalcmd [lindex $x 0]
if { [info procs ${finalcmd}_required_options] != "" } {
- set req [${finalcmd}_required_options]
- if { $req != "" && [lsearch -exact $extra_tool_flags $req] == -1 } {
- lappend extra_tool_flags $req
+ foreach req [${finalcmd}_required_options] {
+ if { $req != ""
+ && [lsearch -exact $extra_tool_flags $req] == -1 } {
+ lappend extra_tool_flags $req
+ }
}
}
}
diff --git a/gcc/testsuite/lib/gcc-gdb-test.exp b/gcc/testsuite/lib/gcc-gdb-test.exp
index b13d3ec..0066e15 100644
--- a/gcc/testsuite/lib/gcc-gdb-test.exp
+++ b/gcc/testsuite/lib/gcc-gdb-test.exp
@@ -54,18 +54,19 @@ proc gdb-test { useline args } {
set var $arg1
}
- set gdb_name $::env(GUALITY_GDB_NAME)
- set testname "$testcase line [lindex $args 0] [lindex $args 1] == [lindex $args 2]"
- set output_file "[file rootname [file tail $prog]].exe"
- set cmd_file "[file rootname [file tail $prog]].gdb"
-
- set fd [open $cmd_file "w"]
set line [lindex $args 0]
if { [string range $line 0 0] == "@" } {
set line [string range $line 1 end]
} else {
set line [get-absolute-line $useline $line]
}
+
+ set gdb_name $::env(GUALITY_GDB_NAME)
+ set testname "$testcase line $line [lindex $args 1] == [lindex $args 2]"
+ set output_file "[file rootname [file tail $prog]].exe"
+ set cmd_file "[file rootname [file tail $prog]].gdb"
+
+ set fd [open $cmd_file "w"]
puts $fd "break $line"
puts $fd "run"
puts $fd "$command $var"
diff --git a/gcc/testsuite/lib/gcov.exp b/gcc/testsuite/lib/gcov.exp
index 03eb14a..f35ca59 100644
--- a/gcc/testsuite/lib/gcov.exp
+++ b/gcc/testsuite/lib/gcov.exp
@@ -133,6 +133,7 @@ proc verify-intermediate { testname testcase file } {
fail "$testname expected 'branch:' tag not found"
incr failed
}
+ close $fd
return $failed
}
diff --git a/gcc/testsuite/lib/multiline.exp b/gcc/testsuite/lib/multiline.exp
index 84c59e1..5f8b62f 100644
--- a/gcc/testsuite/lib/multiline.exp
+++ b/gcc/testsuite/lib/multiline.exp
@@ -202,26 +202,6 @@ proc _build_multiline_regex { multiline index } {
if {[string match "*^" $line] || [string match "*~" $line]} {
# Assume a line containing a caret/range. This must be
# an exact match.
- } elseif {[string match "*\\|" $line]} {
- # Assume a source line with a right-margin. Support
- # arbitrary text in place of any whitespace before the
- # right-margin, to deal with comments containing containing
- # DejaGnu directives.
-
- # Remove final "\|":
- set rexp [string range $rexp 0 [expr [string length $rexp] - 3]]
-
- # Trim off trailing whitespace:
- set old_length [string length $rexp]
- set rexp [string trimright $rexp]
- set new_length [string length $rexp]
-
- # Replace the trimmed whitespace with "." chars to match anything:
- set ws [string repeat "." [expr $old_length - $new_length]]
- set rexp "${rexp}${ws}"
-
- # Add back the trailing '\|':
- set rexp "${rexp}\\|"
} else {
# Assume that we have a quoted source line.
if {![string equal "" $line] } {
diff --git a/gcc/testsuite/lib/prune.exp b/gcc/testsuite/lib/prune.exp
index 1e11dc9..df36c34 100644
--- a/gcc/testsuite/lib/prune.exp
+++ b/gcc/testsuite/lib/prune.exp
@@ -21,7 +21,7 @@ load_lib multiline.exp
if ![info exists TEST_ALWAYS_FLAGS] {
set TEST_ALWAYS_FLAGS ""
}
-set TEST_ALWAYS_FLAGS "-fno-diagnostics-show-caret -fdiagnostics-color=never $TEST_ALWAYS_FLAGS"
+set TEST_ALWAYS_FLAGS "-fno-diagnostics-show-caret -fno-diagnostics-show-line-numbers -fdiagnostics-color=never $TEST_ALWAYS_FLAGS"
proc prune_gcc_output { text } {
global srcdir
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index c2d814c..57bfe9c 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -669,6 +669,7 @@ proc check_profiling_available { test_what } {
|| [istarget bfin-*-*]
|| [istarget cris-*-*]
|| [istarget crisv32-*-*]
+ || [istarget csky-*-elf]
|| [istarget fido-*-elf]
|| [istarget h8300-*-*]
|| [istarget lm32-*-*]
@@ -878,13 +879,8 @@ proc check_effective_target_tls_emulated {} {
# Return 1 if TLS executables can run correctly, 0 otherwise.
proc check_effective_target_tls_runtime {} {
- # The runtime does not have TLS support, but just
- # running the test below is insufficient to show this.
- if { [istarget msp430-*-*] || [istarget visium-*-*] } {
- return 0
- }
return [check_runtime tls_runtime {
- __thread int thr = 0;
+ __thread int thr __attribute__((tls_model("global-dynamic"))) = 0;
int main (void) { return thr; }
} [add_options_for_tls ""]]
}
@@ -1228,6 +1224,16 @@ proc check_effective_target_hard_float { } {
# }]
}
+ # The generic test doesn't work for C-SKY because some cores have
+ # hard float for single precision only.
+ if { [istarget csky*-*-*] } {
+ return [check_no_compiler_messages hard_float assembly {
+ #if defined __csky_soft_float__
+ #error __csky_soft_float__
+ #endif
+ }]
+ }
+
# The generic test equates hard_float with "no call for adding doubles".
return [check_no_messages_and_pattern hard_float "!\\(call" rtl-expand {
double a (double b, double c) { return b + c; }
@@ -5747,8 +5753,7 @@ proc check_effective_target_vect_perm { } {
} else {
set et_vect_perm_saved($et_index) 0
if { [is-effective-target arm_neon]
- || ([istarget aarch64*-*-*]
- && ![check_effective_target_vect_variable_length])
+ || [istarget aarch64*-*-*]
|| [istarget powerpc*-*-*]
|| [istarget spu-*-*]
|| [istarget i?86-*-*] || [istarget x86_64-*-*]
@@ -5813,7 +5818,9 @@ proc check_effective_target_vect_perm { } {
proc vect_perm_supported { count element_bits } {
set vector_bits [lindex [available_vector_sizes] 0]
- if { $vector_bits <= 0 } {
+ # The number of vectors has to be a power of 2 when permuting
+ # variable-length vectors.
+ if { $vector_bits <= 0 && ($count & -$count) != $count } {
return 0
}
set vf [expr { $vector_bits / $element_bits }]
@@ -5853,8 +5860,7 @@ proc check_effective_target_vect_perm_byte { } {
if { ([is-effective-target arm_neon]
&& [is-effective-target arm_little_endian])
|| ([istarget aarch64*-*-*]
- && [is-effective-target aarch64_little_endian]
- && ![check_effective_target_vect_variable_length])
+ && [is-effective-target aarch64_little_endian])
|| [istarget powerpc*-*-*]
|| [istarget spu-*-*]
|| ([istarget mips-*.*]
@@ -5893,8 +5899,7 @@ proc check_effective_target_vect_perm_short { } {
if { ([is-effective-target arm_neon]
&& [is-effective-target arm_little_endian])
|| ([istarget aarch64*-*-*]
- && [is-effective-target aarch64_little_endian]
- && ![check_effective_target_vect_variable_length])
+ && [is-effective-target aarch64_little_endian])
|| [istarget powerpc*-*-*]
|| [istarget spu-*-*]
|| (([istarget i?86-*-*] || [istarget x86_64-*-*])
@@ -8843,6 +8848,7 @@ proc check_effective_target_logical_op_short_circuit {} {
|| [istarget arc*-*-*]
|| [istarget avr*-*-*]
|| [istarget crisv32-*-*] || [istarget cris-*-*]
+ || [istarget csky*-*-*]
|| [istarget mmix-*-*]
|| [istarget s390*-*-*]
|| [istarget powerpc*-*-*]
@@ -8861,6 +8867,7 @@ proc check_effective_target_logical_op_short_circuit {} {
proc check_effective_target_branch_cost {} {
if { [ istarget arm*-*-*]
|| [istarget avr*-*-*]
+ || [istarget csky*-*-*]
|| [istarget epiphany*-*-*]
|| [istarget frv*-*-*]
|| [istarget i?86-*-*] || [istarget x86_64-*-*]
@@ -8883,6 +8890,12 @@ proc force_conventional_output_for { test } {
}
proc ${test}_required_options {} {
global gcc_force_conventional_output
+ upvar 1 extra_tool_flags extra_tool_flags
+ if {[regexp -- "^scan-assembler" [info level 0]]
+ && ![string match "*-fident*" $extra_tool_flags]} {
+ # Do not let .ident confuse assembler scan tests
+ return [list $gcc_force_conventional_output "-fno-ident"]
+ }
return $gcc_force_conventional_output
}
}
diff --git a/gcc/toplev.c b/gcc/toplev.c
index f23e8ae..9fb83d4 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -529,7 +529,9 @@ compile_file (void)
dwarf2out_frame_finish ();
#endif
+ debuginfo_start ();
(*debug_hooks->finish) (main_input_filename);
+ debuginfo_stop ();
timevar_pop (TV_SYMOUT);
/* Output some stuff at end of file if nec. */
@@ -1112,6 +1114,10 @@ general_init (const char *argv0, bool init_signals)
global_dc->show_caret
= global_options_init.x_flag_diagnostics_show_caret;
+ global_dc->show_labels_p
+ = global_options_init.x_flag_diagnostics_show_labels;
+ global_dc->show_line_numbers_p
+ = global_options_init.x_flag_diagnostics_show_line_numbers;
global_dc->show_option_requested
= global_options_init.x_flag_diagnostics_show_option;
global_dc->show_column
@@ -1183,6 +1189,7 @@ general_init (const char *argv0, bool init_signals)
symtab = new (ggc_cleared_alloc <symbol_table> ()) symbol_table ();
statistics_early_init ();
+ debuginfo_early_init ();
finish_params ();
}
@@ -2077,6 +2084,7 @@ finalize (bool no_backend)
if (!no_backend)
{
statistics_fini ();
+ debuginfo_fini ();
g->get_passes ()->finish_optimization_passes ();
@@ -2154,6 +2162,7 @@ do_compile ()
init_final (main_input_filename);
coverage_init (aux_base_name);
statistics_init ();
+ debuginfo_init ();
invoke_plugin_callbacks (PLUGIN_START_UNIT, NULL);
timevar_stop (TV_PHASE_SETUP);
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index ca14915..1d4eb80 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -235,8 +235,7 @@ is_tm_irrevocable (tree x)
if (TREE_CODE (x) == ADDR_EXPR)
x = TREE_OPERAND (x, 0);
if (TREE_CODE (x) == FUNCTION_DECL
- && DECL_BUILT_IN_CLASS (x) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (x) == BUILT_IN_TM_IRREVOCABLE)
+ && fndecl_built_in_p (x, BUILT_IN_TM_IRREVOCABLE))
return true;
return false;
@@ -358,7 +357,8 @@ is_tm_load (gimple *stmt)
return false;
fndecl = gimple_call_fndecl (stmt);
- return (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
+ return (fndecl
+ && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
&& BUILTIN_TM_LOAD_P (DECL_FUNCTION_CODE (fndecl)));
}
@@ -374,7 +374,7 @@ is_tm_simple_load (gimple *stmt)
return false;
fndecl = gimple_call_fndecl (stmt);
- if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+ if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
{
enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
return (fcode == BUILT_IN_TM_LOAD_1
@@ -402,7 +402,8 @@ is_tm_store (gimple *stmt)
return false;
fndecl = gimple_call_fndecl (stmt);
- return (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
+ return (fndecl
+ && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
&& BUILTIN_TM_STORE_P (DECL_FUNCTION_CODE (fndecl)));
}
@@ -418,7 +419,8 @@ is_tm_simple_store (gimple *stmt)
return false;
fndecl = gimple_call_fndecl (stmt);
- if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+ if (fndecl
+ && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
{
enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
return (fcode == BUILT_IN_TM_STORE_1
@@ -440,9 +442,7 @@ is_tm_simple_store (gimple *stmt)
static bool
is_tm_abort (tree fndecl)
{
- return (fndecl
- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_TM_ABORT);
+ return (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_TM_ABORT));
}
/* Build a GENERIC tree for a user abort. This is called by front ends
@@ -2007,7 +2007,7 @@ tm_region_init_1 (struct tm_region *region, basic_block bb)
if (gimple_code (g) == GIMPLE_CALL)
{
tree fn = gimple_call_fndecl (g);
- if (fn && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL)
+ if (fn && fndecl_built_in_p (fn, BUILT_IN_NORMAL))
{
if ((DECL_FUNCTION_CODE (fn) == BUILT_IN_TM_COMMIT
|| DECL_FUNCTION_CODE (fn) == BUILT_IN_TM_COMMIT_EH)
diff --git a/gcc/tree-call-cdce.c b/gcc/tree-call-cdce.c
index a47be1d..01401ca 100644
--- a/gcc/tree-call-cdce.c
+++ b/gcc/tree-call-cdce.c
@@ -737,7 +737,7 @@ gen_shrink_wrap_conditions (gcall *bi_call, vec<gimple *> conds,
call = bi_call;
fn = gimple_call_fndecl (call);
- gcc_assert (fn && DECL_BUILT_IN (fn));
+ gcc_assert (fn && fndecl_built_in_p (fn));
fnc = DECL_FUNCTION_CODE (fn);
*nconds = 0;
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 14d66b7..87979bc 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -171,8 +171,6 @@ static bool gimple_can_merge_blocks_p (basic_block, basic_block);
static void remove_bb (basic_block);
static edge find_taken_edge_computed_goto (basic_block, tree);
static edge find_taken_edge_cond_expr (const gcond *, tree);
-static edge find_taken_edge_switch_expr (const gswitch *, tree);
-static tree find_case_label_for_value (const gswitch *, tree);
static void lower_phi_internal_fn ();
void
@@ -389,7 +387,7 @@ lower_phi_internal_fn ()
{
tree arg = gimple_call_arg (stmt, i);
if (TREE_CODE (arg) == LABEL_DECL)
- pred = label_to_block (arg);
+ pred = label_to_block (cfun, arg);
else
{
edge e = find_edge (pred, bb);
@@ -972,15 +970,15 @@ make_edges_bb (basic_block bb, struct omp_region **pcur_region, int *pomp_index)
tree label2 = gimple_transaction_label_uninst (txn);
if (label1)
- make_edge (bb, label_to_block (label1), EDGE_FALLTHRU);
+ make_edge (bb, label_to_block (cfun, label1), EDGE_FALLTHRU);
if (label2)
- make_edge (bb, label_to_block (label2),
+ make_edge (bb, label_to_block (cfun, label2),
EDGE_TM_UNINSTRUMENTED | (label1 ? 0 : EDGE_FALLTHRU));
tree label3 = gimple_transaction_label_over (txn);
if (gimple_transaction_subcode (txn)
& (GTMA_HAVE_ABORT | GTMA_IS_OUTER))
- make_edge (bb, label_to_block (label3), EDGE_TM_ABORT);
+ make_edge (bb, label_to_block (cfun, label3), EDGE_TM_ABORT);
fallthru = false;
}
@@ -1265,8 +1263,8 @@ make_cond_expr_edges (basic_block bb)
/* Entry basic blocks for each component. */
then_label = gimple_cond_true_label (entry);
else_label = gimple_cond_false_label (entry);
- then_bb = label_to_block (then_label);
- else_bb = label_to_block (else_label);
+ then_bb = label_to_block (cfun, then_label);
+ else_bb = label_to_block (cfun, else_label);
then_stmt = first_stmt (then_bb);
else_stmt = first_stmt (else_bb);
@@ -1373,7 +1371,7 @@ get_cases_for_edge (edge e, gswitch *t)
{
tree elt = gimple_switch_label (t, i);
tree lab = CASE_LABEL (elt);
- basic_block label_bb = label_to_block (lab);
+ basic_block label_bb = label_to_block (cfun, lab);
edge this_edge = find_edge (e->src, label_bb);
/* Add it to the chain of CASE_LABEL_EXPRs referencing E, or create
@@ -1397,8 +1395,7 @@ make_gimple_switch_edges (gswitch *entry, basic_block bb)
for (i = 0; i < n; ++i)
{
- tree lab = CASE_LABEL (gimple_switch_label (entry, i));
- basic_block label_bb = label_to_block (lab);
+ basic_block label_bb = gimple_switch_label_bb (cfun, entry, i);
make_edge (bb, label_bb, 0);
}
}
@@ -1407,7 +1404,7 @@ make_gimple_switch_edges (gswitch *entry, basic_block bb)
/* Return the basic block holding label DEST. */
basic_block
-label_to_block_fn (struct function *ifun, tree dest)
+label_to_block (struct function *ifun, tree dest)
{
int uid = LABEL_DECL_UID (dest);
@@ -1442,7 +1439,7 @@ make_goto_expr_edges (basic_block bb)
if (simple_goto_p (goto_t))
{
tree dest = gimple_goto_dest (goto_t);
- basic_block label_bb = label_to_block (dest);
+ basic_block label_bb = label_to_block (cfun, dest);
edge e = make_edge (bb, label_bb, EDGE_FALLTHRU);
e->goto_locus = gimple_location (goto_t);
gsi_remove (&last, true);
@@ -1464,7 +1461,7 @@ make_gimple_asm_edges (basic_block bb)
for (i = 0; i < n; ++i)
{
tree label = TREE_VALUE (gimple_asm_label_op (stmt, i));
- basic_block label_bb = label_to_block (label);
+ basic_block label_bb = label_to_block (cfun, label);
make_edge (bb, label_bb, 0);
}
}
@@ -1496,7 +1493,7 @@ static struct label_record
static tree
main_block_label (tree label)
{
- basic_block bb = label_to_block (label);
+ basic_block bb = label_to_block (cfun, label);
tree main_label = label_for_bb[bb->index].label;
/* label_to_block possibly inserted undefined label into the chain. */
@@ -1773,7 +1770,7 @@ group_case_labels_stmt (gswitch *stmt)
int i, next_index, new_size;
basic_block default_bb = NULL;
- default_bb = label_to_block (CASE_LABEL (gimple_switch_default_label (stmt)));
+ default_bb = gimple_switch_default_bb (cfun, stmt);
/* Look for possible opportunities to merge cases. */
new_size = i = 1;
@@ -1785,7 +1782,7 @@ group_case_labels_stmt (gswitch *stmt)
base_case = gimple_switch_label (stmt, i);
gcc_assert (base_case);
- base_bb = label_to_block (CASE_LABEL (base_case));
+ base_bb = label_to_block (cfun, CASE_LABEL (base_case));
/* Discard cases that have the same destination as the default case or
whose destiniation blocks have already been removed as unreachable. */
@@ -1806,7 +1803,7 @@ group_case_labels_stmt (gswitch *stmt)
while (next_index < old_size)
{
tree merge_case = gimple_switch_label (stmt, next_index);
- basic_block merge_bb = label_to_block (CASE_LABEL (merge_case));
+ basic_block merge_bb = label_to_block (cfun, CASE_LABEL (merge_case));
wide_int bhp1 = wi::to_wide (base_high) + 1;
/* Merge the cases if they jump to the same place,
@@ -2387,7 +2384,7 @@ find_taken_edge_computed_goto (basic_block bb, tree val)
basic_block dest;
edge e = NULL;
- dest = label_to_block (val);
+ dest = label_to_block (cfun, val);
if (dest)
e = find_edge (bb, dest);
@@ -2437,7 +2434,7 @@ find_taken_edge_cond_expr (const gcond *cond_stmt, tree val)
If VAL is NULL_TREE, then the current value of SWITCH_STMT's index
is used. */
-static edge
+edge
find_taken_edge_switch_expr (const gswitch *switch_stmt, tree val)
{
basic_block dest_bb;
@@ -2455,7 +2452,7 @@ find_taken_edge_switch_expr (const gswitch *switch_stmt, tree val)
else
taken_case = find_case_label_for_value (switch_stmt, val);
}
- dest_bb = label_to_block (CASE_LABEL (taken_case));
+ dest_bb = label_to_block (cfun, CASE_LABEL (taken_case));
e = find_edge (gimple_bb (switch_stmt), dest_bb);
gcc_assert (e);
@@ -2467,7 +2464,7 @@ find_taken_edge_switch_expr (const gswitch *switch_stmt, tree val)
We can make optimal use here of the fact that the case labels are
sorted: We can do a binary search for a case matching VAL. */
-static tree
+tree
find_case_label_for_value (const gswitch *switch_stmt, tree val)
{
size_t low, high, n = gimple_switch_num_labels (switch_stmt);
@@ -3427,7 +3424,7 @@ verify_gimple_call (gcall *stmt)
return true;
}
- if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+ if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
{
switch (DECL_FUNCTION_CODE (fndecl))
{
@@ -5498,7 +5495,7 @@ gimple_verify_flow_info (void)
err = 1;
}
- if (label_to_block (label) != bb)
+ if (label_to_block (cfun, label) != bb)
{
error ("label ");
print_generic_expr (stderr, label);
@@ -5655,8 +5652,7 @@ gimple_verify_flow_info (void)
/* Mark all the destination basic blocks. */
for (i = 0; i < n; ++i)
{
- tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
- basic_block label_bb = label_to_block (lab);
+ basic_block label_bb = gimple_switch_label_bb (cfun, switch_stmt, i);
gcc_assert (!label_bb->aux || label_bb->aux == (void *)1);
label_bb->aux = (void *)1;
}
@@ -5711,8 +5707,8 @@ gimple_verify_flow_info (void)
/* Check that we have all of them. */
for (i = 0; i < n; ++i)
{
- tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
- basic_block label_bb = label_to_block (lab);
+ basic_block label_bb = gimple_switch_label_bb (cfun,
+ switch_stmt, i);
if (label_bb->aux != (void *)2)
{
@@ -5936,7 +5932,7 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
for (i = 0; i < n; i++)
{
tree elt = gimple_switch_label (switch_stmt, i);
- if (label_to_block (CASE_LABEL (elt)) == e->dest)
+ if (label_to_block (cfun, CASE_LABEL (elt)) == e->dest)
CASE_LABEL (elt) = label;
}
}
@@ -5952,7 +5948,7 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
for (i = 0; i < n; ++i)
{
tree cons = gimple_asm_label_op (asm_stmt, i);
- if (label_to_block (TREE_VALUE (cons)) == e->dest)
+ if (label_to_block (cfun, TREE_VALUE (cons)) == e->dest)
{
if (!label)
label = gimple_block_label (dest);
@@ -6884,7 +6880,7 @@ move_stmt_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
/* Remap the region numbers for __builtin_eh_{pointer,filter}. */
{
tree r, fndecl = gimple_call_fndecl (stmt);
- if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+ if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
switch (DECL_FUNCTION_CODE (fndecl))
{
case BUILT_IN_EH_COPY_VALUES:
@@ -8305,15 +8301,14 @@ stmt_can_terminate_bb_p (gimple *t)
if (is_gimple_call (t)
&& fndecl
- && DECL_BUILT_IN (fndecl)
+ && fndecl_built_in_p (fndecl)
&& (call_flags & ECF_NOTHROW)
&& !(call_flags & ECF_RETURNS_TWICE)
/* fork() doesn't really return twice, but the effect of
wrapping it in __gcov_fork() which calls __gcov_flush()
and clears the counters before forking has the same
effect as returning twice. Force a fake edge. */
- && !(DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FORK))
+ && !fndecl_built_in_p (fndecl, BUILT_IN_FORK))
return false;
if (is_gimple_call (t))
@@ -9131,22 +9126,53 @@ generate_range_test (basic_block bb, tree index, tree low, tree high,
tree type = TREE_TYPE (index);
tree utype = unsigned_type_for (type);
- low = fold_convert (type, low);
- high = fold_convert (type, high);
+ low = fold_convert (utype, low);
+ high = fold_convert (utype, high);
- tree tmp = make_ssa_name (type);
- gassign *sub1
- = gimple_build_assign (tmp, MINUS_EXPR, index, low);
+ gimple_seq seq = NULL;
+ index = gimple_convert (&seq, utype, index);
+ *lhs = gimple_build (&seq, MINUS_EXPR, utype, index, low);
+ *rhs = const_binop (MINUS_EXPR, utype, high, low);
- *lhs = make_ssa_name (utype);
- gassign *a = gimple_build_assign (*lhs, NOP_EXPR, tmp);
-
- *rhs = fold_build2 (MINUS_EXPR, utype, high, low);
gimple_stmt_iterator gsi = gsi_last_bb (bb);
- gsi_insert_before (&gsi, sub1, GSI_SAME_STMT);
- gsi_insert_before (&gsi, a, GSI_SAME_STMT);
+ gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
+}
+
+/* Return the basic block that belongs to label numbered INDEX
+ of a switch statement. */
+
+basic_block
+gimple_switch_label_bb (function *ifun, gswitch *gs, unsigned index)
+{
+ return label_to_block (ifun, CASE_LABEL (gimple_switch_label (gs, index)));
+}
+
+/* Return the default basic block of a switch statement. */
+
+basic_block
+gimple_switch_default_bb (function *ifun, gswitch *gs)
+{
+ return gimple_switch_label_bb (ifun, gs, 0);
+}
+
+/* Return the edge that belongs to label numbered INDEX
+ of a switch statement. */
+
+edge
+gimple_switch_edge (function *ifun, gswitch *gs, unsigned index)
+{
+ return find_edge (gimple_bb (gs), gimple_switch_label_bb (ifun, gs, index));
}
+/* Return the default edge of a switch statement. */
+
+edge
+gimple_switch_default_edge (function *ifun, gswitch *gs)
+{
+ return gimple_switch_edge (ifun, gs, 0);
+}
+
+
/* Emit return warnings. */
namespace {
diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h
index 9491bb4..95c070a 100644
--- a/gcc/tree-cfg.h
+++ b/gcc/tree-cfg.h
@@ -33,8 +33,7 @@ extern void init_empty_tree_cfg_for_function (struct function *);
extern void init_empty_tree_cfg (void);
extern void start_recording_case_labels (void);
extern void end_recording_case_labels (void);
-extern basic_block label_to_block_fn (struct function *, tree);
-#define label_to_block(t) (label_to_block_fn (cfun, t))
+extern basic_block label_to_block (struct function *, tree);
extern void cleanup_dead_labels (void);
extern bool group_case_labels_stmt (gswitch *);
extern bool group_case_labels (void);
@@ -103,6 +102,8 @@ extern tree gimplify_build2 (gimple_stmt_iterator *, enum tree_code,
extern tree gimplify_build1 (gimple_stmt_iterator *, enum tree_code,
tree, tree);
extern void extract_true_false_edges_from_block (basic_block, edge *, edge *);
+extern tree find_case_label_for_value (const gswitch *switch_stmt, tree val);
+extern edge find_taken_edge_switch_expr (const gswitch *switch_stmt, tree val);
extern unsigned int execute_fixup_cfg (void);
extern unsigned int split_critical_edges (void);
extern basic_block insert_cond_bb (basic_block, gimple *, gimple *,
@@ -112,6 +113,10 @@ extern bool extract_true_false_controlled_edges (basic_block, basic_block,
edge *, edge *);
extern void generate_range_test (basic_block bb, tree index, tree low,
tree high, tree *lhs, tree *rhs);
+extern basic_block gimple_switch_label_bb (function *, gswitch *, unsigned);
+extern basic_block gimple_switch_default_bb (function *, gswitch *);
+extern edge gimple_switch_edge (function *, gswitch *, unsigned);
+extern edge gimple_switch_default_edge (function *, gswitch *);
/* Return true if the LHS of a call should be removed. */
diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c
index b27ba8a..7fd0430 100644
--- a/gcc/tree-cfgcleanup.c
+++ b/gcc/tree-cfgcleanup.c
@@ -84,13 +84,12 @@ convert_single_case_switch (gswitch *swtch, gimple_stmt_iterator &gsi)
return false;
tree index = gimple_switch_index (swtch);
- tree default_label = CASE_LABEL (gimple_switch_default_label (swtch));
tree label = gimple_switch_label (swtch, 1);
tree low = CASE_LOW (label);
tree high = CASE_HIGH (label);
- basic_block default_bb = label_to_block_fn (cfun, default_label);
- basic_block case_bb = label_to_block_fn (cfun, CASE_LABEL (label));
+ basic_block default_bb = gimple_switch_default_bb (cfun, swtch);
+ basic_block case_bb = label_to_block (cfun, CASE_LABEL (label));
basic_block bb = gimple_bb (swtch);
gcond *cond;
@@ -266,7 +265,7 @@ cleanup_control_flow_bb (basic_block bb)
label = TREE_OPERAND (gimple_goto_dest (stmt), 0);
if (DECL_CONTEXT (label) != cfun->decl)
return retval;
- target_block = label_to_block (label);
+ target_block = label_to_block (cfun, label);
for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
{
if (e->dest != target_block)
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 4a04e9e..dee27f8 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -620,8 +620,6 @@ enum tree_index {
TI_CONST_FEXCEPT_T_PTR_TYPE,
TI_POINTER_SIZED_TYPE,
- TI_POINTER_BOUNDS_TYPE,
-
TI_DFLOAT32_TYPE,
TI_DFLOAT64_TYPE,
TI_DFLOAT128_TYPE,
@@ -1240,6 +1238,9 @@ struct GTY(()) tree_base {
IDENTIFIER_TRANSPARENT_ALIAS in
IDENTIFIER_NODE
+ SSA_NAME_POINTS_TO_READONLY_MEMORY in
+ SSA_NAME
+
visited:
TREE_VISITED in
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index a8c6872..bf30a61 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -1322,13 +1322,9 @@ bool
runtime_alias_check_p (ddr_p ddr, struct loop *loop, bool speed_p)
{
if (dump_enabled_p ())
- {
- dump_printf (MSG_NOTE, "consider run-time aliasing test between ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (DDR_A (ddr)));
- dump_printf (MSG_NOTE, " and ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (DDR_B (ddr)));
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf (MSG_NOTE,
+ "consider run-time aliasing test between %T and %T\n",
+ DR_REF (DDR_A (ddr)), DR_REF (DDR_B (ddr)));
if (!speed_p)
{
@@ -1469,17 +1465,9 @@ prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *alias_pairs,
if (*dr_a1 == *dr_a2 && *dr_b1 == *dr_b2)
{
if (dump_enabled_p ())
- {
- dump_printf (MSG_NOTE, "found equal ranges ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a1->dr));
- dump_printf (MSG_NOTE, ", ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b1->dr));
- dump_printf (MSG_NOTE, " and ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a2->dr));
- dump_printf (MSG_NOTE, ", ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b2->dr));
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf (MSG_NOTE, "found equal ranges %T, %T and %T, %T\n",
+ DR_REF (dr_a1->dr), DR_REF (dr_b1->dr),
+ DR_REF (dr_a2->dr), DR_REF (dr_b2->dr));
alias_pairs->ordered_remove (i--);
continue;
}
@@ -1576,17 +1564,9 @@ prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *alias_pairs,
dr_a1->align = MIN (dr_a1->align, new_align);
}
if (dump_enabled_p ())
- {
- dump_printf (MSG_NOTE, "merging ranges for ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a1->dr));
- dump_printf (MSG_NOTE, ", ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b1->dr));
- dump_printf (MSG_NOTE, " and ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a2->dr));
- dump_printf (MSG_NOTE, ", ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b2->dr));
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf (MSG_NOTE, "merging ranges for %T, %T and %T, %T\n",
+ DR_REF (dr_a1->dr), DR_REF (dr_b1->dr),
+ DR_REF (dr_a2->dr), DR_REF (dr_b2->dr));
alias_pairs->ordered_remove (i);
i--;
}
@@ -1925,13 +1905,9 @@ create_runtime_alias_checks (struct loop *loop,
const dr_with_seg_len& dr_b = (*alias_pairs)[i].second;
if (dump_enabled_p ())
- {
- dump_printf (MSG_NOTE, "create runtime check for data references ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a.dr));
- dump_printf (MSG_NOTE, " and ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b.dr));
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf (MSG_NOTE,
+ "create runtime check for data references %T and %T\n",
+ DR_REF (dr_a.dr), DR_REF (dr_b.dr));
/* Create condition expression for each pair data references. */
create_intersect_range_checks (loop, &part_cond_expr, dr_a, dr_b);
diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c
index 9814d02..c4a200f 100644
--- a/gcc/tree-diagnostic.c
+++ b/gcc/tree-diagnostic.c
@@ -282,7 +282,7 @@ default_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
case 'K':
t = va_arg (*text->args_ptr, tree);
- percent_K_format (text, t);
+ percent_K_format (text, EXPR_LOCATION (t), TREE_BLOCK (t));
return true;
default:
@@ -290,7 +290,7 @@ default_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
}
if (set_locus)
- text->set_location (0, DECL_SOURCE_LOCATION (t), true);
+ text->set_location (0, DECL_SOURCE_LOCATION (t), SHOW_RANGE_WITH_CARET);
if (DECL_P (t))
{
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index f367040..fb931aa 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -1984,7 +1984,7 @@ lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
tree fndecl = gimple_call_fndecl (stmt);
tree rhs, lhs;
- if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+ if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
switch (DECL_FUNCTION_CODE (fndecl))
{
case BUILT_IN_EH_POINTER:
@@ -2231,7 +2231,7 @@ make_eh_dispatch_edges (geh_dispatch *stmt)
case ERT_TRY:
for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
{
- dst = label_to_block (c->label);
+ dst = label_to_block (cfun, c->label);
make_edge (src, dst, 0);
/* A catch-all handler doesn't have a fallthru. */
@@ -2241,7 +2241,7 @@ make_eh_dispatch_edges (geh_dispatch *stmt)
break;
case ERT_ALLOWED_EXCEPTIONS:
- dst = label_to_block (r->u.allowed.label);
+ dst = label_to_block (cfun, r->u.allowed.label);
make_edge (src, dst, 0);
break;
@@ -2270,7 +2270,7 @@ make_eh_edges (gimple *stmt)
gcc_assert (lp != NULL);
src = gimple_bb (stmt);
- dst = label_to_block (lp->post_landing_pad);
+ dst = label_to_block (cfun, lp->post_landing_pad);
make_edge (src, dst, EDGE_EH);
}
@@ -2389,7 +2389,7 @@ redirect_eh_dispatch_edge (geh_dispatch *stmt, edge e, basic_block new_bb)
case ERT_TRY:
for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
{
- old_bb = label_to_block (c->label);
+ old_bb = label_to_block (cfun, c->label);
if (old_bb == e->dest)
{
c->label = new_lab;
@@ -2399,7 +2399,7 @@ redirect_eh_dispatch_edge (geh_dispatch *stmt, edge e, basic_block new_bb)
break;
case ERT_ALLOWED_EXCEPTIONS:
- old_bb = label_to_block (r->u.allowed.label);
+ old_bb = label_to_block (cfun, r->u.allowed.label);
gcc_assert (old_bb == e->dest);
r->u.allowed.label = new_lab;
any_changed = true;
@@ -3329,7 +3329,7 @@ lower_resx (basic_block bb, gresx *stmt,
else
{
lab = *slot;
- new_bb = label_to_block (lab);
+ new_bb = label_to_block (cfun, lab);
}
gcc_assert (EDGE_COUNT (bb->succs) == 0);
@@ -3733,7 +3733,7 @@ lower_eh_dispatch (basic_block src, geh_dispatch *stmt)
while (tp_node);
if (! have_label)
{
- remove_edge (find_edge (src, label_to_block (lab)));
+ remove_edge (find_edge (src, label_to_block (cfun, lab)));
redirected = true;
}
}
@@ -4046,7 +4046,7 @@ maybe_remove_unreachable_handlers (void)
FOR_EACH_VEC_SAFE_ELT (cfun->eh->lp_array, i, lp)
if (lp && lp->post_landing_pad)
{
- if (label_to_block (lp->post_landing_pad) == NULL)
+ if (label_to_block (cfun, lp->post_landing_pad) == NULL)
{
remove_unreachable_handlers ();
return;
@@ -4110,7 +4110,7 @@ remove_unreachable_handlers_no_lp (void)
static bool
unsplit_eh (eh_landing_pad lp)
{
- basic_block bb = label_to_block (lp->post_landing_pad);
+ basic_block bb = label_to_block (cfun, lp->post_landing_pad);
gimple_stmt_iterator gsi;
edge e_in, e_out;
@@ -4475,7 +4475,7 @@ infinite_empty_loop_p (edge e_first)
static bool
cleanup_empty_eh (eh_landing_pad lp)
{
- basic_block bb = label_to_block (lp->post_landing_pad);
+ basic_block bb = label_to_block (cfun, lp->post_landing_pad);
gimple_stmt_iterator gsi;
gimple *resx;
eh_region new_region;
@@ -4795,7 +4795,7 @@ verify_eh_edges (gimple *stmt)
return true;
}
- if (eh_edge->dest != label_to_block (lp->post_landing_pad))
+ if (eh_edge->dest != label_to_block (cfun, lp->post_landing_pad))
{
error ("Incorrect EH edge %i->%i", bb->index, eh_edge->dest->index);
return true;
@@ -4827,7 +4827,7 @@ verify_eh_dispatch_edge (geh_dispatch *stmt)
case ERT_TRY:
for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
{
- dst = label_to_block (c->label);
+ dst = label_to_block (cfun, c->label);
e = find_edge (src, dst);
if (e == NULL)
{
@@ -4846,7 +4846,7 @@ verify_eh_dispatch_edge (geh_dispatch *stmt)
break;
case ERT_ALLOWED_EXCEPTIONS:
- dst = label_to_block (r->u.allowed.label);
+ dst = label_to_block (cfun, r->u.allowed.label);
e = find_edge (src, dst);
if (e == NULL)
{
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index e181468..77eefac 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -1079,7 +1079,7 @@ if_convertible_stmt_p (gimple *stmt, vec<data_reference_p> refs)
&& !(flags & ECF_LOOPING_CONST_OR_PURE)
/* We can only vectorize some builtins at the moment,
so restrict if-conversion to those. */
- && DECL_BUILT_IN (fndecl))
+ && fndecl_built_in_p (fndecl))
return true;
}
return false;
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 6a16ce5..9352acc 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1702,7 +1702,7 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id)
case GIMPLE_CALL:
{
tree r, fndecl = gimple_call_fndecl (copy);
- if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+ if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
switch (DECL_FUNCTION_CODE (fndecl))
{
case BUILT_IN_EH_COPY_VALUES:
@@ -1939,9 +1939,7 @@ copy_bb (copy_body_data *id, basic_block bb,
else if (call_stmt
&& id->call_stmt
&& (decl = gimple_call_fndecl (stmt))
- && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (decl) == BUILT_IN_VA_ARG_PACK_LEN
- && ! gimple_call_va_arg_pack_p (id->call_stmt))
+ && fndecl_built_in_p (decl, BUILT_IN_VA_ARG_PACK_LEN))
{
/* __builtin_va_arg_pack_len () should be replaced by
the number of anonymous arguments. */
@@ -1952,10 +1950,28 @@ copy_bb (copy_body_data *id, basic_block bb,
for (p = DECL_ARGUMENTS (id->src_fn); p; p = DECL_CHAIN (p))
nargs--;
- count = build_int_cst (integer_type_node, nargs);
- new_stmt = gimple_build_assign (gimple_call_lhs (stmt), count);
- gsi_replace (&copy_gsi, new_stmt, false);
- stmt = new_stmt;
+ if (!gimple_call_lhs (stmt))
+ {
+ /* Drop unused calls. */
+ gsi_remove (&copy_gsi, false);
+ continue;
+ }
+ else if (!gimple_call_va_arg_pack_p (id->call_stmt))
+ {
+ count = build_int_cst (integer_type_node, nargs);
+ new_stmt = gimple_build_assign (gimple_call_lhs (stmt), count);
+ gsi_replace (&copy_gsi, new_stmt, false);
+ stmt = new_stmt;
+ }
+ else if (nargs != 0)
+ {
+ tree newlhs = create_tmp_reg_or_ssa_name (integer_type_node);
+ count = build_int_cst (integer_type_node, nargs);
+ new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
+ PLUS_EXPR, newlhs, count);
+ gimple_call_set_lhs (stmt, newlhs);
+ gsi_insert_after (&copy_gsi, new_stmt, GSI_NEW_STMT);
+ }
}
else if (call_stmt
&& id->call_stmt
@@ -4022,7 +4038,7 @@ estimate_num_insns (gimple *stmt, eni_weights *weights)
if (gimple_call_internal_p (stmt))
return 0;
else if ((decl = gimple_call_fndecl (stmt))
- && DECL_BUILT_IN (decl))
+ && fndecl_built_in_p (decl))
{
/* Do not special case builtins where we see the body.
This just confuse inliner. */
@@ -4416,6 +4432,7 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
/* Avoid warnings during early inline pass. */
&& symtab->global_info_ready)
{
+ auto_diagnostic_group d;
if (warning (OPT_Winline, "inlining failed in call to %q+F: %s",
fn, _(cgraph_inline_failed_string (reason))))
{
@@ -4885,7 +4902,7 @@ fold_marked_statements (int first, hash_set<gimple *> *statements)
gimple *old_stmt = gsi_stmt (gsi);
tree old_decl = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0;
- if (old_decl && DECL_BUILT_IN (old_decl))
+ if (old_decl && fndecl_built_in_p (old_decl))
{
/* Folding builtins can create multiple instructions,
we need to look at all of them. */
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index f4af33c..cdae75d 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -2490,6 +2490,28 @@ pass_build_ssa::execute (function *fun)
SET_SSA_NAME_VAR_OR_IDENTIFIER (name, DECL_NAME (decl));
}
+ /* Initialize SSA_NAME_POINTS_TO_READONLY_MEMORY. */
+ tree fnspec = lookup_attribute ("fn spec",
+ TYPE_ATTRIBUTES (TREE_TYPE (fun->decl)));
+ if (fnspec)
+ {
+ fnspec = TREE_VALUE (TREE_VALUE (fnspec));
+ unsigned i = 1;
+ for (tree arg = DECL_ARGUMENTS (cfun->decl);
+ arg; arg = DECL_CHAIN (arg), ++i)
+ {
+ if (i >= (unsigned) TREE_STRING_LENGTH (fnspec))
+ break;
+ if (TREE_STRING_POINTER (fnspec)[i] == 'R'
+ || TREE_STRING_POINTER (fnspec)[i] == 'r')
+ {
+ tree name = ssa_default_def (fun, arg);
+ if (name)
+ SSA_NAME_POINTS_TO_READONLY_MEMORY (name) = 1;
+ }
+ }
+ }
+
return 0;
}
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index 12066144..d8db03b 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -90,7 +90,6 @@ along with GCC; see the file COPYING3. If not see
data reuse. */
#include "config.h"
-#define INCLUDE_ALGORITHM /* stable_sort */
#include "system.h"
#include "coretypes.h"
#include "backend.h"
@@ -2561,12 +2560,14 @@ version_for_distribution_p (vec<struct partition *> *partitions,
/* Compare base offset of builtin mem* partitions P1 and P2. */
-static bool
-offset_cmp (struct partition *p1, struct partition *p2)
+static int
+offset_cmp (const void *vp1, const void *vp2)
{
- gcc_assert (p1 != NULL && p1->builtin != NULL);
- gcc_assert (p2 != NULL && p2->builtin != NULL);
- return p1->builtin->dst_base_offset < p2->builtin->dst_base_offset;
+ struct partition *p1 = *(struct partition *const *) vp1;
+ struct partition *p2 = *(struct partition *const *) vp2;
+ unsigned HOST_WIDE_INT o1 = p1->builtin->dst_base_offset;
+ unsigned HOST_WIDE_INT o2 = p2->builtin->dst_base_offset;
+ return (o2 < o1) - (o1 < o2);
}
/* Fuse adjacent memset builtin PARTITIONS if possible. This is a special
@@ -2618,8 +2619,8 @@ fuse_memset_builtins (vec<struct partition *> *partitions)
}
/* Stable sort is required in order to avoid breaking dependence. */
- std::stable_sort (&(*partitions)[i],
- &(*partitions)[i] + j - i, offset_cmp);
+ gcc_stablesort (&(*partitions)[i], j - i, sizeof (*partitions)[i],
+ offset_cmp);
/* Continue with next partition. */
i = j;
}
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
index e79a954..e89c887 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -2570,15 +2570,14 @@ set_reduc_phi_uids (reduction_info **slot, void *data ATTRIBUTE_UNUSED)
return 1;
}
-/* Return true if the type of reduction performed by STMT is suitable
+/* Return true if the type of reduction performed by STMT_INFO is suitable
for this pass. */
static bool
-valid_reduction_p (gimple *stmt)
+valid_reduction_p (stmt_vec_info stmt_info)
{
/* Parallelization would reassociate the operation, which isn't
allowed for in-order reductions. */
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
vect_reduction_type reduc_type = STMT_VINFO_REDUC_TYPE (stmt_info);
return reduc_type != FOLD_LEFT_REDUCTION;
}
@@ -2593,10 +2592,6 @@ gather_scalar_reductions (loop_p loop, reduction_info_table_type *reduction_list
auto_vec<gphi *, 4> double_reduc_phis;
auto_vec<gimple *, 4> double_reduc_stmts;
- vec<stmt_vec_info> stmt_vec_infos;
- stmt_vec_infos.create (50);
- set_stmt_vec_info_vec (&stmt_vec_infos);
-
vec_info_shared shared;
simple_loop_info = vect_analyze_loop_form (loop, &shared);
if (simple_loop_info == NULL)
@@ -2615,10 +2610,11 @@ gather_scalar_reductions (loop_p loop, reduction_info_table_type *reduction_list
if (simple_iv (loop, loop, res, &iv, true))
continue;
- gimple *reduc_stmt
- = vect_force_simple_reduction (simple_loop_info, phi,
+ stmt_vec_info reduc_stmt_info
+ = vect_force_simple_reduction (simple_loop_info,
+ simple_loop_info->lookup_stmt (phi),
&double_reduc, true);
- if (!reduc_stmt || !valid_reduction_p (reduc_stmt))
+ if (!reduc_stmt_info || !valid_reduction_p (reduc_stmt_info))
continue;
if (double_reduc)
@@ -2627,11 +2623,11 @@ gather_scalar_reductions (loop_p loop, reduction_info_table_type *reduction_list
continue;
double_reduc_phis.safe_push (phi);
- double_reduc_stmts.safe_push (reduc_stmt);
+ double_reduc_stmts.safe_push (reduc_stmt_info->stmt);
continue;
}
- build_new_reduction (reduction_list, reduc_stmt, phi);
+ build_new_reduction (reduction_list, reduc_stmt_info->stmt, phi);
}
delete simple_loop_info;
@@ -2661,12 +2657,15 @@ gather_scalar_reductions (loop_p loop, reduction_info_table_type *reduction_list
&iv, true))
continue;
- gimple *inner_reduc_stmt
- = vect_force_simple_reduction (simple_loop_info, inner_phi,
+ stmt_vec_info inner_phi_info
+ = simple_loop_info->lookup_stmt (inner_phi);
+ stmt_vec_info inner_reduc_stmt_info
+ = vect_force_simple_reduction (simple_loop_info,
+ inner_phi_info,
&double_reduc, true);
gcc_assert (!double_reduc);
- if (inner_reduc_stmt == NULL
- || !valid_reduction_p (inner_reduc_stmt))
+ if (!inner_reduc_stmt_info
+ || !valid_reduction_p (inner_reduc_stmt_info))
continue;
build_new_reduction (reduction_list, double_reduc_stmts[i], phi);
@@ -2676,14 +2675,11 @@ gather_scalar_reductions (loop_p loop, reduction_info_table_type *reduction_list
}
gather_done:
- /* Release the claim on gimple_uid. */
- free_stmt_vec_infos (&stmt_vec_infos);
-
if (reduction_list->elements () == 0)
return;
/* As gimple_uid is used by the vectorizer in between vect_analyze_loop_form
- and free_stmt_vec_info_vec, we can set gimple_uid of reduc_phi stmts only
+ and delete simple_loop_info, we can set gimple_uid of reduc_phi stmts only
now. */
basic_block bb;
FOR_EACH_BB_FN (bb, cfun)
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index e65c40a..2c089b1 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -37,7 +37,7 @@ along with GCC; see the file COPYING3. If not see
/* Local functions, macros and variables. */
static const char *op_symbol (const_tree);
-static void pretty_print_string (pretty_printer *, const char*);
+static void pretty_print_string (pretty_printer *, const char*, unsigned);
static void newline_and_indent (pretty_printer *, int);
static void maybe_init_pretty_print (FILE *);
static void print_struct_decl (pretty_printer *, const_tree, int, dump_flags_t);
@@ -162,6 +162,16 @@ print_generic_expr (FILE *file, tree t, dump_flags_t flags)
pp_flush (tree_pp);
}
+/* Print a single expression T to string, and return it. */
+
+char *
+print_generic_expr_to_str (tree t)
+{
+ pretty_printer pp;
+ dump_generic_node (&pp, t, 0, TDF_VOPS|TDF_MEMSYMS, false);
+ return xstrdup (pp_formatted_text (&pp));
+}
+
/* Dump NAME, an IDENTIFIER_POINTER, sanitized so that D<num> sequences
in it are replaced with Dxxxx, as long as they are at the start or
preceded by $ and at the end or followed by $. See make_fancy_name
@@ -1800,10 +1810,13 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
break;
case STRING_CST:
- pp_string (pp, "\"");
- pretty_print_string (pp, TREE_STRING_POINTER (node));
- pp_string (pp, "\"");
- break;
+ {
+ pp_string (pp, "\"");
+ if (unsigned nbytes = TREE_STRING_LENGTH (node))
+ pretty_print_string (pp, TREE_STRING_POINTER (node), nbytes);
+ pp_string (pp, "\"");
+ break;
+ }
case VECTOR_CST:
{
@@ -3865,15 +3878,16 @@ print_call_name (pretty_printer *pp, tree node, dump_flags_t flags)
}
}
-/* Parses the string STR and replaces new-lines by '\n', tabs by '\t', ... */
+/* Print the first N characters in the array STR, replacing non-printable
+ characters (including embedded nuls) with unambiguous escape sequences. */
static void
-pretty_print_string (pretty_printer *pp, const char *str)
+pretty_print_string (pretty_printer *pp, const char *str, unsigned n)
{
if (str == NULL)
return;
- while (*str)
+ for ( ; n; --n, ++str)
{
switch (str[0])
{
@@ -3913,48 +3927,20 @@ pretty_print_string (pretty_printer *pp, const char *str)
pp_string (pp, "\\'");
break;
- /* No need to handle \0; the loop terminates on \0. */
-
- case '\1':
- pp_string (pp, "\\1");
- break;
-
- case '\2':
- pp_string (pp, "\\2");
- break;
-
- case '\3':
- pp_string (pp, "\\3");
- break;
-
- case '\4':
- pp_string (pp, "\\4");
- break;
-
- case '\5':
- pp_string (pp, "\\5");
- break;
-
- case '\6':
- pp_string (pp, "\\6");
- break;
-
- case '\7':
- pp_string (pp, "\\7");
- break;
-
default:
- if (!ISPRINT (str[0]))
+ if (str[0] || n > 1)
{
- char buf[5];
- sprintf (buf, "\\x%x", (unsigned char)str[0]);
- pp_string (pp, buf);
+ if (!ISPRINT (str[0]))
+ {
+ char buf[5];
+ sprintf (buf, "\\x%02x", (unsigned char)str[0]);
+ pp_string (pp, buf);
+ }
+ else
+ pp_character (pp, str[0]);
+ break;
}
- else
- pp_character (pp, str[0]);
- break;
}
- str++;
}
}
@@ -3980,15 +3966,14 @@ newline_and_indent (pretty_printer *pp, int spc)
/* Handle the %K format for TEXT. Separate from default_tree_printer
so it can also be used in front ends.
- Argument is a statement from which EXPR_LOCATION and TREE_BLOCK will
- be recorded. */
+ The location LOC and BLOCK are expected to be extracted by the caller
+ from the %K argument arg via EXPR_LOCATION(arg) and TREE_BLOCK(arg). */
void
-percent_K_format (text_info *text, tree t)
+percent_K_format (text_info *text, location_t loc, tree block)
{
- text->set_location (0, EXPR_LOCATION (t), true);
+ text->set_location (0, loc, SHOW_RANGE_WITH_CARET);
gcc_assert (pp_ti_abstract_origin (text) != NULL);
- tree block = TREE_BLOCK (t);
*pp_ti_abstract_origin (text) = NULL;
if (in_lto_p)
diff --git a/gcc/tree-pretty-print.h b/gcc/tree-pretty-print.h
index cf2427f..4de0e09 100644
--- a/gcc/tree-pretty-print.h
+++ b/gcc/tree-pretty-print.h
@@ -38,6 +38,7 @@ extern void print_generic_decl (FILE *, tree, dump_flags_t);
extern void print_generic_stmt (FILE *, tree, dump_flags_t = TDF_NONE);
extern void print_generic_stmt_indented (FILE *, tree, dump_flags_t, int);
extern void print_generic_expr (FILE *, tree, dump_flags_t = TDF_NONE);
+extern char *print_generic_expr_to_str (tree);
extern void dump_omp_clauses (pretty_printer *, tree, int, dump_flags_t);
extern int dump_generic_node (pretty_printer *, tree, int, dump_flags_t, bool);
extern void print_declaration (pretty_printer *, tree, int, dump_flags_t);
@@ -45,7 +46,7 @@ extern int op_code_prio (enum tree_code);
extern int op_prio (const_tree);
extern const char *op_symbol_code (enum tree_code);
extern void print_call_name (pretty_printer *, tree, dump_flags_t);
-extern void percent_K_format (text_info *, tree);
+extern void percent_K_format (text_info *, location_t, tree);
extern void pp_tree_identifier (pretty_printer *, tree);
extern void dump_function_header (FILE *, tree, dump_flags_t);
extern void pp_double_int (pretty_printer *pp, double_int d, bool uns);
diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
index 69122f2..6475743 100644
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -3617,7 +3617,8 @@ final_value_replacement_loop (struct loop *loop)
{
fprintf (dump_file, "\nfinal value replacement:\n ");
print_gimple_stmt (dump_file, phi, 0);
- fprintf (dump_file, " with\n ");
+ fprintf (dump_file, " with expr: ");
+ print_generic_expr (dump_file, def);
}
def = unshare_expr (def);
remove_phi_node (&psi, false);
@@ -3656,6 +3657,7 @@ final_value_replacement_loop (struct loop *loop)
gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
if (dump_file)
{
+ fprintf (dump_file, "\n final stmt:\n ");
print_gimple_stmt (dump_file, ass, 0);
fprintf (dump_file, "\n");
}
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 3e30f6b..a9681ec 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -1498,8 +1498,7 @@ scan_function (void)
if (dest)
{
- if (DECL_BUILT_IN_CLASS (dest) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (dest) == BUILT_IN_APPLY_ARGS)
+ if (fndecl_built_in_p (dest, BUILT_IN_APPLY_ARGS))
encountered_apply_args = true;
if (recursive_call_p (current_function_decl, dest))
{
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 7b25778..032e79b 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -1483,6 +1483,16 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
ao_ref_alias_set (ref2)))
return false;
+ /* If the reference is based on a pointer that points to memory
+ that may not be written to then the other reference cannot possibly
+ clobber it. */
+ if ((TREE_CODE (TREE_OPERAND (base2, 0)) == SSA_NAME
+ && SSA_NAME_POINTS_TO_READONLY_MEMORY (TREE_OPERAND (base2, 0)))
+ || (ind1_p
+ && TREE_CODE (TREE_OPERAND (base1, 0)) == SSA_NAME
+ && SSA_NAME_POINTS_TO_READONLY_MEMORY (TREE_OPERAND (base1, 0))))
+ return false;
+
/* Dispatch to the pointer-vs-decl or pointer-vs-pointer disambiguators. */
if (var1_p && ind2_p)
return indirect_ref_may_alias_decl_p (ref2->ref, base2,
@@ -1991,6 +2001,14 @@ call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref)
|| !is_global_var (base)))
return false;
+ /* If the reference is based on a pointer that points to memory
+ that may not be written to then the call cannot possibly clobber it. */
+ if ((TREE_CODE (base) == MEM_REF
+ || TREE_CODE (base) == TARGET_MEM_REF)
+ && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME
+ && SSA_NAME_POINTS_TO_READONLY_MEMORY (TREE_OPERAND (base, 0)))
+ return false;
+
callee = gimple_call_fndecl (call);
/* Handle those builtin functions explicitly that do not act as
@@ -2722,7 +2740,14 @@ next:;
if (arg1 == arg0)
;
else if (! maybe_skip_until (phi, arg0, ref, arg1, cnt, visited,
- abort_on_visited, translate, data))
+ abort_on_visited,
+ /* Do not translate when walking over
+ backedges. */
+ dominated_by_p
+ (CDI_DOMINATORS,
+ gimple_bb (SSA_NAME_DEF_STMT (arg1)),
+ phi_bb)
+ ? NULL : translate, data))
return NULL_TREE;
}
@@ -2783,7 +2808,14 @@ walk_non_aliased_vuses (ao_ref *ref, tree vuse,
break;
if (valueize)
- vuse = valueize (vuse);
+ {
+ vuse = valueize (vuse);
+ if (!vuse)
+ {
+ res = NULL;
+ break;
+ }
+ }
def_stmt = SSA_NAME_DEF_STMT (vuse);
if (gimple_nop_p (def_stmt))
break;
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 2f0e542..95368a5 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -807,7 +807,7 @@ surely_varying_stmt_p (gimple *stmt)
tree fndecl, fntype = gimple_call_fntype (stmt);
if (!gimple_call_lhs (stmt)
|| ((fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
- && !DECL_BUILT_IN (fndecl)
+ && !fndecl_built_in_p (fndecl)
&& !lookup_attribute ("assume_aligned",
TYPE_ATTRIBUTES (fntype))
&& !lookup_attribute ("alloc_align",
@@ -2560,7 +2560,7 @@ optimize_stack_restore (gimple_stmt_iterator i)
callee = gimple_call_fndecl (stmt);
if (!callee
- || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
+ || !fndecl_built_in_p (callee, BUILT_IN_NORMAL)
/* All regular builtins are ok, just obviously not alloca. */
|| ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (callee)))
return NULL_TREE;
@@ -2596,9 +2596,7 @@ optimize_stack_restore (gimple_stmt_iterator i)
if (is_gimple_call (stack_save))
{
callee = gimple_call_fndecl (stack_save);
- if (callee
- && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_SAVE)
+ if (callee && fndecl_built_in_p (callee, BUILT_IN_STACK_SAVE))
{
gimple_stmt_iterator stack_save_gsi;
tree rhs;
@@ -3195,7 +3193,7 @@ pass_fold_builtins::execute (function *fun)
}
callee = gimple_call_fndecl (stmt);
- if (!callee || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL)
+ if (!callee || !fndecl_built_in_p (callee, BUILT_IN_NORMAL))
{
gsi_next (&i);
continue;
@@ -3370,8 +3368,7 @@ pass_fold_builtins::execute (function *fun)
}
callee = gimple_call_fndecl (stmt);
if (!callee
- || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
- || DECL_FUNCTION_CODE (callee) == fcode)
+ || !fndecl_built_in_p (callee, fcode))
gsi_next (&i);
}
}
@@ -3454,9 +3451,10 @@ pass_post_ipa_warn::execute (function *fun)
continue;
location_t loc = gimple_location (stmt);
+ auto_diagnostic_group d;
if (warning_at (loc, OPT_Wnonnull,
"%Gargument %u null where non-null "
- "expected", as_a <gcall *>(stmt), i + 1))
+ "expected", stmt, i + 1))
{
tree fndecl = gimple_call_fndecl (stmt);
if (fndecl && DECL_IS_BUILTIN (fndecl))
diff --git a/gcc/tree-ssa-coalesce.c b/gcc/tree-ssa-coalesce.c
index e4f576f..c123449 100644
--- a/gcc/tree-ssa-coalesce.c
+++ b/gcc/tree-ssa-coalesce.c
@@ -620,7 +620,11 @@ ssa_conflicts_merge (ssa_conflicts *ptr, unsigned x, unsigned y)
{
bitmap bz = ptr->conflicts[z];
if (bz)
- bitmap_set_bit (bz, x);
+ {
+ bool was_there = bitmap_clear_bit (bz, y);
+ gcc_checking_assert (was_there);
+ bitmap_set_bit (bz, x);
+ }
}
if (bx)
@@ -1575,22 +1579,9 @@ gimple_can_coalesce_p (tree name1, tree name2)
/* If the types are not the same, see whether they are compatible. This
(for example) allows coalescing when the types are fundamentally the
- same, but just have different names.
-
- In the non-optimized case, we must first test TYPE_CANONICAL because
- we use it to compute the partition_to_base_index of the map. */
- if (flag_tree_coalesce_vars)
- {
- if (types_compatible_p (t1, t2))
- goto check_modes;
- }
- else
- {
- if (TYPE_CANONICAL (t1)
- && TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2)
- && types_compatible_p (t1, t2))
- goto check_modes;
- }
+ same, but just have different names. */
+ if (types_compatible_p (t1, t2))
+ goto check_modes;
return false;
}
@@ -1716,89 +1707,6 @@ compute_optimized_partition_bases (var_map map, bitmap used_in_copies,
partition_delete (tentative);
}
-/* Hashtable helpers. */
-
-struct tree_int_map_hasher : nofree_ptr_hash <tree_int_map>
-{
- static inline hashval_t hash (const tree_int_map *);
- static inline bool equal (const tree_int_map *, const tree_int_map *);
-};
-
-inline hashval_t
-tree_int_map_hasher::hash (const tree_int_map *v)
-{
- return tree_map_base_hash (v);
-}
-
-inline bool
-tree_int_map_hasher::equal (const tree_int_map *v, const tree_int_map *c)
-{
- return tree_int_map_eq (v, c);
-}
-
-/* This routine will initialize the basevar fields of MAP with base
- names. Partitions will share the same base if they have the same
- SSA_NAME_VAR, or, being anonymous variables, the same type. This
- must match gimple_can_coalesce_p in the non-optimized case. */
-
-static void
-compute_samebase_partition_bases (var_map map)
-{
- int x, num_part;
- tree var;
- struct tree_int_map *m, *mapstorage;
-
- num_part = num_var_partitions (map);
- hash_table<tree_int_map_hasher> tree_to_index (num_part);
- /* We can have at most num_part entries in the hash tables, so it's
- enough to allocate so many map elements once, saving some malloc
- calls. */
- mapstorage = m = XNEWVEC (struct tree_int_map, num_part);
-
- /* If a base table already exists, clear it, otherwise create it. */
- free (map->partition_to_base_index);
- map->partition_to_base_index = (int *) xmalloc (sizeof (int) * num_part);
-
- /* Build the base variable list, and point partitions at their bases. */
- for (x = 0; x < num_part; x++)
- {
- struct tree_int_map **slot;
- unsigned baseindex;
- var = partition_to_var (map, x);
- if (SSA_NAME_VAR (var)
- && (!VAR_P (SSA_NAME_VAR (var))
- || !DECL_IGNORED_P (SSA_NAME_VAR (var))))
- m->base.from = SSA_NAME_VAR (var);
- else
- /* This restricts what anonymous SSA names we can coalesce
- as it restricts the sets we compute conflicts for.
- Using TREE_TYPE to generate sets is the easiest as
- type equivalency also holds for SSA names with the same
- underlying decl.
-
- Check gimple_can_coalesce_p when changing this code. */
- m->base.from = (TYPE_CANONICAL (TREE_TYPE (var))
- ? TYPE_CANONICAL (TREE_TYPE (var))
- : TREE_TYPE (var));
- /* If base variable hasn't been seen, set it up. */
- slot = tree_to_index.find_slot (m, INSERT);
- if (!*slot)
- {
- baseindex = m - mapstorage;
- m->to = baseindex;
- *slot = m;
- m++;
- }
- else
- baseindex = (*slot)->to;
- map->partition_to_base_index[x] = baseindex;
- }
-
- map->num_basevars = m - mapstorage;
-
- free (mapstorage);
-}
-
/* Given an initial var_map MAP, coalesce variables and return a partition map
with the resulting coalesce. Note that this function is called in either
live range computation context or out-of-ssa context, indicated by MAP. */
@@ -1820,10 +1728,7 @@ coalesce_ssa_name (var_map map)
partition_view_bitmap (map, used_in_copies);
- if (flag_tree_coalesce_vars)
- compute_optimized_partition_bases (map, used_in_copies, cl);
- else
- compute_samebase_partition_bases (map);
+ compute_optimized_partition_bases (map, used_in_copies, cl);
if (num_var_partitions (map) < 1)
{
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index d231486..91ce2aa 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -224,7 +224,7 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive)
{
tree callee = gimple_call_fndecl (stmt);
if (callee != NULL_TREE
- && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
+ && fndecl_built_in_p (callee, BUILT_IN_NORMAL))
switch (DECL_FUNCTION_CODE (callee))
{
case BUILT_IN_MALLOC:
@@ -565,7 +565,7 @@ mark_all_reaching_defs_necessary_1 (ao_ref *ref ATTRIBUTE_UNUSED,
{
tree callee = gimple_call_fndecl (def_stmt);
if (callee != NULL_TREE
- && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
+ && fndecl_built_in_p (callee, BUILT_IN_NORMAL))
switch (DECL_FUNCTION_CODE (callee))
{
case BUILT_IN_MALLOC:
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index a6f176c..f7cc034 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -436,7 +436,8 @@ record_edge_info (basic_block bb)
for (i = 0; i < n_labels; i++)
{
tree label = gimple_switch_label (switch_stmt, i);
- basic_block target_bb = label_to_block (CASE_LABEL (label));
+ basic_block target_bb
+ = label_to_block (cfun, CASE_LABEL (label));
if (CASE_HIGH (label)
|| !CASE_LOW (label)
|| info[target_bb->index])
@@ -1700,7 +1701,7 @@ record_equivalences_from_stmt (gimple *stmt, int may_optimize_p,
CONST_AND_COPIES. */
static void
-cprop_operand (gimple *stmt, use_operand_p op_p)
+cprop_operand (gimple *stmt, use_operand_p op_p, vr_values *vr_values)
{
tree val;
tree op = USE_FROM_PTR (op_p);
@@ -1709,6 +1710,9 @@ cprop_operand (gimple *stmt, use_operand_p op_p)
copy of some other variable, use the value or copy stored in
CONST_AND_COPIES. */
val = SSA_NAME_VALUE (op);
+ if (!val)
+ val = vr_values->op_with_constant_singleton_value_range (op);
+
if (val && val != op)
{
/* Do not replace hard register operands in asm statements. */
@@ -1765,7 +1769,7 @@ cprop_operand (gimple *stmt, use_operand_p op_p)
vdef_ops of STMT. */
static void
-cprop_into_stmt (gimple *stmt)
+cprop_into_stmt (gimple *stmt, vr_values *vr_values)
{
use_operand_p op_p;
ssa_op_iter iter;
@@ -1782,7 +1786,7 @@ cprop_into_stmt (gimple *stmt)
operands. */
if (old_op != last_copy_propagated_op)
{
- cprop_operand (stmt, op_p);
+ cprop_operand (stmt, op_p, vr_values);
tree new_op = USE_FROM_PTR (op_p);
if (new_op != old_op && TREE_CODE (new_op) == SSA_NAME)
@@ -1925,7 +1929,7 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator si)
opt_stats.num_stmts++;
/* Const/copy propagate into USES, VUSES and the RHS of VDEFs. */
- cprop_into_stmt (stmt);
+ cprop_into_stmt (stmt, evrp_range_analyzer.get_vr_values ());
/* If the statement has been modified with constant replacements,
fold its RHS before checking for redundant computations. */
@@ -1983,8 +1987,7 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator si)
certain that the value simply isn't constant. */
tree callee = gimple_call_fndecl (stmt);
if (callee
- && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (callee) == BUILT_IN_CONSTANT_P)
+ && fndecl_built_in_p (callee, BUILT_IN_CONSTANT_P))
{
propagate_tree_value_into_stmt (&si, integer_zero_node);
stmt = gsi_stmt (si);
diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c
index 4cb8c0f8..8b7aea0 100644
--- a/gcc/tree-ssa-dse.c
+++ b/gcc/tree-ssa-dse.c
@@ -248,6 +248,18 @@ compute_trims (ao_ref *ref, sbitmap live, int *trim_head, int *trim_tail,
residual handling in mem* and str* functions is usually
reasonably efficient. */
*trim_tail = last_orig - last_live;
+
+ /* But don't trim away out of bounds accesses, as this defeats
+ proper warnings.
+
+ We could have a type with no TYPE_SIZE_UNIT or we could have a VLA
+ where TYPE_SIZE_UNIT is not a constant. */
+ if (*trim_tail
+ && TYPE_SIZE_UNIT (TREE_TYPE (ref->base))
+ && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (ref->base))) == INTEGER_CST
+ && compare_tree_int (TYPE_SIZE_UNIT (TREE_TYPE (ref->base)),
+ last_orig) <= 0)
+ *trim_tail = 0;
}
else
*trim_tail = 0;
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 5607811..b1ee598 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -1071,7 +1071,7 @@ simplify_gimple_switch_label_vec (gswitch *stmt, tree index_type)
for (i = 0; i < gimple_switch_num_labels (stmt); i++)
{
tree elt = gimple_switch_label (stmt, i);
- basic_block target = label_to_block (CASE_LABEL (elt));
+ basic_block target = label_to_block (cfun, CASE_LABEL (elt));
bitmap_set_bit (target_blocks, target->index);
}
for (ei = ei_start (gimple_bb (stmt)->succs); (e = ei_safe_edge (ei)); )
@@ -1278,7 +1278,7 @@ simplify_builtin_call (gimple_stmt_iterator *gsi_p, tree callee2)
constant length. */
callee1 = gimple_call_fndecl (stmt1);
if (callee1 == NULL_TREE
- || DECL_BUILT_IN_CLASS (callee1) != BUILT_IN_NORMAL
+ || !fndecl_built_in_p (callee1, BUILT_IN_NORMAL)
|| gimple_call_num_args (stmt1) != 3)
break;
if (DECL_FUNCTION_CODE (callee1) != BUILT_IN_MEMCPY
@@ -1290,7 +1290,7 @@ simplify_builtin_call (gimple_stmt_iterator *gsi_p, tree callee2)
lhs1 = gimple_call_lhs (stmt1);
if (!tree_fits_uhwi_p (len1))
break;
- str1 = string_constant (src1, &off1);
+ str1 = string_constant (src1, &off1, NULL, NULL);
if (str1 == NULL_TREE)
break;
if (!tree_fits_uhwi_p (off1)
@@ -1391,7 +1391,7 @@ simplify_builtin_call (gimple_stmt_iterator *gsi_p, tree callee2)
src_buf, ptr1_align, false))
break;
- new_str_cst = build_string_literal (src_len + 1, src_buf);
+ new_str_cst = build_string_literal (src_len, src_buf);
if (callee1)
{
/* If STMT1 is a mem{,p}cpy call, adjust it and remove
@@ -2538,7 +2538,7 @@ pass_forwprop::execute (function *fun)
{
tree callee = gimple_call_fndecl (stmt);
if (callee != NULL_TREE
- && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
+ && fndecl_built_in_p (callee, BUILT_IN_NORMAL))
changed = simplify_builtin_call (&gsi, callee);
break;
}
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 01a954e..9c62f208 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -471,9 +471,7 @@ stmt_cost (gimple *stmt)
/* Unless the call is a builtin_constant_p; this always folds to a
constant, so moving it is useless. */
fndecl = gimple_call_fndecl (stmt);
- if (fndecl
- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)
+ if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_CONSTANT_P))
return 0;
return LIM_EXPENSIVE;
diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c
index 326589f..97c2ad9 100644
--- a/gcc/tree-ssa-loop-ivcanon.c
+++ b/gcc/tree-ssa-loop-ivcanon.c
@@ -63,6 +63,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-inline.h"
#include "tree-cfgcleanup.h"
#include "builtins.h"
+#include "tree-ssa-sccvn.h"
/* Specifies types of loops that may be unrolled. */
@@ -1318,50 +1319,6 @@ canonicalize_induction_variables (void)
return 0;
}
-/* Propagate constant SSA_NAMEs defined in basic block BB. */
-
-static void
-propagate_constants_for_unrolling (basic_block bb)
-{
- /* Look for degenerate PHI nodes with constant argument. */
- for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi); )
- {
- gphi *phi = gsi.phi ();
- tree result = gimple_phi_result (phi);
- tree arg = gimple_phi_arg_def (phi, 0);
-
- if (! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (result)
- && gimple_phi_num_args (phi) == 1
- && CONSTANT_CLASS_P (arg))
- {
- replace_uses_by (result, arg);
- gsi_remove (&gsi, true);
- release_ssa_name (result);
- }
- else
- gsi_next (&gsi);
- }
-
- /* Look for assignments to SSA names with constant RHS. */
- for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
- {
- gimple *stmt = gsi_stmt (gsi);
- tree lhs;
-
- if (is_gimple_assign (stmt)
- && TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_constant
- && (lhs = gimple_assign_lhs (stmt), TREE_CODE (lhs) == SSA_NAME)
- && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
- {
- replace_uses_by (lhs, gimple_assign_rhs1 (stmt));
- gsi_remove (&gsi, true);
- release_ssa_name (lhs);
- }
- else
- gsi_next (&gsi);
- }
-}
-
/* Process loops from innermost to outer, stopping at the innermost
loop we unrolled. */
@@ -1512,10 +1469,14 @@ tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer)
EXECUTE_IF_SET_IN_BITMAP (fathers, 0, i, bi)
{
loop_p father = get_loop (cfun, i);
- basic_block *body = get_loop_body_in_dom_order (father);
- for (unsigned j = 0; j < father->num_nodes; j++)
- propagate_constants_for_unrolling (body[j]);
- free (body);
+ bitmap exit_bbs = BITMAP_ALLOC (NULL);
+ loop_exit *exit = father->exits->next;
+ while (exit->e)
+ {
+ bitmap_set_bit (exit_bbs, exit->e->dest->index);
+ exit = exit->next;
+ }
+ do_rpo_vn (cfun, loop_preheader_edge (father), exit_bbs);
}
BITMAP_FREE (fathers);
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index fbdf838..7b6c91c 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -3231,6 +3231,7 @@ do_warn_aggressive_loop_optimizations (struct loop *loop,
char buf[WIDE_INT_PRINT_BUFFER_SIZE];
print_dec (i_bound, buf, TYPE_UNSIGNED (TREE_TYPE (loop->nb_iterations))
? UNSIGNED : SIGNED);
+ auto_diagnostic_group d;
if (warning_at (gimple_location (stmt), OPT_Waggressive_loop_optimizations,
"iteration %s invokes undefined behavior", buf))
inform (gimple_location (estmt), "within this loop");
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index e32669d..e5aa531 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -337,9 +337,9 @@ is_division_by (gimple *use_stmt, tree def)
&& gimple_assign_rhs1 (use_stmt) != def;
}
-/* Return whether USE_STMT is DEF * DEF. */
+/* Return TRUE if USE_STMT is a multiplication of DEF by A. */
static inline bool
-is_square_of (gimple *use_stmt, tree def)
+is_mult_by (gimple *use_stmt, tree def, tree a)
{
if (gimple_code (use_stmt) == GIMPLE_ASSIGN
&& gimple_assign_rhs_code (use_stmt) == MULT_EXPR)
@@ -347,11 +347,19 @@ is_square_of (gimple *use_stmt, tree def)
tree op0 = gimple_assign_rhs1 (use_stmt);
tree op1 = gimple_assign_rhs2 (use_stmt);
- return op0 == op1 && op0 == def;
+ return (op0 == def && op1 == a)
+ || (op0 == a && op1 == def);
}
return 0;
}
+/* Return whether USE_STMT is DEF * DEF. */
+static inline bool
+is_square_of (gimple *use_stmt, tree def)
+{
+ return is_mult_by (use_stmt, def, def);
+}
+
/* Return whether USE_STMT is a floating-point division by
DEF * DEF. */
static inline bool
@@ -422,6 +430,8 @@ insert_reciprocals (gimple_stmt_iterator *def_gsi, struct occurrence *occ,
gsi_next (&gsi);
gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
+ if (should_insert_square_recip)
+ gsi_insert_before (&gsi, new_square_stmt, GSI_SAME_STMT);
}
else if (def_gsi && occ->bb == def_gsi->bb)
{
@@ -429,21 +439,19 @@ insert_reciprocals (gimple_stmt_iterator *def_gsi, struct occurrence *occ,
never happen if the definition statement can throw, because in
that case the sole successor of the statement's basic block will
dominate all the uses as well. */
- gsi = *def_gsi;
gsi_insert_after (def_gsi, new_stmt, GSI_NEW_STMT);
+ if (should_insert_square_recip)
+ gsi_insert_after (def_gsi, new_square_stmt, GSI_NEW_STMT);
}
else
{
/* Case 3: insert in a basic block not containing defs/uses. */
gsi = gsi_after_labels (occ->bb);
gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
+ if (should_insert_square_recip)
+ gsi_insert_before (&gsi, new_square_stmt, GSI_SAME_STMT);
}
- /* Regardless of which case the reciprocal as inserted in,
- we insert the square immediately after the reciprocal. */
- if (should_insert_square_recip)
- gsi_insert_before (&gsi, new_square_stmt, GSI_SAME_STMT);
-
reciprocal_stats.rdivs_inserted++;
occ->recip_def_stmt = new_stmt;
@@ -526,6 +534,188 @@ free_bb (struct occurrence *occ)
}
}
+/* Transform sequences like
+ t = sqrt (a)
+ x = 1.0 / t;
+ r1 = x * x;
+ r2 = a * x;
+ into:
+ t = sqrt (a)
+ r1 = 1.0 / a;
+ r2 = t;
+ x = r1 * r2;
+ depending on the uses of x, r1, r2. This removes one multiplication and
+ allows the sqrt and division operations to execute in parallel.
+ DEF_GSI is the gsi of the initial division by sqrt that defines
+ DEF (x in the example above). */
+
+static void
+optimize_recip_sqrt (gimple_stmt_iterator *def_gsi, tree def)
+{
+ gimple *use_stmt;
+ imm_use_iterator use_iter;
+ gimple *stmt = gsi_stmt (*def_gsi);
+ tree x = def;
+ tree orig_sqrt_ssa_name = gimple_assign_rhs2 (stmt);
+ tree div_rhs1 = gimple_assign_rhs1 (stmt);
+
+ if (TREE_CODE (orig_sqrt_ssa_name) != SSA_NAME
+ || TREE_CODE (div_rhs1) != REAL_CST
+ || !real_equal (&TREE_REAL_CST (div_rhs1), &dconst1))
+ return;
+
+ gcall *sqrt_stmt
+ = dyn_cast <gcall *> (SSA_NAME_DEF_STMT (orig_sqrt_ssa_name));
+
+ if (!sqrt_stmt || !gimple_call_lhs (sqrt_stmt))
+ return;
+
+ switch (gimple_call_combined_fn (sqrt_stmt))
+ {
+ CASE_CFN_SQRT:
+ CASE_CFN_SQRT_FN:
+ break;
+
+ default:
+ return;
+ }
+ tree a = gimple_call_arg (sqrt_stmt, 0);
+
+ /* We have 'a' and 'x'. Now analyze the uses of 'x'. */
+
+ /* Statements that use x in x * x. */
+ auto_vec<gimple *> sqr_stmts;
+ /* Statements that use x in a * x. */
+ auto_vec<gimple *> mult_stmts;
+ bool has_other_use = false;
+ bool mult_on_main_path = false;
+
+ FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, x)
+ {
+ if (is_gimple_debug (use_stmt))
+ continue;
+ if (is_square_of (use_stmt, x))
+ {
+ sqr_stmts.safe_push (use_stmt);
+ if (gimple_bb (use_stmt) == gimple_bb (stmt))
+ mult_on_main_path = true;
+ }
+ else if (is_mult_by (use_stmt, x, a))
+ {
+ mult_stmts.safe_push (use_stmt);
+ if (gimple_bb (use_stmt) == gimple_bb (stmt))
+ mult_on_main_path = true;
+ }
+ else
+ has_other_use = true;
+ }
+
+ /* In the x * x and a * x cases we just rewire stmt operands or
+ remove multiplications. In the has_other_use case we introduce
+ a multiplication so make sure we don't introduce a multiplication
+ on a path where there was none. */
+ if (has_other_use && !mult_on_main_path)
+ return;
+
+ if (sqr_stmts.is_empty () && mult_stmts.is_empty ())
+ return;
+
+ /* If x = 1.0 / sqrt (a) has uses other than those optimized here we want
+ to be able to compose it from the sqr and mult cases. */
+ if (has_other_use && (sqr_stmts.is_empty () || mult_stmts.is_empty ()))
+ return;
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "Optimizing reciprocal sqrt multiplications of\n");
+ print_gimple_stmt (dump_file, sqrt_stmt, 0, TDF_NONE);
+ print_gimple_stmt (dump_file, stmt, 0, TDF_NONE);
+ fprintf (dump_file, "\n");
+ }
+
+ bool delete_div = !has_other_use;
+ tree sqr_ssa_name = NULL_TREE;
+ if (!sqr_stmts.is_empty ())
+ {
+ /* r1 = x * x. Transform the original
+ x = 1.0 / t
+ into
+ tmp1 = 1.0 / a
+ r1 = tmp1. */
+
+ sqr_ssa_name
+ = make_temp_ssa_name (TREE_TYPE (a), NULL, "recip_sqrt_sqr");
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "Replacing original division\n");
+ print_gimple_stmt (dump_file, stmt, 0, TDF_NONE);
+ fprintf (dump_file, "with new division\n");
+ }
+ gimple_assign_set_lhs (stmt, sqr_ssa_name);
+ gimple_assign_set_rhs2 (stmt, a);
+ fold_stmt_inplace (def_gsi);
+ update_stmt (stmt);
+
+ if (dump_file)
+ print_gimple_stmt (dump_file, stmt, 0, TDF_NONE);
+
+ delete_div = false;
+ gimple *sqr_stmt;
+ unsigned int i;
+ FOR_EACH_VEC_ELT (sqr_stmts, i, sqr_stmt)
+ {
+ gimple_stmt_iterator gsi2 = gsi_for_stmt (sqr_stmt);
+ gimple_assign_set_rhs_from_tree (&gsi2, sqr_ssa_name);
+ update_stmt (sqr_stmt);
+ }
+ }
+ if (!mult_stmts.is_empty ())
+ {
+ /* r2 = a * x. Transform this into:
+ r2 = t (The original sqrt (a)). */
+ unsigned int i;
+ gimple *mult_stmt = NULL;
+ FOR_EACH_VEC_ELT (mult_stmts, i, mult_stmt)
+ {
+ gimple_stmt_iterator gsi2 = gsi_for_stmt (mult_stmt);
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "Replacing squaring multiplication\n");
+ print_gimple_stmt (dump_file, mult_stmt, 0, TDF_NONE);
+ fprintf (dump_file, "with assignment\n");
+ }
+ gimple_assign_set_rhs_from_tree (&gsi2, orig_sqrt_ssa_name);
+ fold_stmt_inplace (&gsi2);
+ update_stmt (mult_stmt);
+ if (dump_file)
+ print_gimple_stmt (dump_file, mult_stmt, 0, TDF_NONE);
+ }
+ }
+
+ if (has_other_use)
+ {
+ /* Using the two temporaries tmp1, tmp2 from above
+ the original x is now:
+ x = tmp1 * tmp2. */
+ gcc_assert (orig_sqrt_ssa_name);
+ gcc_assert (sqr_ssa_name);
+
+ gimple *new_stmt
+ = gimple_build_assign (x, MULT_EXPR,
+ orig_sqrt_ssa_name, sqr_ssa_name);
+ gsi_insert_after (def_gsi, new_stmt, GSI_NEW_STMT);
+ update_stmt (stmt);
+ }
+ else if (delete_div)
+ {
+ /* Remove the original division. */
+ gimple_stmt_iterator gsi2 = gsi_for_stmt (stmt);
+ gsi_remove (&gsi2, true);
+ release_defs (stmt);
+ }
+}
/* Look for floating-point divisions among DEF's uses, and try to
replace them by multiplications with the reciprocal. Add
@@ -756,7 +946,15 @@ pass_cse_reciprocals::execute (function *fun)
&& (def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF)) != NULL
&& FLOAT_TYPE_P (TREE_TYPE (def))
&& TREE_CODE (def) == SSA_NAME)
- execute_cse_reciprocals_1 (&gsi, def);
+ {
+ execute_cse_reciprocals_1 (&gsi, def);
+ stmt = gsi_stmt (gsi);
+ if (flag_unsafe_math_optimizations
+ && is_gimple_assign (stmt)
+ && !stmt_can_throw_internal (stmt)
+ && gimple_assign_rhs_code (stmt) == RDIV_EXPR)
+ optimize_recip_sqrt (&gsi, def);
+ }
}
if (optimize_bb_for_size_p (bb))
@@ -793,7 +991,7 @@ pass_cse_reciprocals::execute (function *fun)
{
fndecl = gimple_call_fndecl (call);
if (!fndecl
- || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_MD)
+ || !fndecl_built_in_p (fndecl, BUILT_IN_MD))
continue;
fndecl = targetm.builtin_reciprocal (fndecl);
if (!fndecl)
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index eefe270..7bff676 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -515,7 +515,7 @@ add_stmt_operand (struct function *fn, tree *var_p, gimple *stmt, int flags)
{
tree var = *var_p;
- gcc_assert (SSA_VAR_P (*var_p));
+ gcc_assert (SSA_VAR_P (*var_p) || TREE_CODE (*var_p) == STRING_CST);
if (is_gimple_reg (var))
{
@@ -740,6 +740,7 @@ get_expr_operands (struct function *fn, gimple *stmt, tree *expr_p, int flags)
case VAR_DECL:
case PARM_DECL:
case RESULT_DECL:
+ case STRING_CST:
if (!(flags & opf_address_taken))
add_stmt_operand (fn, expr_p, stmt, flags);
return;
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 144902d..267086c 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -663,6 +663,7 @@ get_expr_value_id (pre_expr expr)
id = VN_INFO (PRE_EXPR_NAME (expr))->value_id;
break;
case NARY:
+ gcc_assert (!PRE_EXPR_NARY (expr)->predicated_values);
id = PRE_EXPR_NARY (expr)->value_id;
break;
case REFERENCE:
@@ -677,10 +678,10 @@ get_expr_value_id (pre_expr expr)
return id;
}
-/* Return a SCCVN valnum (SSA name or constant) for the PRE value-id VAL. */
+/* Return a VN valnum (SSA name or constant) for the PRE value-id VAL. */
static tree
-sccvn_valnum_from_value_id (unsigned int val)
+vn_valnum_from_value_id (unsigned int val)
{
bitmap_iterator bi;
unsigned int i;
@@ -1308,9 +1309,9 @@ get_representative_for (const pre_expr e, basic_block b = NULL)
??? We should be able to re-use this when we insert the statement
to compute it. */
name = make_temp_ssa_name (get_expr_type (e), gimple_build_nop (), "pretmp");
- VN_INFO_GET (name)->value_id = value_id;
+ VN_INFO (name)->value_id = value_id;
VN_INFO (name)->valnum = valnum ? valnum : name;
- /* ??? For now mark this SSA name for release by SCCVN. */
+ /* ??? For now mark this SSA name for release by VN. */
VN_INFO (name)->needs_insertion = true;
add_to_value (value_id, get_or_alloc_expr_for_name (name));
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1404,7 +1405,22 @@ phi_translate_1 (bitmap_set_t dest,
constant = find_leader_in_sets (value_id, dest,
AVAIL_OUT (pred));
if (constant)
- return constant;
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "simplifying ");
+ print_pre_expr (dump_file, expr);
+ fprintf (dump_file, " translated %d -> %d to ",
+ phiblock->index, pred->index);
+ PRE_EXPR_NARY (expr) = newnary;
+ print_pre_expr (dump_file, expr);
+ PRE_EXPR_NARY (expr) = nary;
+ fprintf (dump_file, " to ");
+ print_pre_expr (dump_file, constant);
+ fprintf (dump_file, "\n");
+ }
+ return constant;
+ }
}
}
else
@@ -1426,7 +1442,7 @@ phi_translate_1 (bitmap_set_t dest,
expr = pre_expr_pool.allocate ();
expr->kind = NARY;
expr->id = 0;
- if (nary)
+ if (nary && !nary->predicated_values)
{
PRE_EXPR_NARY (expr) = nary;
new_val_id = nary->value_id;
@@ -1664,7 +1680,10 @@ phi_translate (bitmap_set_t dest, pre_expr expr,
}
/* Translate. */
+ basic_block saved_valueize_bb = vn_context_bb;
+ vn_context_bb = e->src;
phitrans = phi_translate_1 (dest, expr, set1, set2, e);
+ vn_context_bb = saved_valueize_bb;
if (slot)
{
@@ -2414,9 +2433,7 @@ compute_antic (void)
{
/* For partial antic we ignore backedges and thus we do not need
to perform any iteration when we process blocks in postorder. */
- int postorder_num
- = pre_and_rev_post_order_compute (NULL, postorder.address (), false);
- for (i = postorder_num - 1 ; i >= 0; i--)
+ for (i = postorder.length () - 1; i >= 0; i--)
{
basic_block block = BASIC_BLOCK_FOR_FN (cfun, postorder[i]);
compute_partial_antic_aux (block,
@@ -2925,7 +2942,7 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
if (forcedname != folded)
{
- VN_INFO_GET (forcedname)->valnum = forcedname;
+ VN_INFO (forcedname)->valnum = forcedname;
VN_INFO (forcedname)->value_id = get_next_value_id ();
nameexpr = get_or_alloc_expr_for_name (forcedname);
add_to_value (VN_INFO (forcedname)->value_id, nameexpr);
@@ -2951,8 +2968,8 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
the expression may have been represented. There is no harm in replacing
here. */
value_id = get_expr_value_id (expr);
- VN_INFO_GET (name)->value_id = value_id;
- VN_INFO (name)->valnum = sccvn_valnum_from_value_id (value_id);
+ VN_INFO (name)->value_id = value_id;
+ VN_INFO (name)->valnum = vn_valnum_from_value_id (value_id);
if (VN_INFO (name)->valnum == NULL_TREE)
VN_INFO (name)->valnum = name;
gcc_assert (VN_INFO (name)->valnum != NULL_TREE);
@@ -3057,8 +3074,8 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
temp = make_temp_ssa_name (type, NULL, "prephitmp");
phi = create_phi_node (temp, block);
- VN_INFO_GET (temp)->value_id = val;
- VN_INFO (temp)->valnum = sccvn_valnum_from_value_id (val);
+ VN_INFO (temp)->value_id = val;
+ VN_INFO (temp)->valnum = vn_valnum_from_value_id (val);
if (VN_INFO (temp)->valnum == NULL_TREE)
VN_INFO (temp)->valnum = temp;
bitmap_set_bit (inserted_exprs, SSA_NAME_VERSION (temp));
@@ -3302,8 +3319,8 @@ do_pre_regular_insertion (basic_block block, basic_block dom)
gimple_stmt_iterator gsi = gsi_after_labels (block);
gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
- VN_INFO_GET (temp)->value_id = val;
- VN_INFO (temp)->valnum = sccvn_valnum_from_value_id (val);
+ VN_INFO (temp)->value_id = val;
+ VN_INFO (temp)->valnum = vn_valnum_from_value_id (val);
if (VN_INFO (temp)->valnum == NULL_TREE)
VN_INFO (temp)->valnum = temp;
bitmap_set_bit (inserted_exprs, SSA_NAME_VERSION (temp));
@@ -3744,6 +3761,7 @@ compute_avail (void)
/* Pick a block from the worklist. */
block = worklist[--sp];
+ vn_context_bb = block;
/* Initially, the set of available values in BLOCK is that of
its immediate dominator. */
@@ -3885,7 +3903,7 @@ compute_avail (void)
continue;
vn_nary_op_lookup_stmt (stmt, &nary);
- if (!nary)
+ if (!nary || nary->predicated_values)
continue;
/* If the NARY traps and there was a preceding
@@ -4045,6 +4063,7 @@ compute_avail (void)
son = next_dom_son (CDI_DOMINATORS, son))
worklist[sp++] = son;
}
+ vn_context_bb = NULL;
free (worklist);
}
@@ -4135,6 +4154,34 @@ public:
}; // class pass_pre
+/* Valueization hook for RPO VN when we are calling back to it
+ at ANTIC compute time. */
+
+static tree
+pre_valueize (tree name)
+{
+ if (TREE_CODE (name) == SSA_NAME)
+ {
+ tree tem = VN_INFO (name)->valnum;
+ if (tem != VN_TOP && tem != name)
+ {
+ if (TREE_CODE (tem) != SSA_NAME
+ || SSA_NAME_IS_DEFAULT_DEF (tem))
+ return tem;
+ /* We create temporary SSA names for representatives that
+ do not have a definition (yet) but are not default defs either
+ assume they are fine to use. */
+ basic_block def_bb = gimple_bb (SSA_NAME_DEF_STMT (tem));
+ if (! def_bb
+ || dominated_by_p (CDI_DOMINATORS, vn_context_bb, def_bb))
+ return tem;
+ /* ??? Now we could look for a leader. Ideally we'd somehow
+ expose RPO VN leaders and get rid of AVAIL_OUT as well... */
+ }
+ }
+ return name;
+}
+
unsigned int
pass_pre::execute (function *fun)
{
@@ -4143,16 +4190,18 @@ pass_pre::execute (function *fun)
do_partial_partial =
flag_tree_partial_pre && optimize_function_for_speed_p (fun);
- /* This has to happen before SCCVN runs because
+ /* This has to happen before VN runs because
loop_optimizer_init may create new phis, etc. */
loop_optimizer_init (LOOPS_NORMAL);
split_critical_edges ();
scev_initialize ();
- run_scc_vn (VN_WALK);
+ run_rpo_vn (VN_WALK);
init_pre ();
+ vn_valueize = pre_valueize;
+
/* Insert can get quite slow on an incredibly large number of basic
blocks due to some quadratic behavior. Until this behavior is
fixed, don't run it when he have an incredibly large number of
@@ -4181,8 +4230,9 @@ pass_pre::execute (function *fun)
statistics_counter_event (fun, "HOIST inserted", pre_stats.hoist_insert);
statistics_counter_event (fun, "New PHIs", pre_stats.phis);
- /* Remove all the redundant expressions. */
- todo |= vn_eliminate (inserted_exprs);
+ todo |= eliminate_with_rpo_vn (inserted_exprs);
+
+ vn_valueize = NULL;
/* Because we don't follow exactly the standard PRE algorithm, and decide not
to insert PHI nodes sometimes, and because value numbering of casts isn't
@@ -4195,9 +4245,6 @@ pass_pre::execute (function *fun)
scev_finalize ();
loop_optimizer_finalize ();
- /* Restore SSA info before tail-merging as that resets it as well. */
- scc_vn_restore_ssa_info ();
-
/* TODO: tail_merge_optimize may merge all predecessors of a block, in which
case we can merge the block with the remaining predecessor of the block.
It should either:
@@ -4207,7 +4254,7 @@ pass_pre::execute (function *fun)
- share the cfg cleanup with fini_pre. */
todo |= tail_merge_optimize (todo);
- free_scc_vn ();
+ free_rpo_vn ();
/* Tail merging invalidates the virtual SSA web, together with
cfg-cleanup opportunities exposed by PRE this will wreck the
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index 9f67a9a..140b153 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -168,10 +168,18 @@ add_ssa_edge (tree var)
FOR_EACH_IMM_USE_FAST (use_p, iter, var)
{
gimple *use_stmt = USE_STMT (use_p);
+ basic_block use_bb = gimple_bb (use_stmt);
/* If we did not yet simulate the block wait for this to happen
and do not add the stmt to the SSA edge worklist. */
- if (! (gimple_bb (use_stmt)->flags & BB_VISITED))
+ if (! (use_bb->flags & BB_VISITED))
+ continue;
+
+ /* If this is a use on a not yet executable edge do not bother to
+ queue it. */
+ if (gimple_code (use_stmt) == GIMPLE_PHI
+ && !(EDGE_PRED (use_bb, PHI_ARG_INDEX_FROM_USE (use_p))->flags
+ & EDGE_EXECUTABLE))
continue;
if (prop_simulate_again_p (use_stmt)
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 41a37ab..6b0bf5c 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -618,7 +618,7 @@ is_reassociable_op (gimple *stmt, enum tree_code code, struct loop *loop)
&& has_single_use (gimple_assign_lhs (stmt)))
{
tree rhs1 = gimple_assign_rhs1 (stmt);
- tree rhs2 = gimple_assign_rhs1 (stmt);
+ tree rhs2 = gimple_assign_rhs2 (stmt);
if (TREE_CODE (rhs1) == SSA_NAME
&& SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
return false;
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 833291a..cee3d73 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -127,11 +127,12 @@ along with GCC; see the file COPYING3. If not see
structure copies.
*/
+/* There's no BB_EXECUTABLE but we can use BB_VISITED. */
+#define BB_EXECUTABLE BB_VISITED
static tree *last_vuse_ptr;
static vn_lookup_kind vn_walk_kind;
static vn_lookup_kind default_vn_walk_kind;
-bitmap const_parms;
/* vn_nary_op hashtable helpers. */
@@ -304,34 +305,10 @@ static vn_nary_op_t last_inserted_nary;
static vn_tables_t valid_info;
-/* Reverse post order index for each basic block. */
-static int *rpo_numbers;
+/* Valueization hook. Valueize NAME if it is an SSA name, otherwise
+ just return it. */
+tree (*vn_valueize) (tree);
-#define SSA_VAL(x) (VN_INFO ((x))->valnum)
-
-/* Return the SSA value of the VUSE x, supporting released VDEFs
- during elimination which will value-number the VDEF to the
- associated VUSE (but not substitute in the whole lattice). */
-
-static inline tree
-vuse_ssa_val (tree x)
-{
- if (!x)
- return NULL_TREE;
-
- do
- {
- tree tem = SSA_VAL (x);
- /* stmt walking can walk over a backedge and reach code we didn't
- value-number yet. */
- if (tem == VN_TOP)
- return x;
- x = tem;
- }
- while (SSA_NAME_IN_FREE_LIST (x));
-
- return x;
-}
/* This represents the top of the VN lattice, which is the universal
value. */
@@ -342,66 +319,197 @@ tree VN_TOP;
static unsigned int next_value_id;
-/* Next DFS number and the stack for strongly connected component
- detection. */
-
-static unsigned int next_dfs_num;
-static vec<tree> sccstack;
-
-
/* Table of vn_ssa_aux_t's, one per ssa_name. The vn_ssa_aux_t objects
are allocated on an obstack for locality reasons, and to free them
without looping over the vec. */
-static vec<vn_ssa_aux_t> vn_ssa_aux_table;
+struct vn_ssa_aux_hasher : typed_noop_remove <vn_ssa_aux_t>
+{
+ typedef vn_ssa_aux_t value_type;
+ typedef tree compare_type;
+ static inline hashval_t hash (const value_type &);
+ static inline bool equal (const value_type &, const compare_type &);
+ static inline void mark_deleted (value_type &) {}
+ static inline void mark_empty (value_type &e) { e = NULL; }
+ static inline bool is_deleted (value_type &) { return false; }
+ static inline bool is_empty (value_type &e) { return e == NULL; }
+};
+
+hashval_t
+vn_ssa_aux_hasher::hash (const value_type &entry)
+{
+ return SSA_NAME_VERSION (entry->name);
+}
+
+bool
+vn_ssa_aux_hasher::equal (const value_type &entry, const compare_type &name)
+{
+ return name == entry->name;
+}
+
+static hash_table<vn_ssa_aux_hasher> *vn_ssa_aux_hash;
+typedef hash_table<vn_ssa_aux_hasher>::iterator vn_ssa_aux_iterator_type;
static struct obstack vn_ssa_aux_obstack;
+static vn_nary_op_t vn_nary_op_insert_stmt (gimple *, tree);
+static unsigned int vn_nary_length_from_stmt (gimple *);
+static vn_nary_op_t alloc_vn_nary_op_noinit (unsigned int, obstack *);
+static vn_nary_op_t vn_nary_op_insert_into (vn_nary_op_t,
+ vn_nary_op_table_type *, bool);
+static void init_vn_nary_op_from_stmt (vn_nary_op_t, gimple *);
+static void init_vn_nary_op_from_pieces (vn_nary_op_t, unsigned int,
+ enum tree_code, tree, tree *);
+static tree vn_lookup_simplify_result (gimple_match_op *);
+
/* Return whether there is value numbering information for a given SSA name. */
bool
has_VN_INFO (tree name)
{
- if (SSA_NAME_VERSION (name) < vn_ssa_aux_table.length ())
- return vn_ssa_aux_table[SSA_NAME_VERSION (name)] != NULL;
- return false;
+ return vn_ssa_aux_hash->find_with_hash (name, SSA_NAME_VERSION (name));
}
-/* Return the value numbering information for a given SSA name. */
-
vn_ssa_aux_t
VN_INFO (tree name)
{
- vn_ssa_aux_t res = vn_ssa_aux_table[SSA_NAME_VERSION (name)];
- gcc_checking_assert (res);
- return res;
+ vn_ssa_aux_t *res
+ = vn_ssa_aux_hash->find_slot_with_hash (name, SSA_NAME_VERSION (name),
+ INSERT);
+ if (*res != NULL)
+ return *res;
+
+ vn_ssa_aux_t newinfo = *res = XOBNEW (&vn_ssa_aux_obstack, struct vn_ssa_aux);
+ memset (newinfo, 0, sizeof (struct vn_ssa_aux));
+ newinfo->name = name;
+ newinfo->valnum = VN_TOP;
+ /* We are using the visited flag to handle uses with defs not within the
+ region being value-numbered. */
+ newinfo->visited = false;
+
+ /* Given we create the VN_INFOs on-demand now we have to do initialization
+ different than VN_TOP here. */
+ if (SSA_NAME_IS_DEFAULT_DEF (name))
+ switch (TREE_CODE (SSA_NAME_VAR (name)))
+ {
+ case VAR_DECL:
+ /* All undefined vars are VARYING. */
+ newinfo->valnum = name;
+ newinfo->visited = true;
+ break;
+
+ case PARM_DECL:
+ /* Parameters are VARYING but we can record a condition
+ if we know it is a non-NULL pointer. */
+ newinfo->visited = true;
+ newinfo->valnum = name;
+ if (POINTER_TYPE_P (TREE_TYPE (name))
+ && nonnull_arg_p (SSA_NAME_VAR (name)))
+ {
+ tree ops[2];
+ ops[0] = name;
+ ops[1] = build_int_cst (TREE_TYPE (name), 0);
+ vn_nary_op_t nary;
+ /* Allocate from non-unwinding stack. */
+ nary = alloc_vn_nary_op_noinit (2, &vn_tables_insert_obstack);
+ init_vn_nary_op_from_pieces (nary, 2, NE_EXPR,
+ boolean_type_node, ops);
+ nary->predicated_values = 0;
+ nary->u.result = boolean_true_node;
+ vn_nary_op_insert_into (nary, valid_info->nary, true);
+ gcc_assert (nary->unwind_to == NULL);
+ /* Also do not link it into the undo chain. */
+ last_inserted_nary = nary->next;
+ nary->next = (vn_nary_op_t)(void *)-1;
+ nary = alloc_vn_nary_op_noinit (2, &vn_tables_insert_obstack);
+ init_vn_nary_op_from_pieces (nary, 2, EQ_EXPR,
+ boolean_type_node, ops);
+ nary->predicated_values = 0;
+ nary->u.result = boolean_false_node;
+ vn_nary_op_insert_into (nary, valid_info->nary, true);
+ gcc_assert (nary->unwind_to == NULL);
+ last_inserted_nary = nary->next;
+ nary->next = (vn_nary_op_t)(void *)-1;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Recording ");
+ print_generic_expr (dump_file, name, TDF_SLIM);
+ fprintf (dump_file, " != 0\n");
+ }
+ }
+ break;
+
+ case RESULT_DECL:
+ /* If the result is passed by invisible reference the default
+ def is initialized, otherwise it's uninitialized. Still
+ undefined is varying. */
+ newinfo->visited = true;
+ newinfo->valnum = name;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ return newinfo;
}
-/* Set the value numbering info for a given SSA name to a given
- value. */
+/* Return the SSA value of X. */
-static inline void
-VN_INFO_SET (tree name, vn_ssa_aux_t value)
+inline tree
+SSA_VAL (tree x, bool *visited = NULL)
{
- vn_ssa_aux_table[SSA_NAME_VERSION (name)] = value;
+ vn_ssa_aux_t tem = vn_ssa_aux_hash->find_with_hash (x, SSA_NAME_VERSION (x));
+ if (visited)
+ *visited = tem && tem->visited;
+ return tem && tem->visited ? tem->valnum : x;
}
-/* Initialize the value numbering info for a given SSA name.
- This should be called just once for every SSA name. */
+/* Return whether X was visited. */
-vn_ssa_aux_t
-VN_INFO_GET (tree name)
+inline bool
+SSA_VISITED (tree x)
{
- vn_ssa_aux_t newinfo;
+ vn_ssa_aux_t tem = vn_ssa_aux_hash->find_with_hash (x, SSA_NAME_VERSION (x));
+ return tem && tem->visited;
+}
- gcc_assert (SSA_NAME_VERSION (name) >= vn_ssa_aux_table.length ()
- || vn_ssa_aux_table[SSA_NAME_VERSION (name)] == NULL);
- newinfo = XOBNEW (&vn_ssa_aux_obstack, struct vn_ssa_aux);
- memset (newinfo, 0, sizeof (struct vn_ssa_aux));
- if (SSA_NAME_VERSION (name) >= vn_ssa_aux_table.length ())
- vn_ssa_aux_table.safe_grow_cleared (SSA_NAME_VERSION (name) + 1);
- vn_ssa_aux_table[SSA_NAME_VERSION (name)] = newinfo;
- return newinfo;
+/* Return the SSA value of the VUSE x, supporting released VDEFs
+ during elimination which will value-number the VDEF to the
+ associated VUSE (but not substitute in the whole lattice). */
+
+static inline tree
+vuse_ssa_val (tree x)
+{
+ if (!x)
+ return NULL_TREE;
+
+ do
+ {
+ x = SSA_VAL (x);
+ gcc_assert (x != VN_TOP);
+ }
+ while (SSA_NAME_IN_FREE_LIST (x));
+
+ return x;
+}
+
+/* Similar to the above but used as callback for walk_non_aliases_vuses
+ and thus should stop at unvisited VUSE to not walk across region
+ boundaries. */
+
+static tree
+vuse_valueize (tree vuse)
+{
+ do
+ {
+ bool visited;
+ vuse = SSA_VAL (vuse, &visited);
+ if (!visited)
+ return NULL_TREE;
+ gcc_assert (vuse != VN_TOP);
+ }
+ while (SSA_NAME_IN_FREE_LIST (vuse));
+ return vuse;
}
@@ -490,6 +598,11 @@ get_or_alloc_constant_value_id (tree constant)
struct vn_constant_s vc;
vn_constant_t vcp;
+ /* If the hashtable isn't initialized we're not running from PRE and thus
+ do not need value-ids. */
+ if (!constant_to_value_id)
+ return 0;
+
vc.hashcode = vn_hash_constant_with_type (constant);
vc.constant = constant;
slot = constant_to_value_id->find_slot (&vc, INSERT);
@@ -1239,6 +1352,10 @@ vn_reference_maybe_forwprop_address (vec<vn_reference_op_s> *ops,
ptroff = gimple_assign_rhs2 (def_stmt);
if (TREE_CODE (ptr) != SSA_NAME
|| SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr)
+ /* Make sure to not endlessly recurse.
+ See gcc.dg/tree-ssa/20040408-1.c for an example. Can easily
+ happen when we value-number a PHI to its backedge value. */
+ || SSA_VAL (ptr) == op->op0
|| !poly_int_tree_p (ptroff))
return false;
@@ -1251,6 +1368,8 @@ vn_reference_maybe_forwprop_address (vec<vn_reference_op_s> *ops,
mem_op->off = tree_to_shwi (mem_op->op0);
else
mem_op->off = -1;
+ /* ??? Can end up with endless recursion here!?
+ gcc.c-torture/execute/strcmp-1.c */
if (TREE_CODE (op->op0) == SSA_NAME)
op->op0 = SSA_VAL (op->op0);
if (TREE_CODE (op->op0) != SSA_NAME)
@@ -1279,7 +1398,7 @@ fully_constant_vn_reference_p (vn_reference_t ref)
if (op->opcode == CALL_EXPR
&& TREE_CODE (op->op0) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (op->op0, 0)) == FUNCTION_DECL
- && DECL_BUILT_IN (TREE_OPERAND (op->op0, 0))
+ && fndecl_built_in_p (TREE_OPERAND (op->op0, 0))
&& operands.length () >= 2
&& operands.length () <= 3)
{
@@ -1314,16 +1433,17 @@ fully_constant_vn_reference_p (vn_reference_t ref)
/* Simplify reads from constants or constant initializers. */
else if (BITS_PER_UNIT == 8
- && is_gimple_reg_type (ref->type)
- && (!INTEGRAL_TYPE_P (ref->type)
- || TYPE_PRECISION (ref->type) % BITS_PER_UNIT == 0))
+ && COMPLETE_TYPE_P (ref->type)
+ && is_gimple_reg_type (ref->type))
{
poly_int64 off = 0;
HOST_WIDE_INT size;
if (INTEGRAL_TYPE_P (ref->type))
size = TYPE_PRECISION (ref->type);
- else
+ else if (tree_fits_shwi_p (TYPE_SIZE (ref->type)))
size = tree_to_shwi (TYPE_SIZE (ref->type));
+ else
+ return NULL_TREE;
if (size % BITS_PER_UNIT != 0
|| size > MAX_BITSIZE_MODE_ANY_MODE)
return NULL_TREE;
@@ -1413,7 +1533,8 @@ contains_storage_order_barrier_p (vec<vn_reference_op_s> ops)
whether any operands were valueized. */
static vec<vn_reference_op_s>
-valueize_refs_1 (vec<vn_reference_op_s> orig, bool *valueized_anything)
+valueize_refs_1 (vec<vn_reference_op_s> orig, bool *valueized_anything,
+ bool with_avail = false)
{
vn_reference_op_t vro;
unsigned int i;
@@ -1425,7 +1546,7 @@ valueize_refs_1 (vec<vn_reference_op_s> orig, bool *valueized_anything)
if (vro->opcode == SSA_NAME
|| (vro->op0 && TREE_CODE (vro->op0) == SSA_NAME))
{
- tree tem = SSA_VAL (vro->op0);
+ tree tem = with_avail ? vn_valueize (vro->op0) : SSA_VAL (vro->op0);
if (tem != vro->op0)
{
*valueized_anything = true;
@@ -1438,7 +1559,7 @@ valueize_refs_1 (vec<vn_reference_op_s> orig, bool *valueized_anything)
}
if (vro->op1 && TREE_CODE (vro->op1) == SSA_NAME)
{
- tree tem = SSA_VAL (vro->op1);
+ tree tem = with_avail ? vn_valueize (vro->op1) : SSA_VAL (vro->op1);
if (tem != vro->op1)
{
*valueized_anything = true;
@@ -1447,7 +1568,7 @@ valueize_refs_1 (vec<vn_reference_op_s> orig, bool *valueized_anything)
}
if (vro->op2 && TREE_CODE (vro->op2) == SSA_NAME)
{
- tree tem = SSA_VAL (vro->op2);
+ tree tem = with_avail ? vn_valueize (vro->op2) : SSA_VAL (vro->op2);
if (tem != vro->op2)
{
*valueized_anything = true;
@@ -1619,37 +1740,6 @@ vn_reference_lookup_or_insert_for_pieces (tree vuse,
operands.copy (), value, value_id);
}
-static vn_nary_op_t vn_nary_op_insert_stmt (gimple *, tree);
-static unsigned int vn_nary_length_from_stmt (gimple *);
-static vn_nary_op_t alloc_vn_nary_op_noinit (unsigned int, obstack *);
-static vn_nary_op_t vn_nary_op_insert_into (vn_nary_op_t,
- vn_nary_op_table_type *, bool);
-static void init_vn_nary_op_from_stmt (vn_nary_op_t, gimple *);
-
-/* Hook for maybe_push_res_to_seq, lookup the expression in the VN tables. */
-
-static tree
-vn_lookup_simplify_result (gimple_match_op *res_op)
-{
- if (!res_op->code.is_tree_code ())
- return NULL_TREE;
- tree *ops = res_op->ops;
- unsigned int length = res_op->num_ops;
- if (res_op->code == CONSTRUCTOR
- /* ??? We're arriving here with SCCVNs view, decomposed CONSTRUCTOR
- and GIMPLEs / match-and-simplifies, CONSTRUCTOR as GENERIC tree. */
- && TREE_CODE (res_op->ops[0]) == CONSTRUCTOR)
- {
- length = CONSTRUCTOR_NELTS (res_op->ops[0]);
- ops = XALLOCAVEC (tree, length);
- for (unsigned i = 0; i < length; ++i)
- ops[i] = CONSTRUCTOR_ELT (res_op->ops[0], i)->value;
- }
- vn_nary_op_t vnresult = NULL;
- return vn_nary_op_lookup_pieces (length, (tree_code) res_op->code,
- res_op->type, ops, &vnresult);
-}
-
/* Return a value-number for RCODE OPS... either by looking up an existing
value-number for the simplified result or by inserting the operation if
INSERT is true. */
@@ -1680,8 +1770,13 @@ vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert)
gimple *new_stmt = NULL;
if (res
&& gimple_simplified_result_is_gimple_val (res_op))
- /* The expression is already available. */
- result = res_op->ops[0];
+ {
+ /* The expression is already available. */
+ result = res_op->ops[0];
+ /* Valueize it, simplification returns sth in AVAIL only. */
+ if (TREE_CODE (result) == SSA_NAME)
+ result = SSA_VAL (result);
+ }
else
{
tree val = vn_lookup_simplify_result (res_op);
@@ -1704,11 +1799,13 @@ vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert)
/* The expression is not yet available, value-number lhs to
the new SSA_NAME we created. */
/* Initialize value-number information properly. */
- VN_INFO_GET (result)->valnum = result;
- VN_INFO (result)->value_id = get_next_value_id ();
+ vn_ssa_aux_t result_info = VN_INFO (result);
+ result_info->valnum = result;
+ result_info->value_id = get_next_value_id ();
+ result_info->visited = 1;
gimple_seq_add_stmt_without_update (&VN_INFO (result)->expr,
new_stmt);
- VN_INFO (result)->needs_insertion = true;
+ result_info->needs_insertion = true;
/* ??? PRE phi-translation inserts NARYs without corresponding
SSA name result. Re-use those but set their result according
to the stmt we just built. */
@@ -1716,8 +1813,8 @@ vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert)
vn_nary_op_lookup_stmt (new_stmt, &nary);
if (nary)
{
- gcc_assert (nary->result == NULL_TREE);
- nary->result = gimple_assign_lhs (new_stmt);
+ gcc_assert (! nary->predicated_values && nary->u.result == NULL_TREE);
+ nary->u.result = gimple_assign_lhs (new_stmt);
}
/* As all "inserted" statements are singleton SCCs, insert
to the valid table. This is strictly needed to
@@ -1731,9 +1828,10 @@ vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert)
unsigned int length = vn_nary_length_from_stmt (new_stmt);
vn_nary_op_t vno1
= alloc_vn_nary_op_noinit (length, &vn_tables_insert_obstack);
- vno1->value_id = VN_INFO (result)->value_id;
+ vno1->value_id = result_info->value_id;
vno1->length = length;
- vno1->result = result;
+ vno1->predicated_values = 0;
+ vno1->u.result = result;
init_vn_nary_op_from_stmt (vno1, new_stmt);
vn_nary_op_insert_into (vno1, valid_info->nary, true);
/* Also do not link it into the undo chain. */
@@ -1775,6 +1873,7 @@ vn_nary_simplify (vn_nary_op_t nary)
return vn_nary_build_or_lookup_1 (&op, false);
}
+basic_block vn_context_bb;
/* Callback for walk_non_aliased_vuses. Tries to perform a lookup
from the statement defining VUSE and if not successful tries to
@@ -1796,18 +1895,6 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
bool lhs_ref_ok = false;
poly_int64 copy_size;
- /* If the reference is based on a parameter that was determined as
- pointing to readonly memory it doesn't change. */
- if (TREE_CODE (base) == MEM_REF
- && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME
- && SSA_NAME_IS_DEFAULT_DEF (TREE_OPERAND (base, 0))
- && bitmap_bit_p (const_parms,
- SSA_NAME_VERSION (TREE_OPERAND (base, 0))))
- {
- *disambiguate_only = true;
- return NULL;
- }
-
/* First try to disambiguate after value-replacing in the definitions LHS. */
if (is_gimple_assign (def_stmt))
{
@@ -1815,8 +1902,11 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
bool valueized_anything = false;
/* Avoid re-allocation overhead. */
lhs_ops.truncate (0);
+ basic_block saved_rpo_bb = vn_context_bb;
+ vn_context_bb = gimple_bb (def_stmt);
copy_reference_ops_from_ref (lhs, &lhs_ops);
- lhs_ops = valueize_refs_1 (lhs_ops, &valueized_anything);
+ lhs_ops = valueize_refs_1 (lhs_ops, &valueized_anything, true);
+ vn_context_bb = saved_rpo_bb;
if (valueized_anything)
{
lhs_ref_ok = ao_ref_init_from_vn_reference (&lhs_ref,
@@ -2141,7 +2231,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
{
gimple_match_op op (gimple_match_cond::UNCOND,
BIT_FIELD_REF, vr->type,
- SSA_VAL (gimple_assign_rhs1 (def_stmt)),
+ vn_valueize (gimple_assign_rhs1 (def_stmt)),
bitsize_int (ref->size),
bitsize_int (offset - offset2));
tree val = vn_nary_build_or_lookup (&op);
@@ -2316,7 +2406,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
lhs_offset = 0;
if (TREE_CODE (lhs) == SSA_NAME)
{
- lhs = SSA_VAL (lhs);
+ lhs = vn_valueize (lhs);
if (TREE_CODE (lhs) == SSA_NAME)
{
gimple *def_stmt = SSA_NAME_DEF_STMT (lhs);
@@ -2336,7 +2426,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
{
lhs = TREE_OPERAND (tem, 0);
if (TREE_CODE (lhs) == SSA_NAME)
- lhs = SSA_VAL (lhs);
+ lhs = vn_valueize (lhs);
lhs_offset += mem_offset;
}
else if (DECL_P (tem))
@@ -2352,7 +2442,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
rhs = gimple_call_arg (def_stmt, 1);
rhs_offset = 0;
if (TREE_CODE (rhs) == SSA_NAME)
- rhs = SSA_VAL (rhs);
+ rhs = vn_valueize (rhs);
if (TREE_CODE (rhs) == ADDR_EXPR)
{
tree tem = get_addr_base_and_unit_offset (TREE_OPERAND (rhs, 0),
@@ -2502,7 +2592,7 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type,
(vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
vn_reference_lookup_2,
vn_reference_lookup_3,
- vuse_ssa_val, &vr1);
+ vuse_valueize, &vr1);
gcc_checking_assert (vr1.operands == shared_lookup_references);
}
@@ -2558,7 +2648,7 @@ vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind,
(vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
vn_reference_lookup_2,
vn_reference_lookup_3,
- vuse_ssa_val, &vr1);
+ vuse_valueize, &vr1);
gcc_checking_assert (vr1.operands == shared_lookup_references);
if (wvnresult)
{
@@ -2593,10 +2683,9 @@ vn_reference_lookup_call (gcall *call, vn_reference_t *vnresult,
vn_reference_lookup_1 (vr, vnresult);
}
-/* Insert OP into the current hash table with a value number of
- RESULT, and return the resulting reference structure we created. */
+/* Insert OP into the current hash table with a value number of RESULT. */
-static vn_reference_t
+static void
vn_reference_insert (tree op, tree result, tree vuse, tree vdef)
{
vn_reference_s **slot;
@@ -2608,7 +2697,7 @@ vn_reference_insert (tree op, tree result, tree vuse, tree vdef)
vr1->value_id = VN_INFO (result)->value_id;
else
vr1->value_id = get_or_alloc_constant_value_id (result);
- vr1->vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
+ vr1->vuse = vuse_ssa_val (vuse);
vr1->operands = valueize_shared_reference_ops_from_ref (op, &tem).copy ();
vr1->type = TREE_TYPE (op);
vr1->set = get_alias_set (op);
@@ -2617,24 +2706,35 @@ vn_reference_insert (tree op, tree result, tree vuse, tree vdef)
vr1->result_vdef = vdef;
slot = valid_info->references->find_slot_with_hash (vr1, vr1->hashcode,
- INSERT);
-
- /* Because we lookup stores using vuses, and value number failures
- using the vdefs (see visit_reference_op_store for how and why),
- it's possible that on failure we may try to insert an already
- inserted store. This is not wrong, there is no ssa name for a
- store that we could use as a differentiator anyway. Thus, unlike
- the other lookup functions, you cannot gcc_assert (!*slot)
- here. */
-
- /* But free the old slot in case of a collision. */
+ INSERT);
+
+ /* Because IL walking on reference lookup can end up visiting
+ a def that is only to be visited later in iteration order
+ when we are about to make an irreducible region reducible
+ the def can be effectively processed and its ref being inserted
+ by vn_reference_lookup_3 already. So we cannot assert (!*slot)
+ but save a lookup if we deal with already inserted refs here. */
if (*slot)
- free_reference (*slot);
+ {
+ /* We cannot assert that we have the same value either because
+ when disentangling an irreducible region we may end up visiting
+ a use before the corresponding def. That's a missed optimization
+ only though. See gcc.dg/tree-ssa/pr87126.c for example. */
+ if (dump_file && (dump_flags & TDF_DETAILS)
+ && !operand_equal_p ((*slot)->result, vr1->result, 0))
+ {
+ fprintf (dump_file, "Keeping old value ");
+ print_generic_expr (dump_file, (*slot)->result);
+ fprintf (dump_file, " because of collision\n");
+ }
+ free_reference (vr1);
+ obstack_free (&vn_tables_obstack, vr1);
+ return;
+ }
*slot = vr1;
vr1->next = last_inserted_ref;
last_inserted_ref = vr1;
- return vr1;
}
/* Insert a reference by it's pieces into the current hash table with
@@ -2652,7 +2752,7 @@ vn_reference_insert_pieces (tree vuse, alias_set_type set, tree type,
vr1 = XOBNEW (&vn_tables_obstack, vn_reference_s);
vr1->value_id = value_id;
- vr1->vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
+ vr1->vuse = vuse_ssa_val (vuse);
vr1->operands = valueize_refs (operands);
vr1->type = type;
vr1->set = set;
@@ -2662,14 +2762,12 @@ vn_reference_insert_pieces (tree vuse, alias_set_type set, tree type,
vr1->result = result;
slot = valid_info->references->find_slot_with_hash (vr1, vr1->hashcode,
- INSERT);
+ INSERT);
/* At this point we should have all the things inserted that we have
seen before, and we should never try inserting something that
already exists. */
gcc_assert (!*slot);
- if (*slot)
- free_reference (*slot);
*slot = vr1;
vr1->next = last_inserted_ref;
@@ -2845,13 +2943,12 @@ vn_nary_op_lookup_1 (vn_nary_op_t vno, vn_nary_op_t *vnresult)
*vnresult = NULL;
vno->hashcode = vn_nary_op_compute_hash (vno);
- slot = valid_info->nary->find_slot_with_hash (vno, vno->hashcode,
- NO_INSERT);
+ slot = valid_info->nary->find_slot_with_hash (vno, vno->hashcode, NO_INSERT);
if (!slot)
return NULL_TREE;
if (vnresult)
*vnresult = *slot;
- return (*slot)->result;
+ return (*slot)->predicated_values ? NULL_TREE : (*slot)->u.result;
}
/* Lookup a n-ary operation by its pieces and return the resulting value
@@ -2919,7 +3016,8 @@ alloc_vn_nary_op (unsigned int length, tree result, unsigned int value_id)
vno1->value_id = value_id;
vno1->length = length;
- vno1->result = result;
+ vno1->predicated_values = 0;
+ vno1->u.result = result;
return vno1;
}
@@ -2934,18 +3032,124 @@ vn_nary_op_insert_into (vn_nary_op_t vno, vn_nary_op_table_type *table,
vn_nary_op_s **slot;
if (compute_hash)
- vno->hashcode = vn_nary_op_compute_hash (vno);
+ {
+ vno->hashcode = vn_nary_op_compute_hash (vno);
+ gcc_assert (! vno->predicated_values
+ || (! vno->u.values->next
+ && vno->u.values->n == 1));
+ }
slot = table->find_slot_with_hash (vno, vno->hashcode, INSERT);
- /* While we do not want to insert things twice it's awkward to
- avoid it in the case where visit_nary_op pattern-matches stuff
- and ends up simplifying the replacement to itself. We then
- get two inserts, one from visit_nary_op and one from
- vn_nary_build_or_lookup.
- So allow inserts with the same value number. */
- if (*slot && (*slot)->result == vno->result)
- return *slot;
+ vno->unwind_to = *slot;
+ if (*slot)
+ {
+ /* Prefer non-predicated values.
+ ??? Only if those are constant, otherwise, with constant predicated
+ value, turn them into predicated values with entry-block validity
+ (??? but we always find the first valid result currently). */
+ if ((*slot)->predicated_values
+ && ! vno->predicated_values)
+ {
+ /* ??? We cannot remove *slot from the unwind stack list.
+ For the moment we deal with this by skipping not found
+ entries but this isn't ideal ... */
+ *slot = vno;
+ /* ??? Maintain a stack of states we can unwind in
+ vn_nary_op_s? But how far do we unwind? In reality
+ we need to push change records somewhere... Or not
+ unwind vn_nary_op_s and linking them but instead
+ unwind the results "list", linking that, which also
+ doesn't move on hashtable resize. */
+ /* We can also have a ->unwind_to recording *slot there.
+ That way we can make u.values a fixed size array with
+ recording the number of entries but of course we then
+ have always N copies for each unwind_to-state. Or we
+ make sure to only ever append and each unwinding will
+ pop off one entry (but how to deal with predicated
+ replaced with non-predicated here?) */
+ vno->next = last_inserted_nary;
+ last_inserted_nary = vno;
+ return vno;
+ }
+ else if (vno->predicated_values
+ && ! (*slot)->predicated_values)
+ return *slot;
+ else if (vno->predicated_values
+ && (*slot)->predicated_values)
+ {
+ /* ??? Factor this all into a insert_single_predicated_value
+ routine. */
+ gcc_assert (!vno->u.values->next && vno->u.values->n == 1);
+ basic_block vno_bb
+ = BASIC_BLOCK_FOR_FN (cfun, vno->u.values->valid_dominated_by_p[0]);
+ vn_pval *nval = vno->u.values;
+ vn_pval **next = &vno->u.values;
+ bool found = false;
+ for (vn_pval *val = (*slot)->u.values; val; val = val->next)
+ {
+ if (expressions_equal_p (val->result, vno->u.values->result))
+ {
+ found = true;
+ for (unsigned i = 0; i < val->n; ++i)
+ {
+ basic_block val_bb
+ = BASIC_BLOCK_FOR_FN (cfun,
+ val->valid_dominated_by_p[i]);
+ if (dominated_by_p (CDI_DOMINATORS, vno_bb, val_bb))
+ /* Value registered with more generic predicate. */
+ return *slot;
+ else if (dominated_by_p (CDI_DOMINATORS, val_bb, vno_bb))
+ /* Shouldn't happen, we insert in RPO order. */
+ gcc_unreachable ();
+ }
+ /* Append value. */
+ *next = (vn_pval *) obstack_alloc (&vn_tables_obstack,
+ sizeof (vn_pval)
+ + val->n * sizeof (int));
+ (*next)->next = NULL;
+ (*next)->result = val->result;
+ (*next)->n = val->n + 1;
+ memcpy ((*next)->valid_dominated_by_p,
+ val->valid_dominated_by_p,
+ val->n * sizeof (int));
+ (*next)->valid_dominated_by_p[val->n] = vno_bb->index;
+ next = &(*next)->next;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Appending predicate to value.\n");
+ continue;
+ }
+ /* Copy other predicated values. */
+ *next = (vn_pval *) obstack_alloc (&vn_tables_obstack,
+ sizeof (vn_pval)
+ + (val->n-1) * sizeof (int));
+ memcpy (*next, val, sizeof (vn_pval) + (val->n-1) * sizeof (int));
+ (*next)->next = NULL;
+ next = &(*next)->next;
+ }
+ if (!found)
+ *next = nval;
+
+ *slot = vno;
+ vno->next = last_inserted_nary;
+ last_inserted_nary = vno;
+ return vno;
+ }
+
+ /* While we do not want to insert things twice it's awkward to
+ avoid it in the case where visit_nary_op pattern-matches stuff
+ and ends up simplifying the replacement to itself. We then
+ get two inserts, one from visit_nary_op and one from
+ vn_nary_build_or_lookup.
+ So allow inserts with the same value number. */
+ if ((*slot)->u.result == vno->u.result)
+ return *slot;
+ }
+ /* ??? There's also optimistic vs. previous commited state merging
+ that is problematic for the case of unwinding. */
+
+ /* ??? We should return NULL if we do not use 'vno' and have the
+ caller release it. */
gcc_assert (!*slot);
*slot = vno;
@@ -2968,6 +3172,69 @@ vn_nary_op_insert_pieces (unsigned int length, enum tree_code code,
return vn_nary_op_insert_into (vno1, valid_info->nary, true);
}
+static vn_nary_op_t
+vn_nary_op_insert_pieces_predicated (unsigned int length, enum tree_code code,
+ tree type, tree *ops,
+ tree result, unsigned int value_id,
+ edge pred_e)
+{
+ /* ??? Currently tracking BBs. */
+ if (! single_pred_p (pred_e->dest))
+ {
+ /* Never record for backedges. */
+ if (pred_e->flags & EDGE_DFS_BACK)
+ return NULL;
+ edge_iterator ei;
+ edge e;
+ int cnt = 0;
+ /* Ignore backedges. */
+ FOR_EACH_EDGE (e, ei, pred_e->dest->preds)
+ if (! dominated_by_p (CDI_DOMINATORS, e->src, e->dest))
+ cnt++;
+ if (cnt != 1)
+ return NULL;
+ }
+ if (dump_file && (dump_flags & TDF_DETAILS)
+ /* ??? Fix dumping, but currently we only get comparisons. */
+ && TREE_CODE_CLASS (code) == tcc_comparison)
+ {
+ fprintf (dump_file, "Recording on edge %d->%d ", pred_e->src->index,
+ pred_e->dest->index);
+ print_generic_expr (dump_file, ops[0], TDF_SLIM);
+ fprintf (dump_file, " %s ", get_tree_code_name (code));
+ print_generic_expr (dump_file, ops[1], TDF_SLIM);
+ fprintf (dump_file, " == %s\n",
+ integer_zerop (result) ? "false" : "true");
+ }
+ vn_nary_op_t vno1 = alloc_vn_nary_op (length, NULL_TREE, value_id);
+ init_vn_nary_op_from_pieces (vno1, length, code, type, ops);
+ vno1->predicated_values = 1;
+ vno1->u.values = (vn_pval *) obstack_alloc (&vn_tables_obstack,
+ sizeof (vn_pval));
+ vno1->u.values->next = NULL;
+ vno1->u.values->result = result;
+ vno1->u.values->n = 1;
+ vno1->u.values->valid_dominated_by_p[0] = pred_e->dest->index;
+ return vn_nary_op_insert_into (vno1, valid_info->nary, true);
+}
+
+static bool
+dominated_by_p_w_unex (basic_block bb1, basic_block bb2);
+
+static tree
+vn_nary_op_get_predicated_value (vn_nary_op_t vno, basic_block bb)
+{
+ if (! vno->predicated_values)
+ return vno->u.result;
+ for (vn_pval *val = vno->u.values; val; val = val->next)
+ for (unsigned i = 0; i < val->n; ++i)
+ if (dominated_by_p_w_unex (bb,
+ BASIC_BLOCK_FOR_FN
+ (cfun, val->valid_dominated_by_p[i])))
+ return val->result;
+ return NULL_TREE;
+}
+
/* Insert OP into the current hash table with a value number of
RESULT. Return the vn_nary_op_t structure we created and put in
the hashtable. */
@@ -3170,7 +3437,7 @@ vn_phi_eq (const_vn_phi_t const vp1, const_vn_phi_t const vp2)
it does not exist in the hash table. */
static tree
-vn_phi_lookup (gimple *phi)
+vn_phi_lookup (gimple *phi, bool backedges_varying_p)
{
vn_phi_s **slot;
struct vn_phi_s *vp1;
@@ -3185,7 +3452,9 @@ vn_phi_lookup (gimple *phi)
FOR_EACH_EDGE (e, ei, gimple_bb (phi)->preds)
{
tree def = PHI_ARG_DEF_FROM_EDGE (phi, e);
- def = TREE_CODE (def) == SSA_NAME ? SSA_VAL (def) : def;
+ if (TREE_CODE (def) == SSA_NAME
+ && (!backedges_varying_p || !(e->flags & EDGE_DFS_BACK)))
+ def = SSA_VAL (def);
vp1->phiargs[e->dest_idx] = def;
}
vp1->type = TREE_TYPE (gimple_phi_result (phi));
@@ -3197,12 +3466,13 @@ vn_phi_lookup (gimple *phi)
if (EDGE_COUNT (idom1->succs) == 2)
if (gcond *last1 = safe_dyn_cast <gcond *> (last_stmt (idom1)))
{
+ /* ??? We want to use SSA_VAL here. But possibly not
+ allow VN_TOP. */
vp1->cclhs = vn_valueize (gimple_cond_lhs (last1));
vp1->ccrhs = vn_valueize (gimple_cond_rhs (last1));
}
vp1->hashcode = vn_phi_compute_hash (vp1);
- slot = valid_info->phis->find_slot_with_hash (vp1, vp1->hashcode,
- NO_INSERT);
+ slot = valid_info->phis->find_slot_with_hash (vp1, vp1->hashcode, NO_INSERT);
if (!slot)
return NULL_TREE;
return (*slot)->result;
@@ -3212,7 +3482,7 @@ vn_phi_lookup (gimple *phi)
RESULT. */
static vn_phi_t
-vn_phi_insert (gimple *phi, tree result)
+vn_phi_insert (gimple *phi, tree result, bool backedges_varying_p)
{
vn_phi_s **slot;
vn_phi_t vp1 = (vn_phi_t) obstack_alloc (&vn_tables_obstack,
@@ -3226,7 +3496,9 @@ vn_phi_insert (gimple *phi, tree result)
FOR_EACH_EDGE (e, ei, gimple_bb (phi)->preds)
{
tree def = PHI_ARG_DEF_FROM_EDGE (phi, e);
- def = TREE_CODE (def) == SSA_NAME ? SSA_VAL (def) : def;
+ if (TREE_CODE (def) == SSA_NAME
+ && (!backedges_varying_p || !(e->flags & EDGE_DFS_BACK)))
+ def = SSA_VAL (def);
vp1->phiargs[e->dest_idx] = def;
}
vp1->value_id = VN_INFO (result)->value_id;
@@ -3239,6 +3511,8 @@ vn_phi_insert (gimple *phi, tree result)
if (EDGE_COUNT (idom1->succs) == 2)
if (gcond *last1 = safe_dyn_cast <gcond *> (last_stmt (idom1)))
{
+ /* ??? We want to use SSA_VAL here. But possibly not
+ allow VN_TOP. */
vp1->cclhs = vn_valueize (gimple_cond_lhs (last1));
vp1->ccrhs = vn_valueize (gimple_cond_rhs (last1));
}
@@ -3246,9 +3520,8 @@ vn_phi_insert (gimple *phi, tree result)
vp1->hashcode = vn_phi_compute_hash (vp1);
slot = valid_info->phis->find_slot_with_hash (vp1, vp1->hashcode, INSERT);
+ gcc_assert (!*slot);
- /* Because we iterate over phi operations more than once, it's
- possible the slot might already exist here, hence no assert.*/
*slot = vp1;
vp1->next = last_inserted_phi;
last_inserted_phi = vp1;
@@ -3256,23 +3529,6 @@ vn_phi_insert (gimple *phi, tree result)
}
-/* Print set of components in strongly connected component SCC to OUT. */
-
-static void
-print_scc (FILE *out, vec<tree> scc)
-{
- tree var;
- unsigned int i;
-
- fprintf (out, "SCC consists of %u:", scc.length ());
- FOR_EACH_VEC_ELT (scc, i, var)
- {
- fprintf (out, " ");
- print_generic_expr (out, var);
- }
- fprintf (out, "\n");
-}
-
/* Return true if BB1 is dominated by BB2 taking into account edges
that are not executable. */
@@ -3360,7 +3616,8 @@ dominated_by_p_w_unex (basic_block bb1, basic_block bb2)
static inline bool
set_ssa_val_to (tree from, tree to)
{
- tree currval = SSA_VAL (from);
+ vn_ssa_aux_t from_info = VN_INFO (from);
+ tree currval = from_info->valnum; // SSA_VAL (from)
poly_int64 toff, coff;
/* The only thing we allow as value numbers are ssa_names
@@ -3372,16 +3629,23 @@ set_ssa_val_to (tree from, tree to)
get VN_TOP on valueization. */
if (to == VN_TOP)
{
+ /* ??? When iterating and visiting PHI <undef, backedge-value>
+ for the first time we rightfully get VN_TOP and we need to
+ preserve that to optimize for example gcc.dg/tree-ssa/ssa-sccvn-2.c.
+ With SCCVN we were simply lucky we iterated the other PHI
+ cycles first and thus visited the backedge-value DEF. */
+ if (currval == VN_TOP)
+ goto set_and_exit;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Forcing value number to varying on "
"receiving VN_TOP\n");
to = from;
}
- gcc_assert (to != NULL_TREE
- && ((TREE_CODE (to) == SSA_NAME
- && (to == from || SSA_VAL (to) == to))
- || is_gimple_min_invariant (to)));
+ gcc_checking_assert (to != NULL_TREE
+ && ((TREE_CODE (to) == SSA_NAME
+ && (to == from || SSA_VAL (to) == to))
+ || is_gimple_min_invariant (to)));
if (from != to)
{
@@ -3399,6 +3663,7 @@ set_ssa_val_to (tree from, tree to)
}
else if (currval != VN_TOP
&& ! is_gimple_min_invariant (currval)
+ && ! ssa_undefined_value_p (currval, false)
&& is_gimple_min_invariant (to))
{
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -3419,6 +3684,7 @@ set_ssa_val_to (tree from, tree to)
to = from;
}
+set_and_exit:
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Setting value number of ");
@@ -3447,73 +3713,7 @@ set_ssa_val_to (tree from, tree to)
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " (changed)\n");
-
- /* If we equate two SSA names we have to make the side-band info
- of the leader conservative (and remember whatever original value
- was present). */
- if (TREE_CODE (to) == SSA_NAME)
- {
- if (INTEGRAL_TYPE_P (TREE_TYPE (to))
- && SSA_NAME_RANGE_INFO (to))
- {
- if (SSA_NAME_IS_DEFAULT_DEF (to)
- || dominated_by_p_w_unex
- (gimple_bb (SSA_NAME_DEF_STMT (from)),
- gimple_bb (SSA_NAME_DEF_STMT (to))))
- /* Keep the info from the dominator. */
- ;
- else
- {
- /* Save old info. */
- if (! VN_INFO (to)->info.range_info)
- {
- VN_INFO (to)->info.range_info = SSA_NAME_RANGE_INFO (to);
- VN_INFO (to)->range_info_anti_range_p
- = SSA_NAME_ANTI_RANGE_P (to);
- }
- /* Rather than allocating memory and unioning the info
- just clear it. */
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "clearing range info of ");
- print_generic_expr (dump_file, to);
- fprintf (dump_file, "\n");
- }
- SSA_NAME_RANGE_INFO (to) = NULL;
- }
- }
- else if (POINTER_TYPE_P (TREE_TYPE (to))
- && SSA_NAME_PTR_INFO (to))
- {
- if (SSA_NAME_IS_DEFAULT_DEF (to)
- || dominated_by_p_w_unex
- (gimple_bb (SSA_NAME_DEF_STMT (from)),
- gimple_bb (SSA_NAME_DEF_STMT (to))))
- /* Keep the info from the dominator. */
- ;
- else if (! SSA_NAME_PTR_INFO (from)
- /* Handle the case of trivially equivalent info. */
- || memcmp (SSA_NAME_PTR_INFO (to),
- SSA_NAME_PTR_INFO (from),
- sizeof (ptr_info_def)) != 0)
- {
- /* Save old info. */
- if (! VN_INFO (to)->info.ptr_info)
- VN_INFO (to)->info.ptr_info = SSA_NAME_PTR_INFO (to);
- /* Rather than allocating memory and unioning the info
- just clear it. */
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "clearing points-to info of ");
- print_generic_expr (dump_file, to);
- fprintf (dump_file, "\n");
- }
- SSA_NAME_PTR_INFO (to) = NULL;
- }
- }
- }
-
- VN_INFO (from)->valnum = to;
+ from_info->valnum = to;
return true;
}
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -3521,30 +3721,6 @@ set_ssa_val_to (tree from, tree to)
return false;
}
-/* Mark as processed all the definitions in the defining stmt of USE, or
- the USE itself. */
-
-static void
-mark_use_processed (tree use)
-{
- ssa_op_iter iter;
- def_operand_p defp;
- gimple *stmt = SSA_NAME_DEF_STMT (use);
-
- if (SSA_NAME_IS_DEFAULT_DEF (use) || gimple_code (stmt) == GIMPLE_PHI)
- {
- VN_INFO (use)->use_processed = true;
- return;
- }
-
- FOR_EACH_SSA_DEF_OPERAND (defp, stmt, iter, SSA_OP_ALL_DEFS)
- {
- tree def = DEF_FROM_PTR (defp);
-
- VN_INFO (def)->use_processed = true;
- }
-}
-
/* Set all definitions in STMT to value number to themselves.
Return true if a value number changed. */
@@ -3582,7 +3758,7 @@ static tree
valueized_wider_op (tree wide_type, tree op)
{
if (TREE_CODE (op) == SSA_NAME)
- op = SSA_VAL (op);
+ op = vn_valueize (op);
/* Either we have the op widened available. */
tree ops[3] = {};
@@ -3603,7 +3779,7 @@ valueized_wider_op (tree wide_type, tree op)
if (useless_type_conversion_p (wide_type, TREE_TYPE (tem)))
{
if (TREE_CODE (tem) == SSA_NAME)
- tem = SSA_VAL (tem);
+ tem = vn_valueize (tem);
return tem;
}
}
@@ -3622,7 +3798,10 @@ valueized_wider_op (tree wide_type, tree op)
static bool
visit_nary_op (tree lhs, gassign *stmt)
{
- tree result = vn_nary_op_lookup_stmt (stmt, NULL);
+ vn_nary_op_t vnresult;
+ tree result = vn_nary_op_lookup_stmt (stmt, &vnresult);
+ if (! result && vnresult)
+ result = vn_nary_op_get_predicated_value (vnresult, gimple_bb (stmt));
if (result)
return set_ssa_val_to (lhs, result);
@@ -3773,7 +3952,7 @@ visit_reference_op_call (tree lhs, gcall *stmt)
vr2->result = lhs;
vr2->result_vdef = vdef_val;
slot = valid_info->references->find_slot_with_hash (vr2, vr2->hashcode,
- INSERT);
+ INSERT);
gcc_assert (!*slot);
*slot = vr2;
vr2->next = last_inserted_ref;
@@ -3812,6 +3991,10 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt)
gimple_match_op res_op (gimple_match_cond::UNCOND,
VIEW_CONVERT_EXPR, TREE_TYPE (op), result);
result = vn_nary_build_or_lookup (&res_op);
+ /* When building the conversion fails avoid inserting the reference
+ again. */
+ if (!result)
+ return set_ssa_val_to (lhs, lhs);
}
if (result)
@@ -3863,8 +4046,8 @@ visit_reference_op_store (tree lhs, tree op, gimple *stmt)
&& vnresult->result)
{
tree result = vnresult->result;
- if (TREE_CODE (result) == SSA_NAME)
- result = SSA_VAL (result);
+ gcc_checking_assert (TREE_CODE (result) != SSA_NAME
+ || result == SSA_VAL (result));
resultsame = expressions_equal_p (result, op);
if (resultsame)
{
@@ -3887,7 +4070,7 @@ visit_reference_op_store (tree lhs, tree op, gimple *stmt)
vn_reference_lookup (assign, vuse, VN_NOWALK, &vnresult, false);
if (vnresult)
{
- VN_INFO (vdef)->use_processed = true;
+ VN_INFO (vdef)->visited = true;
return set_ssa_val_to (vdef, vnresult->result_vdef);
}
}
@@ -3935,22 +4118,34 @@ visit_reference_op_store (tree lhs, tree op, gimple *stmt)
}
/* Visit and value number PHI, return true if the value number
- changed. */
+ changed. When BACKEDGES_VARYING_P is true then assume all
+ backedge values are varying. When INSERTED is not NULL then
+ this is just a ahead query for a possible iteration, set INSERTED
+ to true if we'd insert into the hashtable. */
static bool
-visit_phi (gimple *phi)
+visit_phi (gimple *phi, bool *inserted, bool backedges_varying_p)
{
tree result, sameval = VN_TOP, seen_undef = NULL_TREE;
+ tree backedge_val = NULL_TREE;
+ bool seen_non_backedge = false;
+ tree sameval_base = NULL_TREE;
+ poly_int64 soff, doff;
unsigned n_executable = 0;
- bool allsame = true;
edge_iterator ei;
edge e;
- /* TODO: We could check for this in init_sccvn, and replace this
+ /* TODO: We could check for this in initialization, and replace this
with a gcc_assert. */
if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi)))
return set_ssa_val_to (PHI_RESULT (phi), PHI_RESULT (phi));
+ /* We track whether a PHI was CSEd to to avoid excessive iterations
+ that would be necessary only because the PHI changed arguments
+ but not value. */
+ if (!inserted)
+ gimple_set_plf (phi, GF_PLF_1, false);
+
/* See if all non-TOP arguments have the same value. TOP is
equivalent to everything, so we can ignore it. */
FOR_EACH_EDGE (e, ei, gimple_bb (phi)->preds)
@@ -3960,26 +4155,62 @@ visit_phi (gimple *phi)
++n_executable;
if (TREE_CODE (def) == SSA_NAME)
- def = SSA_VAL (def);
+ {
+ if (!backedges_varying_p || !(e->flags & EDGE_DFS_BACK))
+ def = SSA_VAL (def);
+ if (e->flags & EDGE_DFS_BACK)
+ backedge_val = def;
+ }
+ if (!(e->flags & EDGE_DFS_BACK))
+ seen_non_backedge = true;
if (def == VN_TOP)
;
/* Ignore undefined defs for sameval but record one. */
else if (TREE_CODE (def) == SSA_NAME
+ && ! virtual_operand_p (def)
&& ssa_undefined_value_p (def, false))
seen_undef = def;
else if (sameval == VN_TOP)
sameval = def;
else if (!expressions_equal_p (def, sameval))
{
- allsame = false;
+ /* We know we're arriving only with invariant addresses here,
+ try harder comparing them. We can do some caching here
+ which we cannot do in expressions_equal_p. */
+ if (TREE_CODE (def) == ADDR_EXPR
+ && TREE_CODE (sameval) == ADDR_EXPR
+ && sameval_base != (void *)-1)
+ {
+ if (!sameval_base)
+ sameval_base = get_addr_base_and_unit_offset
+ (TREE_OPERAND (sameval, 0), &soff);
+ if (!sameval_base)
+ sameval_base = (tree)(void *)-1;
+ else if ((get_addr_base_and_unit_offset
+ (TREE_OPERAND (def, 0), &doff) == sameval_base)
+ && known_eq (soff, doff))
+ continue;
+ }
+ sameval = NULL_TREE;
break;
}
}
-
+ /* If we value-number a virtual operand never value-number to the
+ value from the backedge as that confuses the alias-walking code.
+ See gcc.dg/torture/pr87176.c. If the value is the same on a
+ non-backedge everything is OK though. */
+ if (backedge_val
+ && !seen_non_backedge
+ && TREE_CODE (backedge_val) == SSA_NAME
+ && sameval == backedge_val
+ && SSA_NAME_IS_VIRTUAL_OPERAND (backedge_val))
+ /* Note this just drops to VARYING without inserting the PHI into
+ the hashes. */
+ result = PHI_RESULT (phi);
/* If none of the edges was executable keep the value-number at VN_TOP,
if only a single edge is exectuable use its value. */
- if (n_executable <= 1)
+ else if (n_executable <= 1)
result = seen_undef ? seen_undef : sameval;
/* If we saw only undefined values and VN_TOP use one of the
undefined values. */
@@ -3987,12 +4218,26 @@ visit_phi (gimple *phi)
result = seen_undef ? seen_undef : sameval;
/* First see if it is equivalent to a phi node in this block. We prefer
this as it allows IV elimination - see PRs 66502 and 67167. */
- else if ((result = vn_phi_lookup (phi)))
- ;
+ else if ((result = vn_phi_lookup (phi, backedges_varying_p)))
+ {
+ if (!inserted
+ && TREE_CODE (result) == SSA_NAME
+ && gimple_code (SSA_NAME_DEF_STMT (result)) == GIMPLE_PHI)
+ {
+ gimple_set_plf (SSA_NAME_DEF_STMT (result), GF_PLF_1, true);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Marking CSEd to PHI node ");
+ print_gimple_expr (dump_file, SSA_NAME_DEF_STMT (result),
+ 0, TDF_SLIM);
+ fprintf (dump_file, "\n");
+ }
+ }
+ }
/* If all values are the same use that, unless we've seen undefined
values as well and the value isn't constant.
CCP/copyprop have the same restriction to not remove uninit warnings. */
- else if (allsame
+ else if (sameval
&& (! seen_undef || is_gimple_min_invariant (sameval)))
result = sameval;
else
@@ -4001,7 +4246,9 @@ visit_phi (gimple *phi)
/* Only insert PHIs that are varying, for constant value numbers
we mess up equivalences otherwise as we are only comparing
the immediate controlling predicates. */
- vn_phi_insert (phi, result);
+ vn_phi_insert (phi, result, backedges_varying_p);
+ if (inserted)
+ *inserted = true;
}
return set_ssa_val_to (PHI_RESULT (phi), result);
@@ -4032,30 +4279,22 @@ try_to_simplify (gassign *stmt)
return NULL_TREE;
}
-/* Visit and value number USE, return true if the value number
- changed. */
+/* Visit and value number STMT, return true if the value number
+ changed. */
static bool
-visit_use (tree use)
+visit_stmt (gimple *stmt, bool backedges_varying_p = false)
{
bool changed = false;
- gimple *stmt = SSA_NAME_DEF_STMT (use);
-
- mark_use_processed (use);
-
- gcc_assert (!SSA_NAME_IN_FREE_LIST (use)
- && !SSA_NAME_IS_DEFAULT_DEF (use));
if (dump_file && (dump_flags & TDF_DETAILS))
{
- fprintf (dump_file, "Value numbering ");
- print_generic_expr (dump_file, use);
- fprintf (dump_file, " stmt = ");
+ fprintf (dump_file, "Value numbering stmt = ");
print_gimple_stmt (dump_file, stmt, 0);
}
if (gimple_code (stmt) == GIMPLE_PHI)
- changed = visit_phi (stmt);
+ changed = visit_phi (stmt, NULL, backedges_varying_p);
else if (gimple_has_volatile_ops (stmt))
changed = defs_to_varying (stmt);
else if (gassign *ass = dyn_cast <gassign *> (stmt))
@@ -4242,313 +4481,15 @@ visit_use (tree use)
return changed;
}
-/* Compare two operands by reverse postorder index */
-
-static int
-compare_ops (const void *pa, const void *pb)
-{
- const tree opa = *((const tree *)pa);
- const tree opb = *((const tree *)pb);
- gimple *opstmta = SSA_NAME_DEF_STMT (opa);
- gimple *opstmtb = SSA_NAME_DEF_STMT (opb);
- basic_block bba;
- basic_block bbb;
-
- if (gimple_nop_p (opstmta) && gimple_nop_p (opstmtb))
- return SSA_NAME_VERSION (opa) - SSA_NAME_VERSION (opb);
- else if (gimple_nop_p (opstmta))
- return -1;
- else if (gimple_nop_p (opstmtb))
- return 1;
-
- bba = gimple_bb (opstmta);
- bbb = gimple_bb (opstmtb);
-
- if (!bba && !bbb)
- return SSA_NAME_VERSION (opa) - SSA_NAME_VERSION (opb);
- else if (!bba)
- return -1;
- else if (!bbb)
- return 1;
-
- if (bba == bbb)
- {
- if (gimple_code (opstmta) == GIMPLE_PHI
- && gimple_code (opstmtb) == GIMPLE_PHI)
- return SSA_NAME_VERSION (opa) - SSA_NAME_VERSION (opb);
- else if (gimple_code (opstmta) == GIMPLE_PHI)
- return -1;
- else if (gimple_code (opstmtb) == GIMPLE_PHI)
- return 1;
- else if (gimple_uid (opstmta) != gimple_uid (opstmtb))
- return gimple_uid (opstmta) - gimple_uid (opstmtb);
- else
- return SSA_NAME_VERSION (opa) - SSA_NAME_VERSION (opb);
- }
- return rpo_numbers[bba->index] - rpo_numbers[bbb->index];
-}
-
-/* Sort an array containing members of a strongly connected component
- SCC so that the members are ordered by RPO number.
- This means that when the sort is complete, iterating through the
- array will give you the members in RPO order. */
-
-static void
-sort_scc (vec<tree> scc)
-{
- scc.qsort (compare_ops);
-}
-
-/* Process a strongly connected component in the SSA graph. */
-
-static void
-process_scc (vec<tree> scc)
-{
- tree var;
- unsigned int i;
- unsigned int iterations = 0;
- bool changed = true;
-
- /* If the SCC has a single member, just visit it. */
- if (scc.length () == 1)
- {
- tree use = scc[0];
- if (VN_INFO (use)->use_processed)
- return;
- /* We need to make sure it doesn't form a cycle itself, which can
- happen for self-referential PHI nodes. In that case we would
- end up inserting an expression with VN_TOP operands into the
- valid table which makes us derive bogus equivalences later.
- The cheapest way to check this is to assume it for all PHI nodes. */
- if (gimple_code (SSA_NAME_DEF_STMT (use)) == GIMPLE_PHI)
- /* Fallthru to iteration. */ ;
- else
- {
- visit_use (use);
- return;
- }
- }
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- print_scc (dump_file, scc);
-
- /* Iterate over the SCC with the optimistic table until it stops
- changing. */
- while (changed)
- {
- changed = false;
- iterations++;
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Starting iteration %d\n", iterations);
- /* As we are value-numbering optimistically we have to
- clear the expression tables and the simplified expressions
- in each iteration until we converge. */
- void *ob_top = obstack_alloc (&vn_tables_obstack, 0);
- vn_reference_t ref_top = last_inserted_ref;
- vn_phi_t phi_top = last_inserted_phi;
- vn_nary_op_t nary_top = last_inserted_nary;
- FOR_EACH_VEC_ELT (scc, i, var)
- gcc_assert (!VN_INFO (var)->needs_insertion
- && VN_INFO (var)->expr == NULL);
- FOR_EACH_VEC_ELT (scc, i, var)
- changed |= visit_use (var);
- if (changed)
- {
- for (; last_inserted_nary != nary_top;
- last_inserted_nary = last_inserted_nary->next)
- {
- vn_nary_op_t *slot;
- slot = valid_info->nary->find_slot_with_hash (last_inserted_nary,
- last_inserted_nary->hashcode,
- NO_INSERT);
- gcc_assert (slot);
- valid_info->nary->clear_slot (slot);
- }
- for (; last_inserted_phi != phi_top;
- last_inserted_phi = last_inserted_phi->next)
- {
- vn_phi_t *slot;
- slot = valid_info->phis->find_slot_with_hash (last_inserted_phi,
- last_inserted_phi->hashcode,
- NO_INSERT);
- gcc_assert (slot);
- valid_info->phis->clear_slot (slot);
- }
- for (; last_inserted_ref != ref_top;
- last_inserted_ref = last_inserted_ref->next)
- {
- vn_reference_t *slot;
- slot = valid_info->references->find_slot_with_hash (last_inserted_ref,
- last_inserted_ref->hashcode,
- NO_INSERT);
- gcc_assert (slot);
- (*slot)->operands.release ();
- valid_info->references->clear_slot (slot);
- }
- obstack_free (&vn_tables_obstack, ob_top);
- }
- }
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Processing SCC needed %d iterations\n", iterations);
- statistics_histogram_event (cfun, "SCC iterations", iterations);
-}
-
-
-/* Pop the components of the found SCC for NAME off the SCC stack
- and process them. Returns true if all went well, false if
- we run into resource limits. */
-
-static void
-extract_and_process_scc_for_name (tree name)
-{
- auto_vec<tree> scc;
- tree x;
-
- /* Found an SCC, pop the components off the SCC stack and
- process them. */
- do
- {
- x = sccstack.pop ();
-
- VN_INFO (x)->on_sccstack = false;
- scc.safe_push (x);
- } while (x != name);
-
- /* Drop all defs in the SCC to varying in case a SCC turns out to be
- incredibly large.
- ??? Just switch to a non-optimistic mode that avoids any iteration. */
- if (scc.length () > (unsigned)PARAM_VALUE (PARAM_SCCVN_MAX_SCC_SIZE))
- {
- if (dump_file)
- {
- print_scc (dump_file, scc);
- fprintf (dump_file, "WARNING: Giving up value-numbering SCC due to "
- "size %u exceeding %u\n", scc.length (),
- (unsigned)PARAM_VALUE (PARAM_SCCVN_MAX_SCC_SIZE));
- }
- tree var;
- unsigned i;
- FOR_EACH_VEC_ELT (scc, i, var)
- {
- gimple *def = SSA_NAME_DEF_STMT (var);
- mark_use_processed (var);
- if (SSA_NAME_IS_DEFAULT_DEF (var)
- || gimple_code (def) == GIMPLE_PHI)
- set_ssa_val_to (var, var);
- else
- defs_to_varying (def);
- }
- return;
- }
-
- if (scc.length () > 1)
- sort_scc (scc);
-
- process_scc (scc);
-}
-
-/* Depth first search on NAME to discover and process SCC's in the SSA
- graph.
- Execution of this algorithm relies on the fact that the SCC's are
- popped off the stack in topological order.
- Returns true if successful, false if we stopped processing SCC's due
- to resource constraints. */
-
-static void
-DFS (tree name)
-{
- auto_vec<ssa_op_iter> itervec;
- auto_vec<tree> namevec;
- use_operand_p usep = NULL;
- gimple *defstmt;
- tree use;
- ssa_op_iter iter;
-
-start_over:
- /* SCC info */
- VN_INFO (name)->dfsnum = next_dfs_num++;
- VN_INFO (name)->visited = true;
- VN_INFO (name)->low = VN_INFO (name)->dfsnum;
-
- sccstack.safe_push (name);
- VN_INFO (name)->on_sccstack = true;
- defstmt = SSA_NAME_DEF_STMT (name);
-
- /* Recursively DFS on our operands, looking for SCC's. */
- if (!gimple_nop_p (defstmt))
- {
- /* Push a new iterator. */
- if (gphi *phi = dyn_cast <gphi *> (defstmt))
- usep = op_iter_init_phiuse (&iter, phi, SSA_OP_ALL_USES);
- else
- usep = op_iter_init_use (&iter, defstmt, SSA_OP_ALL_USES);
- }
- else
- clear_and_done_ssa_iter (&iter);
-
- while (1)
- {
- /* If we are done processing uses of a name, go up the stack
- of iterators and process SCCs as we found them. */
- if (op_iter_done (&iter))
- {
- /* See if we found an SCC. */
- if (VN_INFO (name)->low == VN_INFO (name)->dfsnum)
- extract_and_process_scc_for_name (name);
-
- /* Check if we are done. */
- if (namevec.is_empty ())
- return;
-
- /* Restore the last use walker and continue walking there. */
- use = name;
- name = namevec.pop ();
- memcpy (&iter, &itervec.last (),
- sizeof (ssa_op_iter));
- itervec.pop ();
- goto continue_walking;
- }
-
- use = USE_FROM_PTR (usep);
-
- /* Since we handle phi nodes, we will sometimes get
- invariants in the use expression. */
- if (TREE_CODE (use) == SSA_NAME)
- {
- if (! (VN_INFO (use)->visited))
- {
- /* Recurse by pushing the current use walking state on
- the stack and starting over. */
- itervec.safe_push (iter);
- namevec.safe_push (name);
- name = use;
- goto start_over;
-
-continue_walking:
- VN_INFO (name)->low = MIN (VN_INFO (name)->low,
- VN_INFO (use)->low);
- }
- if (VN_INFO (use)->dfsnum < VN_INFO (name)->dfsnum
- && VN_INFO (use)->on_sccstack)
- {
- VN_INFO (name)->low = MIN (VN_INFO (use)->dfsnum,
- VN_INFO (name)->low);
- }
- }
-
- usep = op_iter_next_use (&iter);
- }
-}
/* Allocate a value number table. */
static void
-allocate_vn_table (vn_tables_t table)
+allocate_vn_table (vn_tables_t table, unsigned size)
{
- table->phis = new vn_phi_table_type (23);
- table->nary = new vn_nary_op_table_type (23);
- table->references = new vn_reference_table_type (23);
+ table->phis = new vn_phi_table_type (size);
+ table->nary = new vn_nary_op_table_type (size);
+ table->references = new vn_reference_table_type (size);
}
/* Free a value number table. */
@@ -4569,174 +4510,6 @@ free_vn_table (vn_tables_t table)
table->references = NULL;
}
-static void
-init_scc_vn (void)
-{
- int j;
- int *rpo_numbers_temp;
-
- calculate_dominance_info (CDI_DOMINATORS);
- mark_dfs_back_edges ();
-
- sccstack.create (0);
- constant_to_value_id = new hash_table<vn_constant_hasher> (23);
-
- constant_value_ids = BITMAP_ALLOC (NULL);
-
- next_dfs_num = 1;
- next_value_id = 1;
-
- vn_ssa_aux_table.create (num_ssa_names + 1);
- /* VEC_alloc doesn't actually grow it to the right size, it just
- preallocates the space to do so. */
- vn_ssa_aux_table.safe_grow_cleared (num_ssa_names + 1);
- gcc_obstack_init (&vn_ssa_aux_obstack);
-
- shared_lookup_references.create (0);
- rpo_numbers = XNEWVEC (int, last_basic_block_for_fn (cfun));
- rpo_numbers_temp =
- XNEWVEC (int, n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS);
- pre_and_rev_post_order_compute (NULL, rpo_numbers_temp, false);
-
- /* RPO numbers is an array of rpo ordering, rpo[i] = bb means that
- the i'th block in RPO order is bb. We want to map bb's to RPO
- numbers, so we need to rearrange this array. */
- for (j = 0; j < n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS; j++)
- rpo_numbers[rpo_numbers_temp[j]] = j;
-
- XDELETE (rpo_numbers_temp);
-
- VN_TOP = build_decl (UNKNOWN_LOCATION, VAR_DECL,
- get_identifier ("VN_TOP"), error_mark_node);
-
- renumber_gimple_stmt_uids ();
-
- /* Create the valid and optimistic value numbering tables. */
- gcc_obstack_init (&vn_tables_obstack);
- gcc_obstack_init (&vn_tables_insert_obstack);
- valid_info = XCNEW (struct vn_tables_s);
- allocate_vn_table (valid_info);
- last_inserted_ref = NULL;
- last_inserted_phi = NULL;
- last_inserted_nary = NULL;
-
- /* Create the VN_INFO structures, and initialize value numbers to
- TOP or VARYING for parameters. */
- size_t i;
- tree name;
-
- FOR_EACH_SSA_NAME (i, name, cfun)
- {
- VN_INFO_GET (name)->valnum = VN_TOP;
- VN_INFO (name)->needs_insertion = false;
- VN_INFO (name)->expr = NULL;
- VN_INFO (name)->value_id = 0;
-
- if (!SSA_NAME_IS_DEFAULT_DEF (name))
- continue;
-
- switch (TREE_CODE (SSA_NAME_VAR (name)))
- {
- case VAR_DECL:
- /* All undefined vars are VARYING. */
- VN_INFO (name)->valnum = name;
- VN_INFO (name)->visited = true;
- break;
-
- case PARM_DECL:
- /* Parameters are VARYING but we can record a condition
- if we know it is a non-NULL pointer. */
- VN_INFO (name)->visited = true;
- VN_INFO (name)->valnum = name;
- if (POINTER_TYPE_P (TREE_TYPE (name))
- && nonnull_arg_p (SSA_NAME_VAR (name)))
- {
- tree ops[2];
- ops[0] = name;
- ops[1] = build_int_cst (TREE_TYPE (name), 0);
- vn_nary_op_insert_pieces (2, NE_EXPR, boolean_type_node, ops,
- boolean_true_node, 0);
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Recording ");
- print_generic_expr (dump_file, name, TDF_SLIM);
- fprintf (dump_file, " != 0\n");
- }
- }
- break;
-
- case RESULT_DECL:
- /* If the result is passed by invisible reference the default
- def is initialized, otherwise it's uninitialized. Still
- undefined is varying. */
- VN_INFO (name)->visited = true;
- VN_INFO (name)->valnum = name;
- break;
-
- default:
- gcc_unreachable ();
- }
- }
-}
-
-/* Restore SSA info that has been reset on value leaders. */
-
-void
-scc_vn_restore_ssa_info (void)
-{
- unsigned i;
- tree name;
-
- FOR_EACH_SSA_NAME (i, name, cfun)
- {
- if (has_VN_INFO (name))
- {
- if (VN_INFO (name)->needs_insertion)
- ;
- else if (POINTER_TYPE_P (TREE_TYPE (name))
- && VN_INFO (name)->info.ptr_info)
- SSA_NAME_PTR_INFO (name) = VN_INFO (name)->info.ptr_info;
- else if (INTEGRAL_TYPE_P (TREE_TYPE (name))
- && VN_INFO (name)->info.range_info)
- {
- SSA_NAME_RANGE_INFO (name) = VN_INFO (name)->info.range_info;
- SSA_NAME_ANTI_RANGE_P (name)
- = VN_INFO (name)->range_info_anti_range_p;
- }
- }
- }
-}
-
-void
-free_scc_vn (void)
-{
- size_t i;
- tree name;
-
- delete constant_to_value_id;
- constant_to_value_id = NULL;
- BITMAP_FREE (constant_value_ids);
- shared_lookup_references.release ();
- XDELETEVEC (rpo_numbers);
-
- FOR_EACH_SSA_NAME (i, name, cfun)
- {
- if (has_VN_INFO (name)
- && VN_INFO (name)->needs_insertion)
- release_ssa_name (name);
- }
- obstack_free (&vn_ssa_aux_obstack, NULL);
- vn_ssa_aux_table.release ();
-
- sccstack.release ();
- free_vn_table (valid_info);
- XDELETE (valid_info);
- obstack_free (&vn_tables_obstack, NULL);
- obstack_free (&vn_tables_insert_obstack, NULL);
-
- BITMAP_FREE (const_parms);
-}
-
/* Set *ID according to RESULT. */
static void
@@ -4766,7 +4539,8 @@ set_hashtable_value_ids (void)
table. */
FOR_EACH_HASH_TABLE_ELEMENT (*valid_info->nary, vno, vn_nary_op_t, hin)
- set_value_id_for_result (vno->result, &vno->value_id);
+ if (! vno->predicated_values)
+ set_value_id_for_result (vno->u.result, &vno->value_id);
FOR_EACH_HASH_TABLE_ELEMENT (*valid_info->phis, vp, vn_phi_t, hip)
set_value_id_for_result (vp->result, &vp->value_id);
@@ -4776,317 +4550,6 @@ set_hashtable_value_ids (void)
set_value_id_for_result (vr->result, &vr->value_id);
}
-class sccvn_dom_walker : public dom_walker
-{
-public:
- sccvn_dom_walker ()
- : dom_walker (CDI_DOMINATORS, REACHABLE_BLOCKS), cond_stack (0) {}
-
- virtual edge before_dom_children (basic_block);
- virtual void after_dom_children (basic_block);
-
- void record_cond (basic_block,
- enum tree_code code, tree lhs, tree rhs, bool value);
- void record_conds (basic_block,
- enum tree_code code, tree lhs, tree rhs, bool value);
-
- auto_vec<std::pair <basic_block, std::pair <vn_nary_op_t, vn_nary_op_t> > >
- cond_stack;
-};
-
-/* Record a temporary condition for the BB and its dominated blocks. */
-
-void
-sccvn_dom_walker::record_cond (basic_block bb,
- enum tree_code code, tree lhs, tree rhs,
- bool value)
-{
- tree ops[2] = { lhs, rhs };
- vn_nary_op_t old = NULL;
- if (vn_nary_op_lookup_pieces (2, code, boolean_type_node, ops, &old))
- valid_info->nary->remove_elt_with_hash (old, old->hashcode);
- vn_nary_op_t cond
- = vn_nary_op_insert_pieces (2, code, boolean_type_node, ops,
- value
- ? boolean_true_node
- : boolean_false_node, 0);
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Recording temporarily ");
- print_generic_expr (dump_file, ops[0], TDF_SLIM);
- fprintf (dump_file, " %s ", get_tree_code_name (code));
- print_generic_expr (dump_file, ops[1], TDF_SLIM);
- fprintf (dump_file, " == %s%s\n",
- value ? "true" : "false",
- old ? " (old entry saved)" : "");
- }
- cond_stack.safe_push (std::make_pair (bb, std::make_pair (cond, old)));
-}
-
-/* Record temporary conditions for the BB and its dominated blocks
- according to LHS CODE RHS == VALUE and its dominated conditions. */
-
-void
-sccvn_dom_walker::record_conds (basic_block bb,
- enum tree_code code, tree lhs, tree rhs,
- bool value)
-{
- /* Record the original condition. */
- record_cond (bb, code, lhs, rhs, value);
-
- if (!value)
- return;
-
- /* Record dominated conditions if the condition is true. Note that
- the inversion is already recorded. */
- switch (code)
- {
- case LT_EXPR:
- case GT_EXPR:
- record_cond (bb, code == LT_EXPR ? LE_EXPR : GE_EXPR, lhs, rhs, true);
- record_cond (bb, NE_EXPR, lhs, rhs, true);
- record_cond (bb, EQ_EXPR, lhs, rhs, false);
- break;
-
- case EQ_EXPR:
- record_cond (bb, LE_EXPR, lhs, rhs, true);
- record_cond (bb, GE_EXPR, lhs, rhs, true);
- record_cond (bb, LT_EXPR, lhs, rhs, false);
- record_cond (bb, GT_EXPR, lhs, rhs, false);
- break;
-
- default:
- break;
- }
-}
-
-/* Restore expressions and values derived from conditionals. */
-
-void
-sccvn_dom_walker::after_dom_children (basic_block bb)
-{
- while (!cond_stack.is_empty ()
- && cond_stack.last ().first == bb)
- {
- vn_nary_op_t cond = cond_stack.last ().second.first;
- vn_nary_op_t old = cond_stack.last ().second.second;
- valid_info->nary->remove_elt_with_hash (cond, cond->hashcode);
- if (old)
- vn_nary_op_insert_into (old, valid_info->nary, false);
- cond_stack.pop ();
- }
-}
-
-/* Value number all statements in BB. */
-
-edge
-sccvn_dom_walker::before_dom_children (basic_block bb)
-{
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Visiting BB %d\n", bb->index);
-
- /* If we have a single predecessor record the equivalence from a
- possible condition on the predecessor edge. */
- edge pred_e = single_pred_edge_ignoring_loop_edges (bb, false);
- if (pred_e)
- {
- /* Check if there are multiple executable successor edges in
- the source block. Otherwise there is no additional info
- to be recorded. */
- edge_iterator ei;
- edge e2;
- FOR_EACH_EDGE (e2, ei, pred_e->src->succs)
- if (e2 != pred_e
- && e2->flags & EDGE_EXECUTABLE)
- break;
- if (e2 && (e2->flags & EDGE_EXECUTABLE))
- {
- gimple *stmt = last_stmt (pred_e->src);
- if (stmt
- && gimple_code (stmt) == GIMPLE_COND)
- {
- enum tree_code code = gimple_cond_code (stmt);
- tree lhs = gimple_cond_lhs (stmt);
- tree rhs = gimple_cond_rhs (stmt);
- record_conds (bb, code, lhs, rhs,
- (pred_e->flags & EDGE_TRUE_VALUE) != 0);
- code = invert_tree_comparison (code, HONOR_NANS (lhs));
- if (code != ERROR_MARK)
- record_conds (bb, code, lhs, rhs,
- (pred_e->flags & EDGE_TRUE_VALUE) == 0);
- }
- }
- }
-
- /* Value-number all defs in the basic-block. */
- for (gphi_iterator gsi = gsi_start_phis (bb);
- !gsi_end_p (gsi); gsi_next (&gsi))
- {
- gphi *phi = gsi.phi ();
- tree res = PHI_RESULT (phi);
- if (!VN_INFO (res)->visited)
- DFS (res);
- }
- for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
- !gsi_end_p (gsi); gsi_next (&gsi))
- {
- ssa_op_iter i;
- tree op;
- FOR_EACH_SSA_TREE_OPERAND (op, gsi_stmt (gsi), i, SSA_OP_ALL_DEFS)
- if (!VN_INFO (op)->visited)
- DFS (op);
- }
-
- /* Finally look at the last stmt. */
- gimple *stmt = last_stmt (bb);
- if (!stmt)
- return NULL;
-
- enum gimple_code code = gimple_code (stmt);
- if (code != GIMPLE_COND
- && code != GIMPLE_SWITCH
- && code != GIMPLE_GOTO)
- return NULL;
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Visiting control stmt ending BB %d: ", bb->index);
- print_gimple_stmt (dump_file, stmt, 0);
- }
-
- /* ??? We can even handle stmts with outgoing EH or ABNORMAL edges
- if value-numbering can prove they are not reachable. Handling
- computed gotos is also possible. */
- tree val;
- switch (code)
- {
- case GIMPLE_COND:
- {
- tree lhs = vn_valueize (gimple_cond_lhs (stmt));
- tree rhs = vn_valueize (gimple_cond_rhs (stmt));
- val = gimple_simplify (gimple_cond_code (stmt),
- boolean_type_node, lhs, rhs,
- NULL, vn_valueize);
- /* If that didn't simplify to a constant see if we have recorded
- temporary expressions from taken edges. */
- if (!val || TREE_CODE (val) != INTEGER_CST)
- {
- tree ops[2];
- ops[0] = lhs;
- ops[1] = rhs;
- val = vn_nary_op_lookup_pieces (2, gimple_cond_code (stmt),
- boolean_type_node, ops, NULL);
- }
- break;
- }
- case GIMPLE_SWITCH:
- val = gimple_switch_index (as_a <gswitch *> (stmt));
- break;
- case GIMPLE_GOTO:
- val = gimple_goto_dest (stmt);
- break;
- default:
- gcc_unreachable ();
- }
- if (!val)
- return NULL;
-
- edge taken = find_taken_edge (bb, vn_valueize (val));
- if (!taken)
- return NULL;
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Marking all edges out of BB %d but (%d -> %d) as "
- "not executable\n", bb->index, bb->index, taken->dest->index);
-
- return taken;
-}
-
-/* Do SCCVN. Returns true if it finished, false if we bailed out
- due to resource constraints. DEFAULT_VN_WALK_KIND_ specifies
- how we use the alias oracle walking during the VN process. */
-
-void
-run_scc_vn (vn_lookup_kind default_vn_walk_kind_)
-{
- size_t i;
-
- default_vn_walk_kind = default_vn_walk_kind_;
-
- init_scc_vn ();
-
- /* Collect pointers we know point to readonly memory. */
- const_parms = BITMAP_ALLOC (NULL);
- tree fnspec = lookup_attribute ("fn spec",
- TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl)));
- if (fnspec)
- {
- fnspec = TREE_VALUE (TREE_VALUE (fnspec));
- i = 1;
- for (tree arg = DECL_ARGUMENTS (cfun->decl);
- arg; arg = DECL_CHAIN (arg), ++i)
- {
- if (i >= (unsigned) TREE_STRING_LENGTH (fnspec))
- break;
- if (TREE_STRING_POINTER (fnspec)[i] == 'R'
- || TREE_STRING_POINTER (fnspec)[i] == 'r')
- {
- tree name = ssa_default_def (cfun, arg);
- if (name)
- bitmap_set_bit (const_parms, SSA_NAME_VERSION (name));
- }
- }
- }
-
- /* Walk all blocks in dominator order, value-numbering stmts
- SSA defs and decide whether outgoing edges are not executable. */
- sccvn_dom_walker walker;
- walker.walk (ENTRY_BLOCK_PTR_FOR_FN (cfun));
-
- /* Initialize the value ids and prune out remaining VN_TOPs
- from dead code. */
- tree name;
- FOR_EACH_SSA_NAME (i, name, cfun)
- {
- vn_ssa_aux_t info = VN_INFO (name);
- if (!info->visited
- || info->valnum == VN_TOP)
- info->valnum = name;
- if (info->valnum == name)
- info->value_id = get_next_value_id ();
- else if (is_gimple_min_invariant (info->valnum))
- info->value_id = get_or_alloc_constant_value_id (info->valnum);
- }
-
- /* Propagate. */
- FOR_EACH_SSA_NAME (i, name, cfun)
- {
- vn_ssa_aux_t info = VN_INFO (name);
- if (TREE_CODE (info->valnum) == SSA_NAME
- && info->valnum != name
- && info->value_id != VN_INFO (info->valnum)->value_id)
- info->value_id = VN_INFO (info->valnum)->value_id;
- }
-
- set_hashtable_value_ids ();
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Value numbers:\n");
- FOR_EACH_SSA_NAME (i, name, cfun)
- {
- if (VN_INFO (name)->visited
- && SSA_VAL (name) != name)
- {
- print_generic_expr (dump_file, name);
- fprintf (dump_file, " = ");
- print_generic_expr (dump_file, SSA_VAL (name));
- fprintf (dump_file, "\n");
- }
- }
- }
-}
-
/* Return the maximum value id we have ever seen. */
unsigned int
@@ -5187,9 +4650,13 @@ public:
virtual edge before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
- tree eliminate_avail (tree op);
- void eliminate_push_avail (tree op);
- tree eliminate_insert (gimple_stmt_iterator *gsi, tree val);
+ virtual tree eliminate_avail (basic_block, tree op);
+ virtual void eliminate_push_avail (basic_block, tree op);
+ tree eliminate_insert (basic_block, gimple_stmt_iterator *gsi, tree val);
+
+ void eliminate_stmt (basic_block, gimple_stmt_iterator *);
+
+ unsigned eliminate_cleanup (bool region_p = false);
bool do_pre;
unsigned int el_todo;
@@ -5205,6 +4672,7 @@ public:
/* Blocks with statements that have had their AB properties changed. */
bitmap need_ab_cleanup;
+ /* Local state for the eliminate domwalk. */
auto_vec<gimple *> to_remove;
auto_vec<gimple *> to_fixup;
auto_vec<tree> avail;
@@ -5231,7 +4699,7 @@ eliminate_dom_walker::~eliminate_dom_walker ()
eliminate domwalk. */
tree
-eliminate_dom_walker::eliminate_avail (tree op)
+eliminate_dom_walker::eliminate_avail (basic_block, tree op)
{
tree valnum = VN_INFO (op)->valnum;
if (TREE_CODE (valnum) == SSA_NAME)
@@ -5249,7 +4717,7 @@ eliminate_dom_walker::eliminate_avail (tree op)
/* At the current point of the eliminate domwalk make OP available. */
void
-eliminate_dom_walker::eliminate_push_avail (tree op)
+eliminate_dom_walker::eliminate_push_avail (basic_block, tree op)
{
tree valnum = VN_INFO (op)->valnum;
if (TREE_CODE (valnum) == SSA_NAME)
@@ -5268,7 +4736,8 @@ eliminate_dom_walker::eliminate_push_avail (tree op)
the leader for the expression if insertion was successful. */
tree
-eliminate_dom_walker::eliminate_insert (gimple_stmt_iterator *gsi, tree val)
+eliminate_dom_walker::eliminate_insert (basic_block bb,
+ gimple_stmt_iterator *gsi, tree val)
{
/* We can insert a sequence with a single assignment only. */
gimple_seq stmts = VN_INFO (val)->expr;
@@ -5287,7 +4756,7 @@ eliminate_dom_walker::eliminate_insert (gimple_stmt_iterator *gsi, tree val)
if (gimple_assign_rhs_code (stmt) == VIEW_CONVERT_EXPR
|| gimple_assign_rhs_code (stmt) == BIT_FIELD_REF)
op = TREE_OPERAND (op, 0);
- tree leader = TREE_CODE (op) == SSA_NAME ? eliminate_avail (op) : op;
+ tree leader = TREE_CODE (op) == SSA_NAME ? eliminate_avail (bb, op) : op;
if (!leader)
return NULL_TREE;
@@ -5319,7 +4788,7 @@ eliminate_dom_walker::eliminate_insert (gimple_stmt_iterator *gsi, tree val)
if (dump_file && (dump_flags & TDF_DETAILS))
{
if (TREE_CODE (res) == SSA_NAME)
- res = eliminate_avail (res);
+ res = eliminate_avail (bb, res);
if (res)
{
fprintf (dump_file, "Failed to insert expression for value ");
@@ -5335,7 +4804,8 @@ eliminate_dom_walker::eliminate_insert (gimple_stmt_iterator *gsi, tree val)
else
{
gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
- VN_INFO_GET (res)->valnum = val;
+ VN_INFO (res)->valnum = val;
+ VN_INFO (res)->visited = true;
}
insertions++;
@@ -5348,7 +4818,480 @@ eliminate_dom_walker::eliminate_insert (gimple_stmt_iterator *gsi, tree val)
return res;
}
+void
+eliminate_dom_walker::eliminate_stmt (basic_block b, gimple_stmt_iterator *gsi)
+{
+ tree sprime = NULL_TREE;
+ gimple *stmt = gsi_stmt (*gsi);
+ tree lhs = gimple_get_lhs (stmt);
+ if (lhs && TREE_CODE (lhs) == SSA_NAME
+ && !gimple_has_volatile_ops (stmt)
+ /* See PR43491. Do not replace a global register variable when
+ it is a the RHS of an assignment. Do replace local register
+ variables since gcc does not guarantee a local variable will
+ be allocated in register.
+ ??? The fix isn't effective here. This should instead
+ be ensured by not value-numbering them the same but treating
+ them like volatiles? */
+ && !(gimple_assign_single_p (stmt)
+ && (TREE_CODE (gimple_assign_rhs1 (stmt)) == VAR_DECL
+ && DECL_HARD_REGISTER (gimple_assign_rhs1 (stmt))
+ && is_global_var (gimple_assign_rhs1 (stmt)))))
+ {
+ sprime = eliminate_avail (b, lhs);
+ if (!sprime)
+ {
+ /* If there is no existing usable leader but SCCVN thinks
+ it has an expression it wants to use as replacement,
+ insert that. */
+ tree val = VN_INFO (lhs)->valnum;
+ if (val != VN_TOP
+ && TREE_CODE (val) == SSA_NAME
+ && VN_INFO (val)->needs_insertion
+ && VN_INFO (val)->expr != NULL
+ && (sprime = eliminate_insert (b, gsi, val)) != NULL_TREE)
+ eliminate_push_avail (b, sprime);
+ }
+
+ /* If this now constitutes a copy duplicate points-to
+ and range info appropriately. This is especially
+ important for inserted code. See tree-ssa-copy.c
+ for similar code. */
+ if (sprime
+ && TREE_CODE (sprime) == SSA_NAME)
+ {
+ basic_block sprime_b = gimple_bb (SSA_NAME_DEF_STMT (sprime));
+ if (POINTER_TYPE_P (TREE_TYPE (lhs))
+ && SSA_NAME_PTR_INFO (lhs)
+ && ! SSA_NAME_PTR_INFO (sprime))
+ {
+ duplicate_ssa_name_ptr_info (sprime,
+ SSA_NAME_PTR_INFO (lhs));
+ if (b != sprime_b)
+ mark_ptr_info_alignment_unknown
+ (SSA_NAME_PTR_INFO (sprime));
+ }
+ else if (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+ && SSA_NAME_RANGE_INFO (lhs)
+ && ! SSA_NAME_RANGE_INFO (sprime)
+ && b == sprime_b)
+ duplicate_ssa_name_range_info (sprime,
+ SSA_NAME_RANGE_TYPE (lhs),
+ SSA_NAME_RANGE_INFO (lhs));
+ }
+
+ /* Inhibit the use of an inserted PHI on a loop header when
+ the address of the memory reference is a simple induction
+ variable. In other cases the vectorizer won't do anything
+ anyway (either it's loop invariant or a complicated
+ expression). */
+ if (sprime
+ && TREE_CODE (sprime) == SSA_NAME
+ && do_pre
+ && (flag_tree_loop_vectorize || flag_tree_parallelize_loops > 1)
+ && loop_outer (b->loop_father)
+ && has_zero_uses (sprime)
+ && bitmap_bit_p (inserted_exprs, SSA_NAME_VERSION (sprime))
+ && gimple_assign_load_p (stmt))
+ {
+ gimple *def_stmt = SSA_NAME_DEF_STMT (sprime);
+ basic_block def_bb = gimple_bb (def_stmt);
+ if (gimple_code (def_stmt) == GIMPLE_PHI
+ && def_bb->loop_father->header == def_bb)
+ {
+ loop_p loop = def_bb->loop_father;
+ ssa_op_iter iter;
+ tree op;
+ bool found = false;
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
+ {
+ affine_iv iv;
+ def_bb = gimple_bb (SSA_NAME_DEF_STMT (op));
+ if (def_bb
+ && flow_bb_inside_loop_p (loop, def_bb)
+ && simple_iv (loop, loop, op, &iv, true))
+ {
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Not replacing ");
+ print_gimple_expr (dump_file, stmt, 0);
+ fprintf (dump_file, " with ");
+ print_generic_expr (dump_file, sprime);
+ fprintf (dump_file, " which would add a loop"
+ " carried dependence to loop %d\n",
+ loop->num);
+ }
+ /* Don't keep sprime available. */
+ sprime = NULL_TREE;
+ }
+ }
+ }
+
+ if (sprime)
+ {
+ /* If we can propagate the value computed for LHS into
+ all uses don't bother doing anything with this stmt. */
+ if (may_propagate_copy (lhs, sprime))
+ {
+ /* Mark it for removal. */
+ to_remove.safe_push (stmt);
+
+ /* ??? Don't count copy/constant propagations. */
+ if (gimple_assign_single_p (stmt)
+ && (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
+ || gimple_assign_rhs1 (stmt) == sprime))
+ return;
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Replaced ");
+ print_gimple_expr (dump_file, stmt, 0);
+ fprintf (dump_file, " with ");
+ print_generic_expr (dump_file, sprime);
+ fprintf (dump_file, " in all uses of ");
+ print_gimple_stmt (dump_file, stmt, 0);
+ }
+
+ eliminations++;
+ return;
+ }
+
+ /* If this is an assignment from our leader (which
+ happens in the case the value-number is a constant)
+ then there is nothing to do. */
+ if (gimple_assign_single_p (stmt)
+ && sprime == gimple_assign_rhs1 (stmt))
+ return;
+
+ /* Else replace its RHS. */
+ bool can_make_abnormal_goto
+ = is_gimple_call (stmt)
+ && stmt_can_make_abnormal_goto (stmt);
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Replaced ");
+ print_gimple_expr (dump_file, stmt, 0);
+ fprintf (dump_file, " with ");
+ print_generic_expr (dump_file, sprime);
+ fprintf (dump_file, " in ");
+ print_gimple_stmt (dump_file, stmt, 0);
+ }
+
+ eliminations++;
+ gimple *orig_stmt = stmt;
+ if (!useless_type_conversion_p (TREE_TYPE (lhs),
+ TREE_TYPE (sprime)))
+ sprime = fold_convert (TREE_TYPE (lhs), sprime);
+ tree vdef = gimple_vdef (stmt);
+ tree vuse = gimple_vuse (stmt);
+ propagate_tree_value_into_stmt (gsi, sprime);
+ stmt = gsi_stmt (*gsi);
+ update_stmt (stmt);
+ /* In case the VDEF on the original stmt was released, value-number
+ it to the VUSE. This is to make vuse_ssa_val able to skip
+ released virtual operands. */
+ if (vdef != gimple_vdef (stmt))
+ {
+ gcc_assert (SSA_NAME_IN_FREE_LIST (vdef));
+ VN_INFO (vdef)->valnum = vuse;
+ }
+
+ /* If we removed EH side-effects from the statement, clean
+ its EH information. */
+ if (maybe_clean_or_replace_eh_stmt (orig_stmt, stmt))
+ {
+ bitmap_set_bit (need_eh_cleanup,
+ gimple_bb (stmt)->index);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " Removed EH side-effects.\n");
+ }
+
+ /* Likewise for AB side-effects. */
+ if (can_make_abnormal_goto
+ && !stmt_can_make_abnormal_goto (stmt))
+ {
+ bitmap_set_bit (need_ab_cleanup,
+ gimple_bb (stmt)->index);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " Removed AB side-effects.\n");
+ }
+
+ return;
+ }
+ }
+
+ /* If the statement is a scalar store, see if the expression
+ has the same value number as its rhs. If so, the store is
+ dead. */
+ if (gimple_assign_single_p (stmt)
+ && !gimple_has_volatile_ops (stmt)
+ && !is_gimple_reg (gimple_assign_lhs (stmt))
+ && (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
+ || is_gimple_min_invariant (gimple_assign_rhs1 (stmt))))
+ {
+ tree val;
+ tree rhs = gimple_assign_rhs1 (stmt);
+ vn_reference_t vnresult;
+ val = vn_reference_lookup (lhs, gimple_vuse (stmt), VN_WALKREWRITE,
+ &vnresult, false);
+ if (TREE_CODE (rhs) == SSA_NAME)
+ rhs = VN_INFO (rhs)->valnum;
+ if (val
+ && operand_equal_p (val, rhs, 0))
+ {
+ /* We can only remove the later store if the former aliases
+ at least all accesses the later one does or if the store
+ was to readonly memory storing the same value. */
+ alias_set_type set = get_alias_set (lhs);
+ if (! vnresult
+ || vnresult->set == set
+ || alias_set_subset_of (set, vnresult->set))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Deleted redundant store ");
+ print_gimple_stmt (dump_file, stmt, 0);
+ }
+
+ /* Queue stmt for removal. */
+ to_remove.safe_push (stmt);
+ return;
+ }
+ }
+ }
+
+ /* If this is a control statement value numbering left edges
+ unexecuted on force the condition in a way consistent with
+ that. */
+ if (gcond *cond = dyn_cast <gcond *> (stmt))
+ {
+ if ((EDGE_SUCC (b, 0)->flags & EDGE_EXECUTABLE)
+ ^ (EDGE_SUCC (b, 1)->flags & EDGE_EXECUTABLE))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Removing unexecutable edge from ");
+ print_gimple_stmt (dump_file, stmt, 0);
+ }
+ if (((EDGE_SUCC (b, 0)->flags & EDGE_TRUE_VALUE) != 0)
+ == ((EDGE_SUCC (b, 0)->flags & EDGE_EXECUTABLE) != 0))
+ gimple_cond_make_true (cond);
+ else
+ gimple_cond_make_false (cond);
+ update_stmt (cond);
+ el_todo |= TODO_cleanup_cfg;
+ return;
+ }
+ }
+
+ bool can_make_abnormal_goto = stmt_can_make_abnormal_goto (stmt);
+ bool was_noreturn = (is_gimple_call (stmt)
+ && gimple_call_noreturn_p (stmt));
+ tree vdef = gimple_vdef (stmt);
+ tree vuse = gimple_vuse (stmt);
+
+ /* If we didn't replace the whole stmt (or propagate the result
+ into all uses), replace all uses on this stmt with their
+ leaders. */
+ bool modified = false;
+ use_operand_p use_p;
+ ssa_op_iter iter;
+ FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
+ {
+ tree use = USE_FROM_PTR (use_p);
+ /* ??? The call code above leaves stmt operands un-updated. */
+ if (TREE_CODE (use) != SSA_NAME)
+ continue;
+ tree sprime;
+ if (SSA_NAME_IS_DEFAULT_DEF (use))
+ /* ??? For default defs BB shouldn't matter, but we have to
+ solve the inconsistency between rpo eliminate and
+ dom eliminate avail valueization first. */
+ sprime = eliminate_avail (b, use);
+ else
+ /* Look for sth available at the definition block of the argument.
+ This avoids inconsistencies between availability there which
+ decides if the stmt can be removed and availability at the
+ use site. The SSA property ensures that things available
+ at the definition are also available at uses. */
+ sprime = eliminate_avail (gimple_bb (SSA_NAME_DEF_STMT (use)), use);
+ if (sprime && sprime != use
+ && may_propagate_copy (use, sprime)
+ /* We substitute into debug stmts to avoid excessive
+ debug temporaries created by removed stmts, but we need
+ to avoid doing so for inserted sprimes as we never want
+ to create debug temporaries for them. */
+ && (!inserted_exprs
+ || TREE_CODE (sprime) != SSA_NAME
+ || !is_gimple_debug (stmt)
+ || !bitmap_bit_p (inserted_exprs, SSA_NAME_VERSION (sprime))))
+ {
+ propagate_value (use_p, sprime);
+ modified = true;
+ }
+ }
+
+ /* Fold the stmt if modified, this canonicalizes MEM_REFs we propagated
+ into which is a requirement for the IPA devirt machinery. */
+ gimple *old_stmt = stmt;
+ if (modified)
+ {
+ /* If a formerly non-invariant ADDR_EXPR is turned into an
+ invariant one it was on a separate stmt. */
+ if (gimple_assign_single_p (stmt)
+ && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR)
+ recompute_tree_invariant_for_addr_expr (gimple_assign_rhs1 (stmt));
+ gimple_stmt_iterator prev = *gsi;
+ gsi_prev (&prev);
+ if (fold_stmt (gsi))
+ {
+ /* fold_stmt may have created new stmts inbetween
+ the previous stmt and the folded stmt. Mark
+ all defs created there as varying to not confuse
+ the SCCVN machinery as we're using that even during
+ elimination. */
+ if (gsi_end_p (prev))
+ prev = gsi_start_bb (b);
+ else
+ gsi_next (&prev);
+ if (gsi_stmt (prev) != gsi_stmt (*gsi))
+ do
+ {
+ tree def;
+ ssa_op_iter dit;
+ FOR_EACH_SSA_TREE_OPERAND (def, gsi_stmt (prev),
+ dit, SSA_OP_ALL_DEFS)
+ /* As existing DEFs may move between stmts
+ only process new ones. */
+ if (! has_VN_INFO (def))
+ {
+ VN_INFO (def)->valnum = def;
+ VN_INFO (def)->visited = true;
+ }
+ if (gsi_stmt (prev) == gsi_stmt (*gsi))
+ break;
+ gsi_next (&prev);
+ }
+ while (1);
+ }
+ stmt = gsi_stmt (*gsi);
+ /* In case we folded the stmt away schedule the NOP for removal. */
+ if (gimple_nop_p (stmt))
+ to_remove.safe_push (stmt);
+ }
+
+ /* Visit indirect calls and turn them into direct calls if
+ possible using the devirtualization machinery. Do this before
+ checking for required EH/abnormal/noreturn cleanup as devird
+ may expose more of those. */
+ if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
+ {
+ tree fn = gimple_call_fn (call_stmt);
+ if (fn
+ && flag_devirtualize
+ && virtual_method_call_p (fn))
+ {
+ tree otr_type = obj_type_ref_class (fn);
+ unsigned HOST_WIDE_INT otr_tok
+ = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (fn));
+ tree instance;
+ ipa_polymorphic_call_context context (current_function_decl,
+ fn, stmt, &instance);
+ context.get_dynamic_type (instance, OBJ_TYPE_REF_OBJECT (fn),
+ otr_type, stmt);
+ bool final;
+ vec <cgraph_node *> targets
+ = possible_polymorphic_call_targets (obj_type_ref_class (fn),
+ otr_tok, context, &final);
+ if (dump_file)
+ dump_possible_polymorphic_call_targets (dump_file,
+ obj_type_ref_class (fn),
+ otr_tok, context);
+ if (final && targets.length () <= 1 && dbg_cnt (devirt))
+ {
+ tree fn;
+ if (targets.length () == 1)
+ fn = targets[0]->decl;
+ else
+ fn = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
+ if (dump_enabled_p ())
+ {
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, stmt,
+ "converting indirect call to "
+ "function %s\n",
+ lang_hooks.decl_printable_name (fn, 2));
+ }
+ gimple_call_set_fndecl (call_stmt, fn);
+ /* If changing the call to __builtin_unreachable
+ or similar noreturn function, adjust gimple_call_fntype
+ too. */
+ if (gimple_call_noreturn_p (call_stmt)
+ && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fn)))
+ && TYPE_ARG_TYPES (TREE_TYPE (fn))
+ && (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fn)))
+ == void_type_node))
+ gimple_call_set_fntype (call_stmt, TREE_TYPE (fn));
+ maybe_remove_unused_call_args (cfun, call_stmt);
+ modified = true;
+ }
+ }
+ }
+ if (modified)
+ {
+ /* When changing a call into a noreturn call, cfg cleanup
+ is needed to fix up the noreturn call. */
+ if (!was_noreturn
+ && is_gimple_call (stmt) && gimple_call_noreturn_p (stmt))
+ to_fixup.safe_push (stmt);
+ /* When changing a condition or switch into one we know what
+ edge will be executed, schedule a cfg cleanup. */
+ if ((gimple_code (stmt) == GIMPLE_COND
+ && (gimple_cond_true_p (as_a <gcond *> (stmt))
+ || gimple_cond_false_p (as_a <gcond *> (stmt))))
+ || (gimple_code (stmt) == GIMPLE_SWITCH
+ && TREE_CODE (gimple_switch_index
+ (as_a <gswitch *> (stmt))) == INTEGER_CST))
+ el_todo |= TODO_cleanup_cfg;
+ /* If we removed EH side-effects from the statement, clean
+ its EH information. */
+ if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
+ {
+ bitmap_set_bit (need_eh_cleanup,
+ gimple_bb (stmt)->index);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " Removed EH side-effects.\n");
+ }
+ /* Likewise for AB side-effects. */
+ if (can_make_abnormal_goto
+ && !stmt_can_make_abnormal_goto (stmt))
+ {
+ bitmap_set_bit (need_ab_cleanup,
+ gimple_bb (stmt)->index);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " Removed AB side-effects.\n");
+ }
+ update_stmt (stmt);
+ /* In case the VDEF on the original stmt was released, value-number
+ it to the VUSE. This is to make vuse_ssa_val able to skip
+ released virtual operands. */
+ if (vdef && SSA_NAME_IN_FREE_LIST (vdef))
+ VN_INFO (vdef)->valnum = vuse;
+ }
+
+ /* Make new values available - for fully redundant LHS we
+ continue with the next stmt above and skip this. */
+ def_operand_p defp;
+ FOR_EACH_SSA_DEF_OPERAND (defp, stmt, iter, SSA_OP_DEF)
+ eliminate_push_avail (b, DEF_FROM_PTR (defp));
+}
/* Perform elimination for the basic-block B during the domwalk. */
@@ -5359,14 +5302,11 @@ eliminate_dom_walker::before_dom_children (basic_block b)
avail_stack.safe_push (NULL_TREE);
/* Skip unreachable blocks marked unreachable during the SCCVN domwalk. */
- edge_iterator ei;
- edge e;
- FOR_EACH_EDGE (e, ei, b->preds)
- if (e->flags & EDGE_EXECUTABLE)
- break;
- if (! e)
+ if (!(b->flags & BB_EXECUTABLE))
return NULL;
+ vn_context_bb = b;
+
for (gphi_iterator gsi = gsi_start_phis (b); !gsi_end_p (gsi);)
{
gphi *phi = gsi.phi ();
@@ -5378,7 +5318,7 @@ eliminate_dom_walker::before_dom_children (basic_block b)
continue;
}
- tree sprime = eliminate_avail (res);
+ tree sprime = eliminate_avail (b, res);
if (sprime
&& sprime != res)
{
@@ -5416,468 +5356,828 @@ eliminate_dom_walker::before_dom_children (basic_block b)
continue;
}
- eliminate_push_avail (res);
+ eliminate_push_avail (b, res);
gsi_next (&gsi);
}
for (gimple_stmt_iterator gsi = gsi_start_bb (b);
!gsi_end_p (gsi);
gsi_next (&gsi))
- {
- tree sprime = NULL_TREE;
- gimple *stmt = gsi_stmt (gsi);
- tree lhs = gimple_get_lhs (stmt);
- if (lhs && TREE_CODE (lhs) == SSA_NAME
- && !gimple_has_volatile_ops (stmt)
- /* See PR43491. Do not replace a global register variable when
- it is a the RHS of an assignment. Do replace local register
- variables since gcc does not guarantee a local variable will
- be allocated in register.
- ??? The fix isn't effective here. This should instead
- be ensured by not value-numbering them the same but treating
- them like volatiles? */
- && !(gimple_assign_single_p (stmt)
- && (TREE_CODE (gimple_assign_rhs1 (stmt)) == VAR_DECL
- && DECL_HARD_REGISTER (gimple_assign_rhs1 (stmt))
- && is_global_var (gimple_assign_rhs1 (stmt)))))
+ eliminate_stmt (b, &gsi);
+
+ /* Replace destination PHI arguments. */
+ edge_iterator ei;
+ edge e;
+ FOR_EACH_EDGE (e, ei, b->succs)
+ if (e->flags & EDGE_EXECUTABLE)
+ for (gphi_iterator gsi = gsi_start_phis (e->dest);
+ !gsi_end_p (gsi);
+ gsi_next (&gsi))
{
- sprime = eliminate_avail (lhs);
- if (!sprime)
- {
- /* If there is no existing usable leader but SCCVN thinks
- it has an expression it wants to use as replacement,
- insert that. */
- tree val = VN_INFO (lhs)->valnum;
- if (val != VN_TOP
- && TREE_CODE (val) == SSA_NAME
- && VN_INFO (val)->needs_insertion
- && VN_INFO (val)->expr != NULL
- && (sprime = eliminate_insert (&gsi, val)) != NULL_TREE)
- eliminate_push_avail (sprime);
- }
+ gphi *phi = gsi.phi ();
+ use_operand_p use_p = PHI_ARG_DEF_PTR_FROM_EDGE (phi, e);
+ tree arg = USE_FROM_PTR (use_p);
+ if (TREE_CODE (arg) != SSA_NAME
+ || virtual_operand_p (arg))
+ continue;
+ tree sprime = eliminate_avail (b, arg);
+ if (sprime && may_propagate_copy (arg, sprime))
+ propagate_value (use_p, sprime);
+ }
- /* If this now constitutes a copy duplicate points-to
- and range info appropriately. This is especially
- important for inserted code. See tree-ssa-copy.c
- for similar code. */
- if (sprime
- && TREE_CODE (sprime) == SSA_NAME)
+ vn_context_bb = NULL;
+
+ return NULL;
+}
+
+/* Make no longer available leaders no longer available. */
+
+void
+eliminate_dom_walker::after_dom_children (basic_block)
+{
+ tree entry;
+ while ((entry = avail_stack.pop ()) != NULL_TREE)
+ {
+ tree valnum = VN_INFO (entry)->valnum;
+ tree old = avail[SSA_NAME_VERSION (valnum)];
+ if (old == entry)
+ avail[SSA_NAME_VERSION (valnum)] = NULL_TREE;
+ else
+ avail[SSA_NAME_VERSION (valnum)] = entry;
+ }
+}
+
+/* Remove queued stmts and perform delayed cleanups. */
+
+unsigned
+eliminate_dom_walker::eliminate_cleanup (bool region_p)
+{
+ statistics_counter_event (cfun, "Eliminated", eliminations);
+ statistics_counter_event (cfun, "Insertions", insertions);
+
+ /* We cannot remove stmts during BB walk, especially not release SSA
+ names there as this confuses the VN machinery. The stmts ending
+ up in to_remove are either stores or simple copies.
+ Remove stmts in reverse order to make debug stmt creation possible. */
+ while (!to_remove.is_empty ())
+ {
+ bool do_release_defs = true;
+ gimple *stmt = to_remove.pop ();
+
+ /* When we are value-numbering a region we do not require exit PHIs to
+ be present so we have to make sure to deal with uses outside of the
+ region of stmts that we thought are eliminated.
+ ??? Note we may be confused by uses in dead regions we didn't run
+ elimination on. Rather than checking individual uses we accept
+ dead copies to be generated here (gcc.c-torture/execute/20060905-1.c
+ contains such example). */
+ if (region_p)
+ {
+ if (gphi *phi = dyn_cast <gphi *> (stmt))
{
- basic_block sprime_b = gimple_bb (SSA_NAME_DEF_STMT (sprime));
- if (POINTER_TYPE_P (TREE_TYPE (lhs))
- && VN_INFO_PTR_INFO (lhs)
- && ! VN_INFO_PTR_INFO (sprime))
+ tree lhs = gimple_phi_result (phi);
+ if (!has_zero_uses (lhs))
{
- duplicate_ssa_name_ptr_info (sprime,
- VN_INFO_PTR_INFO (lhs));
- if (b != sprime_b)
- mark_ptr_info_alignment_unknown
- (SSA_NAME_PTR_INFO (sprime));
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Keeping eliminated stmt live "
+ "as copy because of out-of-region uses\n");
+ tree sprime = eliminate_avail (gimple_bb (stmt), lhs);
+ gimple *copy = gimple_build_assign (lhs, sprime);
+ gimple_stmt_iterator gsi
+ = gsi_after_labels (gimple_bb (stmt));
+ gsi_insert_before (&gsi, copy, GSI_SAME_STMT);
+ do_release_defs = false;
}
- else if (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
- && VN_INFO_RANGE_INFO (lhs)
- && ! VN_INFO_RANGE_INFO (sprime)
- && b == sprime_b)
- duplicate_ssa_name_range_info (sprime,
- VN_INFO_RANGE_TYPE (lhs),
- VN_INFO_RANGE_INFO (lhs));
}
+ else if (tree lhs = gimple_get_lhs (stmt))
+ if (TREE_CODE (lhs) == SSA_NAME
+ && !has_zero_uses (lhs))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Keeping eliminated stmt live "
+ "as copy because of out-of-region uses\n");
+ tree sprime = eliminate_avail (gimple_bb (stmt), lhs);
+ gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+ if (is_gimple_assign (stmt))
+ {
+ gimple_assign_set_rhs_from_tree (&gsi, sprime);
+ stmt = gsi_stmt (gsi);
+ update_stmt (stmt);
+ if (maybe_clean_or_replace_eh_stmt (stmt, stmt))
+ bitmap_set_bit (need_eh_cleanup, gimple_bb (stmt)->index);
+ continue;
+ }
+ else
+ {
+ gimple *copy = gimple_build_assign (lhs, sprime);
+ gsi_insert_before (&gsi, copy, GSI_SAME_STMT);
+ do_release_defs = false;
+ }
+ }
+ }
- /* Inhibit the use of an inserted PHI on a loop header when
- the address of the memory reference is a simple induction
- variable. In other cases the vectorizer won't do anything
- anyway (either it's loop invariant or a complicated
- expression). */
- if (sprime
- && TREE_CODE (sprime) == SSA_NAME
- && do_pre
- && (flag_tree_loop_vectorize || flag_tree_parallelize_loops > 1)
- && loop_outer (b->loop_father)
- && has_zero_uses (sprime)
- && bitmap_bit_p (inserted_exprs, SSA_NAME_VERSION (sprime))
- && gimple_assign_load_p (stmt))
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Removing dead stmt ");
+ print_gimple_stmt (dump_file, stmt, 0, TDF_NONE);
+ }
+
+ gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+ if (gimple_code (stmt) == GIMPLE_PHI)
+ remove_phi_node (&gsi, do_release_defs);
+ else
+ {
+ basic_block bb = gimple_bb (stmt);
+ unlink_stmt_vdef (stmt);
+ if (gsi_remove (&gsi, true))
+ bitmap_set_bit (need_eh_cleanup, bb->index);
+ if (is_gimple_call (stmt) && stmt_can_make_abnormal_goto (stmt))
+ bitmap_set_bit (need_ab_cleanup, bb->index);
+ if (do_release_defs)
+ release_defs (stmt);
+ }
+
+ /* Removing a stmt may expose a forwarder block. */
+ el_todo |= TODO_cleanup_cfg;
+ }
+
+ /* Fixup stmts that became noreturn calls. This may require splitting
+ blocks and thus isn't possible during the dominator walk. Do this
+ in reverse order so we don't inadvertedly remove a stmt we want to
+ fixup by visiting a dominating now noreturn call first. */
+ while (!to_fixup.is_empty ())
+ {
+ gimple *stmt = to_fixup.pop ();
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Fixing up noreturn call ");
+ print_gimple_stmt (dump_file, stmt, 0);
+ }
+
+ if (fixup_noreturn_call (stmt))
+ el_todo |= TODO_cleanup_cfg;
+ }
+
+ bool do_eh_cleanup = !bitmap_empty_p (need_eh_cleanup);
+ bool do_ab_cleanup = !bitmap_empty_p (need_ab_cleanup);
+
+ if (do_eh_cleanup)
+ gimple_purge_all_dead_eh_edges (need_eh_cleanup);
+
+ if (do_ab_cleanup)
+ gimple_purge_all_dead_abnormal_call_edges (need_ab_cleanup);
+
+ if (do_eh_cleanup || do_ab_cleanup)
+ el_todo |= TODO_cleanup_cfg;
+
+ return el_todo;
+}
+
+/* Eliminate fully redundant computations. */
+
+unsigned
+eliminate_with_rpo_vn (bitmap inserted_exprs)
+{
+ eliminate_dom_walker walker (CDI_DOMINATORS, inserted_exprs);
+
+ walker.walk (cfun->cfg->x_entry_block_ptr);
+ return walker.eliminate_cleanup ();
+}
+
+static unsigned
+do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
+ bool iterate, bool eliminate);
+
+void
+run_rpo_vn (vn_lookup_kind kind)
+{
+ default_vn_walk_kind = kind;
+ do_rpo_vn (cfun, NULL, NULL, true, false);
+
+ /* ??? Prune requirement of these. */
+ constant_to_value_id = new hash_table<vn_constant_hasher> (23);
+ constant_value_ids = BITMAP_ALLOC (NULL);
+
+ /* Initialize the value ids and prune out remaining VN_TOPs
+ from dead code. */
+ tree name;
+ unsigned i;
+ FOR_EACH_SSA_NAME (i, name, cfun)
+ {
+ vn_ssa_aux_t info = VN_INFO (name);
+ if (!info->visited
+ || info->valnum == VN_TOP)
+ info->valnum = name;
+ if (info->valnum == name)
+ info->value_id = get_next_value_id ();
+ else if (is_gimple_min_invariant (info->valnum))
+ info->value_id = get_or_alloc_constant_value_id (info->valnum);
+ }
+
+ /* Propagate. */
+ FOR_EACH_SSA_NAME (i, name, cfun)
+ {
+ vn_ssa_aux_t info = VN_INFO (name);
+ if (TREE_CODE (info->valnum) == SSA_NAME
+ && info->valnum != name
+ && info->value_id != VN_INFO (info->valnum)->value_id)
+ info->value_id = VN_INFO (info->valnum)->value_id;
+ }
+
+ set_hashtable_value_ids ();
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Value numbers:\n");
+ FOR_EACH_SSA_NAME (i, name, cfun)
+ {
+ if (VN_INFO (name)->visited
+ && SSA_VAL (name) != name)
{
- gimple *def_stmt = SSA_NAME_DEF_STMT (sprime);
- basic_block def_bb = gimple_bb (def_stmt);
- if (gimple_code (def_stmt) == GIMPLE_PHI
- && def_bb->loop_father->header == def_bb)
- {
- loop_p loop = def_bb->loop_father;
- ssa_op_iter iter;
- tree op;
- bool found = false;
- FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
- {
- affine_iv iv;
- def_bb = gimple_bb (SSA_NAME_DEF_STMT (op));
- if (def_bb
- && flow_bb_inside_loop_p (loop, def_bb)
- && simple_iv (loop, loop, op, &iv, true))
- {
- found = true;
- break;
- }
- }
- if (found)
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Not replacing ");
- print_gimple_expr (dump_file, stmt, 0);
- fprintf (dump_file, " with ");
- print_generic_expr (dump_file, sprime);
- fprintf (dump_file, " which would add a loop"
- " carried dependence to loop %d\n",
- loop->num);
- }
- /* Don't keep sprime available. */
- sprime = NULL_TREE;
- }
- }
+ print_generic_expr (dump_file, name);
+ fprintf (dump_file, " = ");
+ print_generic_expr (dump_file, SSA_VAL (name));
+ fprintf (dump_file, " (%04d)\n", VN_INFO (name)->value_id);
}
+ }
+ }
+}
- if (sprime)
- {
- /* If we can propagate the value computed for LHS into
- all uses don't bother doing anything with this stmt. */
- if (may_propagate_copy (lhs, sprime))
- {
- /* Mark it for removal. */
- to_remove.safe_push (stmt);
+/* Free VN associated data structures. */
- /* ??? Don't count copy/constant propagations. */
- if (gimple_assign_single_p (stmt)
- && (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
- || gimple_assign_rhs1 (stmt) == sprime))
- continue;
+void
+free_rpo_vn (void)
+{
+ free_vn_table (valid_info);
+ XDELETE (valid_info);
+ obstack_free (&vn_tables_obstack, NULL);
+ obstack_free (&vn_tables_insert_obstack, NULL);
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Replaced ");
- print_gimple_expr (dump_file, stmt, 0);
- fprintf (dump_file, " with ");
- print_generic_expr (dump_file, sprime);
- fprintf (dump_file, " in all uses of ");
- print_gimple_stmt (dump_file, stmt, 0);
- }
+ vn_ssa_aux_iterator_type it;
+ vn_ssa_aux_t info;
+ FOR_EACH_HASH_TABLE_ELEMENT (*vn_ssa_aux_hash, info, vn_ssa_aux_t, it)
+ if (info->needs_insertion)
+ release_ssa_name (info->name);
+ obstack_free (&vn_ssa_aux_obstack, NULL);
+ delete vn_ssa_aux_hash;
- eliminations++;
- continue;
- }
+ delete constant_to_value_id;
+ constant_to_value_id = NULL;
+ BITMAP_FREE (constant_value_ids);
+}
- /* If this is an assignment from our leader (which
- happens in the case the value-number is a constant)
- then there is nothing to do. */
- if (gimple_assign_single_p (stmt)
- && sprime == gimple_assign_rhs1 (stmt))
- continue;
+/* Adaptor to the elimination engine using RPO availability. */
+
+class rpo_elim : public eliminate_dom_walker
+{
+public:
+ rpo_elim(basic_block entry_)
+ : eliminate_dom_walker (CDI_DOMINATORS, NULL), entry (entry_) {}
+ ~rpo_elim();
+
+ virtual tree eliminate_avail (basic_block, tree op);
+
+ virtual void eliminate_push_avail (basic_block, tree);
+
+ basic_block entry;
+ /* Instead of having a local availability lattice for each
+ basic-block and availability at X defined as union of
+ the local availabilities at X and its dominators we're
+ turning this upside down and track availability per
+ value given values are usually made available at very
+ few points (at least one).
+ So we have a value -> vec<location, leader> map where
+ LOCATION is specifying the basic-block LEADER is made
+ available for VALUE. We push to this vector in RPO
+ order thus for iteration we can simply pop the last
+ entries.
+ LOCATION is the basic-block index and LEADER is its
+ SSA name version. */
+ /* ??? We'd like to use auto_vec here with embedded storage
+ but that doesn't play well until we can provide move
+ constructors and use std::move on hash-table expansion.
+ So for now this is a bit more expensive than necessary.
+ We eventually want to switch to a chaining scheme like
+ for hashtable entries for unwinding which would make
+ making the vector part of the vn_ssa_aux structure possible. */
+ typedef hash_map<tree, vec<std::pair<int, int> > > rpo_avail_t;
+ rpo_avail_t m_rpo_avail;
+};
+
+/* Global RPO state for access from hooks. */
+static rpo_elim *rpo_avail;
+
+/* Hook for maybe_push_res_to_seq, lookup the expression in the VN tables. */
+
+static tree
+vn_lookup_simplify_result (gimple_match_op *res_op)
+{
+ if (!res_op->code.is_tree_code ())
+ return NULL_TREE;
+ tree *ops = res_op->ops;
+ unsigned int length = res_op->num_ops;
+ if (res_op->code == CONSTRUCTOR
+ /* ??? We're arriving here with SCCVNs view, decomposed CONSTRUCTOR
+ and GIMPLEs / match-and-simplifies, CONSTRUCTOR as GENERIC tree. */
+ && TREE_CODE (res_op->ops[0]) == CONSTRUCTOR)
+ {
+ length = CONSTRUCTOR_NELTS (res_op->ops[0]);
+ ops = XALLOCAVEC (tree, length);
+ for (unsigned i = 0; i < length; ++i)
+ ops[i] = CONSTRUCTOR_ELT (res_op->ops[0], i)->value;
+ }
+ vn_nary_op_t vnresult = NULL;
+ tree res = vn_nary_op_lookup_pieces (length, (tree_code) res_op->code,
+ res_op->type, ops, &vnresult);
+ /* If this is used from expression simplification make sure to
+ return an available expression. */
+ if (res && TREE_CODE (res) == SSA_NAME && mprts_hook && rpo_avail)
+ res = rpo_avail->eliminate_avail (vn_context_bb, res);
+ return res;
+}
+
+rpo_elim::~rpo_elim ()
+{
+ /* Release the avail vectors. */
+ for (rpo_avail_t::iterator i = m_rpo_avail.begin ();
+ i != m_rpo_avail.end (); ++i)
+ (*i).second.release ();
+}
- /* Else replace its RHS. */
- bool can_make_abnormal_goto
- = is_gimple_call (stmt)
- && stmt_can_make_abnormal_goto (stmt);
+/* Return a leader for OPs value that is valid at BB. */
+tree
+rpo_elim::eliminate_avail (basic_block bb, tree op)
+{
+ bool visited;
+ tree valnum = SSA_VAL (op, &visited);
+ /* If we didn't visit OP then it must be defined outside of the
+ region we process and also dominate it. So it is available. */
+ if (!visited)
+ return op;
+ if (TREE_CODE (valnum) == SSA_NAME)
+ {
+ if (SSA_NAME_IS_DEFAULT_DEF (valnum))
+ return valnum;
+ vec<std::pair<int, int> > *av = m_rpo_avail.get (valnum);
+ if (!av || av->is_empty ())
+ return NULL_TREE;
+ int i = av->length () - 1;
+ if ((*av)[i].first == bb->index)
+ /* On tramp3d 90% of the cases are here. */
+ return ssa_name ((*av)[i].second);
+ do
+ {
+ basic_block abb = BASIC_BLOCK_FOR_FN (cfun, (*av)[i].first);
+ /* ??? During elimination we have to use availability at the
+ definition site of a use we try to replace. This
+ is required to not run into inconsistencies because
+ of dominated_by_p_w_unex behavior and removing a definition
+ while not replacing all uses.
+ ??? We could try to consistently walk dominators
+ ignoring non-executable regions. The nearest common
+ dominator of bb and abb is where we can stop walking. We
+ may also be able to "pre-compute" (bits of) the next immediate
+ (non-)dominator during the RPO walk when marking edges as
+ executable. */
+ if (dominated_by_p_w_unex (bb, abb))
+ {
+ tree leader = ssa_name ((*av)[i].second);
+ /* Prevent eliminations that break loop-closed SSA. */
+ if (loops_state_satisfies_p (LOOP_CLOSED_SSA)
+ && ! SSA_NAME_IS_DEFAULT_DEF (leader)
+ && ! flow_bb_inside_loop_p (gimple_bb (SSA_NAME_DEF_STMT
+ (leader))->loop_father,
+ bb))
+ return NULL_TREE;
if (dump_file && (dump_flags & TDF_DETAILS))
{
- fprintf (dump_file, "Replaced ");
- print_gimple_expr (dump_file, stmt, 0);
- fprintf (dump_file, " with ");
- print_generic_expr (dump_file, sprime);
- fprintf (dump_file, " in ");
- print_gimple_stmt (dump_file, stmt, 0);
+ print_generic_expr (dump_file, leader);
+ fprintf (dump_file, " is available for ");
+ print_generic_expr (dump_file, valnum);
+ fprintf (dump_file, "\n");
}
+ /* On tramp3d 99% of the _remaining_ cases succeed at
+ the first enty. */
+ return leader;
+ }
+ /* ??? Can we somehow skip to the immediate dominator
+ RPO index (bb_to_rpo)? Again, maybe not worth, on
+ tramp3d the worst number of elements in the vector is 9. */
+ }
+ while (--i >= 0);
+ }
+ else if (valnum != VN_TOP)
+ /* valnum is is_gimple_min_invariant. */
+ return valnum;
+ return NULL_TREE;
+}
- eliminations++;
- gimple *orig_stmt = stmt;
- if (!useless_type_conversion_p (TREE_TYPE (lhs),
- TREE_TYPE (sprime)))
- sprime = fold_convert (TREE_TYPE (lhs), sprime);
- tree vdef = gimple_vdef (stmt);
- tree vuse = gimple_vuse (stmt);
- propagate_tree_value_into_stmt (&gsi, sprime);
- stmt = gsi_stmt (gsi);
- update_stmt (stmt);
- if (vdef != gimple_vdef (stmt))
- VN_INFO (vdef)->valnum = vuse;
-
- /* If we removed EH side-effects from the statement, clean
- its EH information. */
- if (maybe_clean_or_replace_eh_stmt (orig_stmt, stmt))
- {
- bitmap_set_bit (need_eh_cleanup,
- gimple_bb (stmt)->index);
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " Removed EH side-effects.\n");
- }
+/* Make LEADER a leader for its value at BB. */
- /* Likewise for AB side-effects. */
- if (can_make_abnormal_goto
- && !stmt_can_make_abnormal_goto (stmt))
- {
- bitmap_set_bit (need_ab_cleanup,
- gimple_bb (stmt)->index);
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " Removed AB side-effects.\n");
- }
+void
+rpo_elim::eliminate_push_avail (basic_block bb, tree leader)
+{
+ tree valnum = VN_INFO (leader)->valnum;
+ if (valnum == VN_TOP)
+ return;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Making available beyond BB%d ", bb->index);
+ print_generic_expr (dump_file, leader);
+ fprintf (dump_file, " for value ");
+ print_generic_expr (dump_file, valnum);
+ fprintf (dump_file, "\n");
+ }
+ bool existed;
+ vec<std::pair<int, int> > &av = m_rpo_avail.get_or_insert (valnum, &existed);
+ if (!existed)
+ {
+ new (&av) vec<std::pair<int, int> >;
+ av = vNULL;
+ av.reserve_exact (2);
+ }
+ av.safe_push (std::make_pair (bb->index, SSA_NAME_VERSION (leader)));
+}
- continue;
+/* Valueization hook for RPO VN plus required state. */
+
+tree
+rpo_vn_valueize (tree name)
+{
+ if (TREE_CODE (name) == SSA_NAME)
+ {
+ vn_ssa_aux_t val = VN_INFO (name);
+ if (val)
+ {
+ tree tem = val->valnum;
+ if (tem != VN_TOP && tem != name)
+ {
+ if (TREE_CODE (tem) != SSA_NAME)
+ return tem;
+ /* For all values we only valueize to an available leader
+ which means we can use SSA name info without restriction. */
+ tem = rpo_avail->eliminate_avail (vn_context_bb, tem);
+ if (tem)
+ return tem;
}
}
+ }
+ return name;
+}
- /* If the statement is a scalar store, see if the expression
- has the same value number as its rhs. If so, the store is
- dead. */
- if (gimple_assign_single_p (stmt)
- && !gimple_has_volatile_ops (stmt)
- && !is_gimple_reg (gimple_assign_lhs (stmt))
- && (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
- || is_gimple_min_invariant (gimple_assign_rhs1 (stmt))))
+/* Insert on PRED_E predicates derived from CODE OPS being true besides the
+ inverted condition. */
+
+static void
+insert_related_predicates_on_edge (enum tree_code code, tree *ops, edge pred_e)
+{
+ switch (code)
+ {
+ case LT_EXPR:
+ /* a < b -> a {!,<}= b */
+ vn_nary_op_insert_pieces_predicated (2, NE_EXPR, boolean_type_node,
+ ops, boolean_true_node, 0, pred_e);
+ vn_nary_op_insert_pieces_predicated (2, LE_EXPR, boolean_type_node,
+ ops, boolean_true_node, 0, pred_e);
+ /* a < b -> ! a {>,=} b */
+ vn_nary_op_insert_pieces_predicated (2, GT_EXPR, boolean_type_node,
+ ops, boolean_false_node, 0, pred_e);
+ vn_nary_op_insert_pieces_predicated (2, EQ_EXPR, boolean_type_node,
+ ops, boolean_false_node, 0, pred_e);
+ break;
+ case GT_EXPR:
+ /* a > b -> a {!,>}= b */
+ vn_nary_op_insert_pieces_predicated (2, NE_EXPR, boolean_type_node,
+ ops, boolean_true_node, 0, pred_e);
+ vn_nary_op_insert_pieces_predicated (2, GE_EXPR, boolean_type_node,
+ ops, boolean_true_node, 0, pred_e);
+ /* a > b -> ! a {<,=} b */
+ vn_nary_op_insert_pieces_predicated (2, LT_EXPR, boolean_type_node,
+ ops, boolean_false_node, 0, pred_e);
+ vn_nary_op_insert_pieces_predicated (2, EQ_EXPR, boolean_type_node,
+ ops, boolean_false_node, 0, pred_e);
+ break;
+ case EQ_EXPR:
+ /* a == b -> ! a {<,>} b */
+ vn_nary_op_insert_pieces_predicated (2, LT_EXPR, boolean_type_node,
+ ops, boolean_false_node, 0, pred_e);
+ vn_nary_op_insert_pieces_predicated (2, GT_EXPR, boolean_type_node,
+ ops, boolean_false_node, 0, pred_e);
+ break;
+ case LE_EXPR:
+ case GE_EXPR:
+ case NE_EXPR:
+ /* Nothing besides inverted condition. */
+ break;
+ default:;
+ }
+}
+
+/* Main stmt worker for RPO VN, process BB. */
+
+static unsigned
+process_bb (rpo_elim &avail, basic_block bb,
+ bool bb_visited, bool iterate_phis, bool iterate, bool eliminate,
+ bool do_region, bitmap exit_bbs)
+{
+ unsigned todo = 0;
+ edge_iterator ei;
+ edge e;
+
+ vn_context_bb = bb;
+
+ /* If we are in loop-closed SSA preserve this state. This is
+ relevant when called on regions from outside of FRE/PRE. */
+ bool lc_phi_nodes = false;
+ if (loops_state_satisfies_p (LOOP_CLOSED_SSA))
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if (e->src->loop_father != e->dest->loop_father
+ && flow_loop_nested_p (e->dest->loop_father,
+ e->src->loop_father))
{
- tree val;
- tree rhs = gimple_assign_rhs1 (stmt);
- vn_reference_t vnresult;
- val = vn_reference_lookup (lhs, gimple_vuse (stmt), VN_WALKREWRITE,
- &vnresult, false);
- if (TREE_CODE (rhs) == SSA_NAME)
- rhs = VN_INFO (rhs)->valnum;
- if (val
- && operand_equal_p (val, rhs, 0))
+ lc_phi_nodes = true;
+ break;
+ }
+
+ /* Value-number all defs in the basic-block. */
+ for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ {
+ gphi *phi = gsi.phi ();
+ tree res = PHI_RESULT (phi);
+ vn_ssa_aux_t res_info = VN_INFO (res);
+ if (!bb_visited)
+ {
+ gcc_assert (!res_info->visited);
+ res_info->valnum = VN_TOP;
+ res_info->visited = true;
+ }
+
+ /* When not iterating force backedge values to varying. */
+ visit_stmt (phi, !iterate_phis);
+ if (virtual_operand_p (res))
+ continue;
+
+ /* Eliminate */
+ /* The interesting case is gcc.dg/tree-ssa/pr22230.c for correctness
+ how we handle backedges and availability.
+ And gcc.dg/tree-ssa/ssa-sccvn-2.c for optimization. */
+ tree val = res_info->valnum;
+ if (res != val && !iterate && eliminate)
+ {
+ if (tree leader = avail.eliminate_avail (bb, res))
{
- /* We can only remove the later store if the former aliases
- at least all accesses the later one does or if the store
- was to readonly memory storing the same value. */
- alias_set_type set = get_alias_set (lhs);
- if (! vnresult
- || vnresult->set == set
- || alias_set_subset_of (set, vnresult->set))
+ if (leader != res
+ /* Preserve loop-closed SSA form. */
+ && (! lc_phi_nodes
+ || is_gimple_min_invariant (leader)))
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
- fprintf (dump_file, "Deleted redundant store ");
- print_gimple_stmt (dump_file, stmt, 0);
+ fprintf (dump_file, "Replaced redundant PHI node "
+ "defining ");
+ print_generic_expr (dump_file, res);
+ fprintf (dump_file, " with ");
+ print_generic_expr (dump_file, leader);
+ fprintf (dump_file, "\n");
}
+ avail.eliminations++;
- /* Queue stmt for removal. */
- to_remove.safe_push (stmt);
- continue;
+ if (may_propagate_copy (res, leader))
+ {
+ /* Schedule for removal. */
+ avail.to_remove.safe_push (phi);
+ continue;
+ }
+ /* ??? Else generate a copy stmt. */
}
}
}
+ /* Only make defs available that not already are. But make
+ sure loop-closed SSA PHI node defs are picked up for
+ downstream uses. */
+ if (lc_phi_nodes
+ || res == val
+ || ! avail.eliminate_avail (bb, res))
+ avail.eliminate_push_avail (bb, res);
+ }
- /* If this is a control statement value numbering left edges
- unexecuted on force the condition in a way consistent with
- that. */
- if (gcond *cond = dyn_cast <gcond *> (stmt))
+ /* For empty BBs mark outgoing edges executable. For non-empty BBs
+ we do this when processing the last stmt as we have to do this
+ before elimination which otherwise forces GIMPLE_CONDs to
+ if (1 != 0) style when seeing non-executable edges. */
+ if (gsi_end_p (gsi_start_bb (bb)))
+ {
+ FOR_EACH_EDGE (e, ei, bb->succs)
{
- if ((EDGE_SUCC (b, 0)->flags & EDGE_EXECUTABLE)
- ^ (EDGE_SUCC (b, 1)->flags & EDGE_EXECUTABLE))
+ if (!(e->flags & EDGE_EXECUTABLE))
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Removing unexecutable edge from ");
- print_gimple_stmt (dump_file, stmt, 0);
- }
- if (((EDGE_SUCC (b, 0)->flags & EDGE_TRUE_VALUE) != 0)
- == ((EDGE_SUCC (b, 0)->flags & EDGE_EXECUTABLE) != 0))
- gimple_cond_make_true (cond);
- else
- gimple_cond_make_false (cond);
- update_stmt (cond);
- el_todo |= TODO_cleanup_cfg;
- continue;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "marking outgoing edge %d -> %d executable\n",
+ e->src->index, e->dest->index);
+ e->flags |= EDGE_EXECUTABLE;
+ e->dest->flags |= BB_EXECUTABLE;
+ }
+ else if (!(e->dest->flags & BB_EXECUTABLE))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "marking destination block %d reachable\n",
+ e->dest->index);
+ e->dest->flags |= BB_EXECUTABLE;
}
}
-
- bool can_make_abnormal_goto = stmt_can_make_abnormal_goto (stmt);
- bool was_noreturn = (is_gimple_call (stmt)
- && gimple_call_noreturn_p (stmt));
- tree vdef = gimple_vdef (stmt);
- tree vuse = gimple_vuse (stmt);
-
- /* If we didn't replace the whole stmt (or propagate the result
- into all uses), replace all uses on this stmt with their
- leaders. */
- bool modified = false;
- use_operand_p use_p;
- ssa_op_iter iter;
- FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
+ }
+ for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
+ !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ ssa_op_iter i;
+ tree op;
+ if (!bb_visited)
{
- tree use = USE_FROM_PTR (use_p);
- /* ??? The call code above leaves stmt operands un-updated. */
- if (TREE_CODE (use) != SSA_NAME)
- continue;
- tree sprime = eliminate_avail (use);
- if (sprime && sprime != use
- && may_propagate_copy (use, sprime)
- /* We substitute into debug stmts to avoid excessive
- debug temporaries created by removed stmts, but we need
- to avoid doing so for inserted sprimes as we never want
- to create debug temporaries for them. */
- && (!inserted_exprs
- || TREE_CODE (sprime) != SSA_NAME
- || !is_gimple_debug (stmt)
- || !bitmap_bit_p (inserted_exprs, SSA_NAME_VERSION (sprime))))
+ FOR_EACH_SSA_TREE_OPERAND (op, gsi_stmt (gsi), i, SSA_OP_ALL_DEFS)
{
- propagate_value (use_p, sprime);
- modified = true;
+ vn_ssa_aux_t op_info = VN_INFO (op);
+ gcc_assert (!op_info->visited);
+ op_info->valnum = VN_TOP;
+ op_info->visited = true;
}
+
+ /* We somehow have to deal with uses that are not defined
+ in the processed region. Forcing unvisited uses to
+ varying here doesn't play well with def-use following during
+ expression simplification, so we deal with this by checking
+ the visited flag in SSA_VAL. */
}
- /* Fold the stmt if modified, this canonicalizes MEM_REFs we propagated
- into which is a requirement for the IPA devirt machinery. */
- gimple *old_stmt = stmt;
- if (modified)
+ visit_stmt (gsi_stmt (gsi));
+
+ gimple *last = gsi_stmt (gsi);
+ e = NULL;
+ switch (gimple_code (last))
{
- /* If a formerly non-invariant ADDR_EXPR is turned into an
- invariant one it was on a separate stmt. */
- if (gimple_assign_single_p (stmt)
- && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR)
- recompute_tree_invariant_for_addr_expr (gimple_assign_rhs1 (stmt));
- gimple_stmt_iterator prev = gsi;
- gsi_prev (&prev);
- if (fold_stmt (&gsi))
- {
- /* fold_stmt may have created new stmts inbetween
- the previous stmt and the folded stmt. Mark
- all defs created there as varying to not confuse
- the SCCVN machinery as we're using that even during
- elimination. */
- if (gsi_end_p (prev))
- prev = gsi_start_bb (b);
- else
- gsi_next (&prev);
- if (gsi_stmt (prev) != gsi_stmt (gsi))
- do
+ case GIMPLE_SWITCH:
+ e = find_taken_edge (bb, vn_valueize (gimple_switch_index
+ (as_a <gswitch *> (last))));
+ break;
+ case GIMPLE_COND:
+ {
+ tree lhs = vn_valueize (gimple_cond_lhs (last));
+ tree rhs = vn_valueize (gimple_cond_rhs (last));
+ tree val = gimple_simplify (gimple_cond_code (last),
+ boolean_type_node, lhs, rhs,
+ NULL, vn_valueize);
+ /* If the condition didn't simplfy see if we have recorded
+ an expression from sofar taken edges. */
+ if (! val || TREE_CODE (val) != INTEGER_CST)
+ {
+ vn_nary_op_t vnresult;
+ tree ops[2];
+ ops[0] = lhs;
+ ops[1] = rhs;
+ val = vn_nary_op_lookup_pieces (2, gimple_cond_code (last),
+ boolean_type_node, ops,
+ &vnresult);
+ /* Did we get a predicated value? */
+ if (! val && vnresult && vnresult->predicated_values)
{
- tree def;
- ssa_op_iter dit;
- FOR_EACH_SSA_TREE_OPERAND (def, gsi_stmt (prev),
- dit, SSA_OP_ALL_DEFS)
- /* As existing DEFs may move between stmts
- we have to guard VN_INFO_GET. */
- if (! has_VN_INFO (def))
- VN_INFO_GET (def)->valnum = def;
- if (gsi_stmt (prev) == gsi_stmt (gsi))
- break;
- gsi_next (&prev);
+ val = vn_nary_op_get_predicated_value (vnresult, bb);
+ if (val && dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Got predicated value ");
+ print_generic_expr (dump_file, val, TDF_NONE);
+ fprintf (dump_file, " for ");
+ print_gimple_stmt (dump_file, last, TDF_SLIM);
+ }
}
- while (1);
- }
- stmt = gsi_stmt (gsi);
- /* In case we folded the stmt away schedule the NOP for removal. */
- if (gimple_nop_p (stmt))
- to_remove.safe_push (stmt);
+ }
+ if (val)
+ e = find_taken_edge (bb, val);
+ if (! e)
+ {
+ /* If we didn't manage to compute the taken edge then
+ push predicated expressions for the condition itself
+ and related conditions to the hashtables. This allows
+ simplification of redundant conditions which is
+ important as early cleanup. */
+ edge true_e, false_e;
+ extract_true_false_edges_from_block (bb, &true_e, &false_e);
+ enum tree_code code = gimple_cond_code (last);
+ enum tree_code icode
+ = invert_tree_comparison (code, HONOR_NANS (lhs));
+ tree ops[2];
+ ops[0] = lhs;
+ ops[1] = rhs;
+ if (do_region
+ && bitmap_bit_p (exit_bbs, true_e->dest->index))
+ true_e = NULL;
+ if (do_region
+ && bitmap_bit_p (exit_bbs, false_e->dest->index))
+ false_e = NULL;
+ if (true_e)
+ vn_nary_op_insert_pieces_predicated
+ (2, code, boolean_type_node, ops,
+ boolean_true_node, 0, true_e);
+ if (false_e)
+ vn_nary_op_insert_pieces_predicated
+ (2, code, boolean_type_node, ops,
+ boolean_false_node, 0, false_e);
+ if (icode != ERROR_MARK)
+ {
+ if (true_e)
+ vn_nary_op_insert_pieces_predicated
+ (2, icode, boolean_type_node, ops,
+ boolean_false_node, 0, true_e);
+ if (false_e)
+ vn_nary_op_insert_pieces_predicated
+ (2, icode, boolean_type_node, ops,
+ boolean_true_node, 0, false_e);
+ }
+ /* Relax for non-integers, inverted condition handled
+ above. */
+ if (INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
+ {
+ if (true_e)
+ insert_related_predicates_on_edge (code, ops, true_e);
+ if (false_e)
+ insert_related_predicates_on_edge (icode, ops, false_e);
+ }
+ }
+ break;
+ }
+ case GIMPLE_GOTO:
+ e = find_taken_edge (bb, vn_valueize (gimple_goto_dest (last)));
+ break;
+ default:
+ e = NULL;
}
-
- /* Visit indirect calls and turn them into direct calls if
- possible using the devirtualization machinery. Do this before
- checking for required EH/abnormal/noreturn cleanup as devird
- may expose more of those. */
- if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
+ if (e)
{
- tree fn = gimple_call_fn (call_stmt);
- if (fn
- && flag_devirtualize
- && virtual_method_call_p (fn))
+ todo = TODO_cleanup_cfg;
+ if (!(e->flags & EDGE_EXECUTABLE))
{
- tree otr_type = obj_type_ref_class (fn);
- unsigned HOST_WIDE_INT otr_tok
- = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (fn));
- tree instance;
- ipa_polymorphic_call_context context (current_function_decl,
- fn, stmt, &instance);
- context.get_dynamic_type (instance, OBJ_TYPE_REF_OBJECT (fn),
- otr_type, stmt);
- bool final;
- vec <cgraph_node *> targets
- = possible_polymorphic_call_targets (obj_type_ref_class (fn),
- otr_tok, context, &final);
- if (dump_file)
- dump_possible_polymorphic_call_targets (dump_file,
- obj_type_ref_class (fn),
- otr_tok, context);
- if (final && targets.length () <= 1 && dbg_cnt (devirt))
- {
- tree fn;
- if (targets.length () == 1)
- fn = targets[0]->decl;
- else
- fn = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
- if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, stmt,
- "converting indirect call to "
- "function %s\n",
- lang_hooks.decl_printable_name (fn, 2));
- }
- gimple_call_set_fndecl (call_stmt, fn);
- /* If changing the call to __builtin_unreachable
- or similar noreturn function, adjust gimple_call_fntype
- too. */
- if (gimple_call_noreturn_p (call_stmt)
- && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fn)))
- && TYPE_ARG_TYPES (TREE_TYPE (fn))
- && (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fn)))
- == void_type_node))
- gimple_call_set_fntype (call_stmt, TREE_TYPE (fn));
- maybe_remove_unused_call_args (cfun, call_stmt);
- modified = true;
- }
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "marking known outgoing %sedge %d -> %d executable\n",
+ e->flags & EDGE_DFS_BACK ? "back-" : "",
+ e->src->index, e->dest->index);
+ e->flags |= EDGE_EXECUTABLE;
+ e->dest->flags |= BB_EXECUTABLE;
}
- }
-
- if (modified)
- {
- /* When changing a call into a noreturn call, cfg cleanup
- is needed to fix up the noreturn call. */
- if (!was_noreturn
- && is_gimple_call (stmt) && gimple_call_noreturn_p (stmt))
- to_fixup.safe_push (stmt);
- /* When changing a condition or switch into one we know what
- edge will be executed, schedule a cfg cleanup. */
- if ((gimple_code (stmt) == GIMPLE_COND
- && (gimple_cond_true_p (as_a <gcond *> (stmt))
- || gimple_cond_false_p (as_a <gcond *> (stmt))))
- || (gimple_code (stmt) == GIMPLE_SWITCH
- && TREE_CODE (gimple_switch_index
- (as_a <gswitch *> (stmt))) == INTEGER_CST))
- el_todo |= TODO_cleanup_cfg;
- /* If we removed EH side-effects from the statement, clean
- its EH information. */
- if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
+ else if (!(e->dest->flags & BB_EXECUTABLE))
{
- bitmap_set_bit (need_eh_cleanup,
- gimple_bb (stmt)->index);
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " Removed EH side-effects.\n");
+ fprintf (dump_file,
+ "marking destination block %d reachable\n",
+ e->dest->index);
+ e->dest->flags |= BB_EXECUTABLE;
}
- /* Likewise for AB side-effects. */
- if (can_make_abnormal_goto
- && !stmt_can_make_abnormal_goto (stmt))
+ }
+ else if (gsi_one_before_end_p (gsi))
+ {
+ FOR_EACH_EDGE (e, ei, bb->succs)
{
- bitmap_set_bit (need_ab_cleanup,
- gimple_bb (stmt)->index);
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " Removed AB side-effects.\n");
+ if (!(e->flags & EDGE_EXECUTABLE))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "marking outgoing edge %d -> %d executable\n",
+ e->src->index, e->dest->index);
+ e->flags |= EDGE_EXECUTABLE;
+ e->dest->flags |= BB_EXECUTABLE;
+ }
+ else if (!(e->dest->flags & BB_EXECUTABLE))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "marking destination block %d reachable\n",
+ e->dest->index);
+ e->dest->flags |= BB_EXECUTABLE;
+ }
}
- update_stmt (stmt);
- if (vdef != gimple_vdef (stmt))
- VN_INFO (vdef)->valnum = vuse;
}
- /* Make new values available - for fully redundant LHS we
- continue with the next stmt above and skip this. */
- def_operand_p defp;
- FOR_EACH_SSA_DEF_OPERAND (defp, stmt, iter, SSA_OP_DEF)
- eliminate_push_avail (DEF_FROM_PTR (defp));
+ /* Eliminate. That also pushes to avail. */
+ if (eliminate && ! iterate)
+ avail.eliminate_stmt (bb, &gsi);
+ else
+ /* If not eliminating, make all not already available defs
+ available. */
+ FOR_EACH_SSA_TREE_OPERAND (op, gsi_stmt (gsi), i, SSA_OP_DEF)
+ if (! avail.eliminate_avail (bb, op))
+ avail.eliminate_push_avail (bb, op);
}
- /* Replace destination PHI arguments. */
- FOR_EACH_EDGE (e, ei, b->succs)
- if (e->flags & EDGE_EXECUTABLE)
+ /* Eliminate in destination PHI arguments. Always substitute in dest
+ PHIs, even for non-executable edges. This handles region
+ exits PHIs. */
+ if (!iterate && eliminate)
+ FOR_EACH_EDGE (e, ei, bb->succs)
for (gphi_iterator gsi = gsi_start_phis (e->dest);
- !gsi_end_p (gsi);
- gsi_next (&gsi))
+ !gsi_end_p (gsi); gsi_next (&gsi))
{
gphi *phi = gsi.phi ();
use_operand_p use_p = PHI_ARG_DEF_PTR_FROM_EDGE (phi, e);
@@ -5885,106 +6185,531 @@ eliminate_dom_walker::before_dom_children (basic_block b)
if (TREE_CODE (arg) != SSA_NAME
|| virtual_operand_p (arg))
continue;
- tree sprime = eliminate_avail (arg);
- if (sprime && may_propagate_copy (arg, sprime))
+ tree sprime;
+ if (SSA_NAME_IS_DEFAULT_DEF (arg))
+ {
+ sprime = SSA_VAL (arg);
+ gcc_assert (TREE_CODE (sprime) != SSA_NAME
+ || SSA_NAME_IS_DEFAULT_DEF (sprime));
+ }
+ else
+ /* Look for sth available at the definition block of the argument.
+ This avoids inconsistencies between availability there which
+ decides if the stmt can be removed and availability at the
+ use site. The SSA property ensures that things available
+ at the definition are also available at uses. */
+ sprime = avail.eliminate_avail (gimple_bb (SSA_NAME_DEF_STMT (arg)),
+ arg);
+ if (sprime
+ && sprime != arg
+ && may_propagate_copy (arg, sprime))
propagate_value (use_p, sprime);
}
- return NULL;
+
+ vn_context_bb = NULL;
+ return todo;
}
-/* Make no longer available leaders no longer available. */
+/* Unwind state per basic-block. */
-void
-eliminate_dom_walker::after_dom_children (basic_block)
+struct unwind_state
{
- tree entry;
- while ((entry = avail_stack.pop ()) != NULL_TREE)
+ /* Times this block has been visited. */
+ unsigned visited;
+ /* Whether to handle this as iteration point or whether to treat
+ incoming backedge PHI values as varying. */
+ bool iterate;
+ /* Maximum RPO index this block is reachable from. */
+ int max_rpo;
+ /* Unwind state. */
+ void *ob_top;
+ vn_reference_t ref_top;
+ vn_phi_t phi_top;
+ vn_nary_op_t nary_top;
+};
+
+/* Unwind the RPO VN state for iteration. */
+
+static void
+do_unwind (unwind_state *to, int rpo_idx, rpo_elim &avail, int *bb_to_rpo)
+{
+ gcc_assert (to->iterate);
+ for (; last_inserted_nary != to->nary_top;
+ last_inserted_nary = last_inserted_nary->next)
{
- tree valnum = VN_INFO (entry)->valnum;
- tree old = avail[SSA_NAME_VERSION (valnum)];
- if (old == entry)
- avail[SSA_NAME_VERSION (valnum)] = NULL_TREE;
+ vn_nary_op_t *slot;
+ slot = valid_info->nary->find_slot_with_hash
+ (last_inserted_nary, last_inserted_nary->hashcode, NO_INSERT);
+ /* Predication causes the need to restore previous state. */
+ if ((*slot)->unwind_to)
+ *slot = (*slot)->unwind_to;
else
- avail[SSA_NAME_VERSION (valnum)] = entry;
+ valid_info->nary->clear_slot (slot);
+ }
+ for (; last_inserted_phi != to->phi_top;
+ last_inserted_phi = last_inserted_phi->next)
+ {
+ vn_phi_t *slot;
+ slot = valid_info->phis->find_slot_with_hash
+ (last_inserted_phi, last_inserted_phi->hashcode, NO_INSERT);
+ valid_info->phis->clear_slot (slot);
+ }
+ for (; last_inserted_ref != to->ref_top;
+ last_inserted_ref = last_inserted_ref->next)
+ {
+ vn_reference_t *slot;
+ slot = valid_info->references->find_slot_with_hash
+ (last_inserted_ref, last_inserted_ref->hashcode, NO_INSERT);
+ (*slot)->operands.release ();
+ valid_info->references->clear_slot (slot);
+ }
+ obstack_free (&vn_tables_obstack, to->ob_top);
+
+ /* Prune [rpo_idx, ] from avail. */
+ /* ??? This is O(number-of-values-in-region) which is
+ O(region-size) rather than O(iteration-piece). */
+ for (rpo_elim::rpo_avail_t::iterator i
+ = avail.m_rpo_avail.begin ();
+ i != avail.m_rpo_avail.end (); ++i)
+ {
+ while (! (*i).second.is_empty ())
+ {
+ if (bb_to_rpo[(*i).second.last ().first] < rpo_idx)
+ break;
+ (*i).second.pop ();
+ }
}
}
-/* Eliminate fully redundant computations. */
+/* Do VN on a SEME region specified by ENTRY and EXIT_BBS in FN.
+ If ITERATE is true then treat backedges optimistically as not
+ executed and iterate. If ELIMINATE is true then perform
+ elimination, otherwise leave that to the caller. */
-unsigned int
-vn_eliminate (bitmap inserted_exprs)
+static unsigned
+do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
+ bool iterate, bool eliminate)
{
- eliminate_dom_walker el (CDI_DOMINATORS, inserted_exprs);
- el.avail.reserve (num_ssa_names);
+ unsigned todo = 0;
- el.walk (cfun->cfg->x_entry_block_ptr);
+ /* We currently do not support region-based iteration when
+ elimination is requested. */
+ gcc_assert (!entry || !iterate || !eliminate);
+ /* When iterating we need loop info up-to-date. */
+ gcc_assert (!iterate || !loops_state_satisfies_p (LOOPS_NEED_FIXUP));
- /* We cannot remove stmts during BB walk, especially not release SSA
- names there as this confuses the VN machinery. The stmts ending
- up in to_remove are either stores or simple copies.
- Remove stmts in reverse order to make debug stmt creation possible. */
- while (!el.to_remove.is_empty ())
+ bool do_region = entry != NULL;
+ if (!do_region)
{
- gimple *stmt = el.to_remove.pop ();
+ entry = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (fn));
+ exit_bbs = BITMAP_ALLOC (NULL);
+ bitmap_set_bit (exit_bbs, EXIT_BLOCK);
+ }
- if (dump_file && (dump_flags & TDF_DETAILS))
+ int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (fn) - NUM_FIXED_BLOCKS);
+ int n = rev_post_order_and_mark_dfs_back_seme
+ (fn, entry, exit_bbs, !loops_state_satisfies_p (LOOPS_NEED_FIXUP), rpo);
+ /* rev_post_order_and_mark_dfs_back_seme fills RPO in reverse order. */
+ for (int i = 0; i < n / 2; ++i)
+ std::swap (rpo[i], rpo[n-i-1]);
+
+ if (!do_region)
+ BITMAP_FREE (exit_bbs);
+
+ int *bb_to_rpo = XNEWVEC (int, last_basic_block_for_fn (fn));
+ for (int i = 0; i < n; ++i)
+ bb_to_rpo[rpo[i]] = i;
+
+ unwind_state *rpo_state = XNEWVEC (unwind_state, n);
+
+ rpo_elim avail (entry->dest);
+ rpo_avail = &avail;
+
+ /* Verify we have no extra entries into the region. */
+ if (flag_checking && do_region)
+ {
+ auto_bb_flag bb_in_region (fn);
+ for (int i = 0; i < n; ++i)
{
- fprintf (dump_file, "Removing dead stmt ");
- print_gimple_stmt (dump_file, stmt, 0, TDF_NONE);
+ basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[i]);
+ bb->flags |= bb_in_region;
}
-
- gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
- if (gimple_code (stmt) == GIMPLE_PHI)
- remove_phi_node (&gsi, true);
- else
+ /* We can't merge the first two loops because we cannot rely
+ on EDGE_DFS_BACK for edges not within the region. But if
+ we decide to always have the bb_in_region flag we can
+ do the checking during the RPO walk itself (but then it's
+ also easy to handle MEME conservatively). */
+ for (int i = 0; i < n; ++i)
{
- basic_block bb = gimple_bb (stmt);
- unlink_stmt_vdef (stmt);
- if (gsi_remove (&gsi, true))
- bitmap_set_bit (el.need_eh_cleanup, bb->index);
- if (is_gimple_call (stmt) && stmt_can_make_abnormal_goto (stmt))
- bitmap_set_bit (el.need_ab_cleanup, bb->index);
- release_defs (stmt);
+ basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[i]);
+ edge e;
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ gcc_assert (e == entry || (e->src->flags & bb_in_region));
+ }
+ for (int i = 0; i < n; ++i)
+ {
+ basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[i]);
+ bb->flags &= ~bb_in_region;
}
+ }
- /* Removing a stmt may expose a forwarder block. */
- el.el_todo |= TODO_cleanup_cfg;
+ /* Create the VN state. For the initial size of the various hashtables
+ use a heuristic based on region size and number of SSA names. */
+ unsigned region_size = (((unsigned HOST_WIDE_INT)n * num_ssa_names)
+ / (n_basic_blocks_for_fn (fn) - NUM_FIXED_BLOCKS));
+ VN_TOP = create_tmp_var_raw (void_type_node, "vn_top");
+
+ vn_ssa_aux_hash = new hash_table <vn_ssa_aux_hasher> (region_size * 2);
+ gcc_obstack_init (&vn_ssa_aux_obstack);
+
+ gcc_obstack_init (&vn_tables_obstack);
+ gcc_obstack_init (&vn_tables_insert_obstack);
+ valid_info = XCNEW (struct vn_tables_s);
+ allocate_vn_table (valid_info, region_size);
+ last_inserted_ref = NULL;
+ last_inserted_phi = NULL;
+ last_inserted_nary = NULL;
+
+ vn_valueize = rpo_vn_valueize;
+
+ /* Initialize the unwind state and edge/BB executable state. */
+ bool need_max_rpo_iterate = false;
+ for (int i = 0; i < n; ++i)
+ {
+ basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[i]);
+ rpo_state[i].visited = 0;
+ rpo_state[i].max_rpo = i;
+ bb->flags &= ~BB_EXECUTABLE;
+ bool has_backedges = false;
+ edge e;
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ {
+ if (e->flags & EDGE_DFS_BACK)
+ has_backedges = true;
+ e->flags &= ~EDGE_EXECUTABLE;
+ if (iterate || e == entry)
+ continue;
+ if (bb_to_rpo[e->src->index] > i)
+ {
+ rpo_state[i].max_rpo = MAX (rpo_state[i].max_rpo,
+ bb_to_rpo[e->src->index]);
+ need_max_rpo_iterate = true;
+ }
+ else
+ rpo_state[i].max_rpo
+ = MAX (rpo_state[i].max_rpo,
+ rpo_state[bb_to_rpo[e->src->index]].max_rpo);
+ }
+ rpo_state[i].iterate = iterate && has_backedges;
}
+ entry->flags |= EDGE_EXECUTABLE;
+ entry->dest->flags |= BB_EXECUTABLE;
+
+ /* When there are irreducible regions the simplistic max_rpo computation
+ above for the case of backedges doesn't work and we need to iterate
+ until there are no more changes. */
+ unsigned nit = 0;
+ while (need_max_rpo_iterate)
+ {
+ nit++;
+ need_max_rpo_iterate = false;
+ for (int i = 0; i < n; ++i)
+ {
+ basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[i]);
+ edge e;
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ {
+ if (e == entry)
+ continue;
+ int max_rpo = MAX (rpo_state[i].max_rpo,
+ rpo_state[bb_to_rpo[e->src->index]].max_rpo);
+ if (rpo_state[i].max_rpo != max_rpo)
+ {
+ rpo_state[i].max_rpo = max_rpo;
+ need_max_rpo_iterate = true;
+ }
+ }
+ }
+ }
+ statistics_histogram_event (cfun, "RPO max_rpo iterations", nit);
- /* Fixup stmts that became noreturn calls. This may require splitting
- blocks and thus isn't possible during the dominator walk. Do this
- in reverse order so we don't inadvertedly remove a stmt we want to
- fixup by visiting a dominating now noreturn call first. */
- while (!el.to_fixup.is_empty ())
+ /* As heuristic to improve compile-time we handle only the N innermost
+ loops and the outermost one optimistically. */
+ if (iterate)
{
- gimple *stmt = el.to_fixup.pop ();
+ loop_p loop;
+ unsigned max_depth = PARAM_VALUE (PARAM_RPO_VN_MAX_LOOP_DEPTH);
+ FOR_EACH_LOOP (loop, LI_ONLY_INNERMOST)
+ if (loop_depth (loop) > max_depth)
+ for (unsigned i = 2;
+ i < loop_depth (loop) - max_depth; ++i)
+ {
+ basic_block header = superloop_at_depth (loop, i)->header;
+ bool non_latch_backedge = false;
+ edge e;
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, header->preds)
+ if (e->flags & EDGE_DFS_BACK)
+ {
+ e->flags |= EDGE_EXECUTABLE;
+ /* There can be a non-latch backedge into the header
+ which is part of an outer irreducible region. We
+ cannot avoid iterating this block then. */
+ if (!dominated_by_p (CDI_DOMINATORS,
+ e->src, e->dest))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "non-latch backedge %d -> %d "
+ "forces iteration of loop %d\n",
+ e->src->index, e->dest->index, loop->num);
+ non_latch_backedge = true;
+ }
+ }
+ rpo_state[bb_to_rpo[header->index]].iterate = non_latch_backedge;
+ }
+ }
- if (dump_file && (dump_flags & TDF_DETAILS))
+ uint64_t nblk = 0;
+ int idx = 0;
+ if (iterate)
+ /* Go and process all blocks, iterating as necessary. */
+ do
+ {
+ basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[idx]);
+
+ /* If the block has incoming backedges remember unwind state. This
+ is required even for non-executable blocks since in irreducible
+ regions we might reach them via the backedge and re-start iterating
+ from there.
+ Note we can individually mark blocks with incoming backedges to
+ not iterate where we then handle PHIs conservatively. We do that
+ heuristically to reduce compile-time for degenerate cases. */
+ if (rpo_state[idx].iterate)
+ {
+ rpo_state[idx].ob_top = obstack_alloc (&vn_tables_obstack, 0);
+ rpo_state[idx].ref_top = last_inserted_ref;
+ rpo_state[idx].phi_top = last_inserted_phi;
+ rpo_state[idx].nary_top = last_inserted_nary;
+ }
+
+ if (!(bb->flags & BB_EXECUTABLE))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Block %d: BB%d found not executable\n",
+ idx, bb->index);
+ idx++;
+ continue;
+ }
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Processing block %d: BB%d\n", idx, bb->index);
+ nblk++;
+ todo |= process_bb (avail, bb,
+ rpo_state[idx].visited != 0,
+ rpo_state[idx].iterate,
+ iterate, eliminate, do_region, exit_bbs);
+ rpo_state[idx].visited++;
+
+ /* Verify if changed values flow over executable outgoing backedges
+ and those change destination PHI values (that's the thing we
+ can easily verify). Reduce over all such edges to the farthest
+ away PHI. */
+ int iterate_to = -1;
+ edge_iterator ei;
+ edge e;
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if ((e->flags & (EDGE_DFS_BACK|EDGE_EXECUTABLE))
+ == (EDGE_DFS_BACK|EDGE_EXECUTABLE)
+ && rpo_state[bb_to_rpo[e->dest->index]].iterate)
+ {
+ int destidx = bb_to_rpo[e->dest->index];
+ if (!rpo_state[destidx].visited)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Unvisited destination %d\n",
+ e->dest->index);
+ if (iterate_to == -1 || destidx < iterate_to)
+ iterate_to = destidx;
+ continue;
+ }
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Looking for changed values of backedge"
+ " %d->%d destination PHIs\n",
+ e->src->index, e->dest->index);
+ vn_context_bb = e->dest;
+ gphi_iterator gsi;
+ for (gsi = gsi_start_phis (e->dest);
+ !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ bool inserted = false;
+ /* While we'd ideally just iterate on value changes
+ we CSE PHIs and do that even across basic-block
+ boundaries. So even hashtable state changes can
+ be important (which is roughly equivalent to
+ PHI argument value changes). To not excessively
+ iterate because of that we track whether a PHI
+ was CSEd to with GF_PLF_1. */
+ bool phival_changed;
+ if ((phival_changed = visit_phi (gsi.phi (),
+ &inserted, false))
+ || (inserted && gimple_plf (gsi.phi (), GF_PLF_1)))
+ {
+ if (!phival_changed
+ && dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "PHI was CSEd and hashtable "
+ "state (changed)\n");
+ if (iterate_to == -1 || destidx < iterate_to)
+ iterate_to = destidx;
+ break;
+ }
+ }
+ vn_context_bb = NULL;
+ }
+ if (iterate_to != -1)
+ {
+ do_unwind (&rpo_state[iterate_to], iterate_to, avail, bb_to_rpo);
+ idx = iterate_to;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Iterating to %d BB%d\n",
+ iterate_to, rpo[iterate_to]);
+ continue;
+ }
+
+ idx++;
+ }
+ while (idx < n);
+
+ else /* !iterate */
+ {
+ /* Process all blocks greedily with a worklist that enforces RPO
+ processing of reachable blocks. */
+ auto_bitmap worklist;
+ bitmap_set_bit (worklist, 0);
+ while (!bitmap_empty_p (worklist))
{
- fprintf (dump_file, "Fixing up noreturn call ");
- print_gimple_stmt (dump_file, stmt, 0);
+ int idx = bitmap_first_set_bit (worklist);
+ bitmap_clear_bit (worklist, idx);
+ basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[idx]);
+ gcc_assert ((bb->flags & BB_EXECUTABLE)
+ && !rpo_state[idx].visited);
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Processing block %d: BB%d\n", idx, bb->index);
+
+ /* When we run into predecessor edges where we cannot trust its
+ executable state mark them executable so PHI processing will
+ be conservative.
+ ??? Do we need to force arguments flowing over that edge
+ to be varying or will they even always be? */
+ edge_iterator ei;
+ edge e;
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if (!(e->flags & EDGE_EXECUTABLE)
+ && !rpo_state[bb_to_rpo[e->src->index]].visited
+ && rpo_state[bb_to_rpo[e->src->index]].max_rpo >= (int)idx)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Cannot trust state of predecessor "
+ "edge %d -> %d, marking executable\n",
+ e->src->index, e->dest->index);
+ e->flags |= EDGE_EXECUTABLE;
+ }
+
+ nblk++;
+ todo |= process_bb (avail, bb, false, false, false, eliminate,
+ do_region, exit_bbs);
+ rpo_state[idx].visited++;
+
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if ((e->flags & EDGE_EXECUTABLE)
+ && e->dest->index != EXIT_BLOCK
+ && (!do_region || !bitmap_bit_p (exit_bbs, e->dest->index))
+ && !rpo_state[bb_to_rpo[e->dest->index]].visited)
+ bitmap_set_bit (worklist, bb_to_rpo[e->dest->index]);
}
+ }
- if (fixup_noreturn_call (stmt))
- el.el_todo |= TODO_cleanup_cfg;
+ /* If statistics or dump file active. */
+ int nex = 0;
+ unsigned max_visited = 1;
+ for (int i = 0; i < n; ++i)
+ {
+ basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[i]);
+ if (bb->flags & BB_EXECUTABLE)
+ nex++;
+ statistics_histogram_event (cfun, "RPO block visited times",
+ rpo_state[i].visited);
+ if (rpo_state[i].visited > max_visited)
+ max_visited = rpo_state[i].visited;
+ }
+ unsigned nvalues = 0, navail = 0;
+ for (rpo_elim::rpo_avail_t::iterator i = avail.m_rpo_avail.begin ();
+ i != avail.m_rpo_avail.end (); ++i)
+ {
+ nvalues++;
+ navail += (*i).second.length ();
+ }
+ statistics_counter_event (cfun, "RPO blocks", n);
+ statistics_counter_event (cfun, "RPO blocks visited", nblk);
+ statistics_counter_event (cfun, "RPO blocks executable", nex);
+ statistics_histogram_event (cfun, "RPO iterations", 10*nblk / nex);
+ statistics_histogram_event (cfun, "RPO num values", nvalues);
+ statistics_histogram_event (cfun, "RPO num avail", navail);
+ statistics_histogram_event (cfun, "RPO num lattice",
+ vn_ssa_aux_hash->elements ());
+ if (dump_file && (dump_flags & (TDF_DETAILS|TDF_STATS)))
+ {
+ fprintf (dump_file, "RPO iteration over %d blocks visited %" PRIu64
+ " blocks in total discovering %d executable blocks iterating "
+ "%d.%d times, a block was visited max. %u times\n",
+ n, nblk, nex,
+ (int)((10*nblk / nex)/10), (int)((10*nblk / nex)%10),
+ max_visited);
+ fprintf (dump_file, "RPO tracked %d values available at %d locations "
+ "and %" PRIu64 " lattice elements\n",
+ nvalues, navail, (uint64_t) vn_ssa_aux_hash->elements ());
}
- bool do_eh_cleanup = !bitmap_empty_p (el.need_eh_cleanup);
- bool do_ab_cleanup = !bitmap_empty_p (el.need_ab_cleanup);
+ if (eliminate)
+ {
+ /* When !iterate we already performed elimination during the RPO
+ walk. */
+ if (iterate)
+ {
+ /* Elimination for region-based VN needs to be done within the
+ RPO walk. */
+ gcc_assert (! do_region);
+ /* Note we can't use avail.walk here because that gets confused
+ by the existing availability and it will be less efficient
+ as well. */
+ todo |= eliminate_with_rpo_vn (NULL);
+ }
+ else
+ todo |= avail.eliminate_cleanup (do_region);
+ }
- if (do_eh_cleanup)
- gimple_purge_all_dead_eh_edges (el.need_eh_cleanup);
+ vn_valueize = NULL;
+ rpo_avail = NULL;
- if (do_ab_cleanup)
- gimple_purge_all_dead_abnormal_call_edges (el.need_ab_cleanup);
+ XDELETEVEC (bb_to_rpo);
+ XDELETEVEC (rpo);
- if (do_eh_cleanup || do_ab_cleanup)
- el.el_todo |= TODO_cleanup_cfg;
+ return todo;
+}
- statistics_counter_event (cfun, "Eliminated", el.eliminations);
- statistics_counter_event (cfun, "Insertions", el.insertions);
+/* Region-based entry for RPO VN. Performs value-numbering and elimination
+ on the SEME region specified by ENTRY and EXIT_BBS. */
- return el.el_todo;
+unsigned
+do_rpo_vn (function *fn, edge entry, bitmap exit_bbs)
+{
+ default_vn_walk_kind = VN_WALKREWRITE;
+ unsigned todo = do_rpo_vn (fn, entry, exit_bbs, false, true);
+ free_rpo_vn ();
+ return todo;
}
@@ -6018,17 +6743,21 @@ public:
}; // class pass_fre
unsigned int
-pass_fre::execute (function *)
+pass_fre::execute (function *fun)
{
- unsigned int todo = 0;
+ unsigned todo = 0;
- run_scc_vn (VN_WALKREWRITE);
+ /* At -O[1g] use the cheap non-iterating mode. */
+ calculate_dominance_info (CDI_DOMINATORS);
+ if (optimize > 1)
+ loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
- /* Remove all the redundant expressions. */
- todo |= vn_eliminate (NULL);
+ default_vn_walk_kind = VN_WALKREWRITE;
+ todo = do_rpo_vn (fun, NULL, NULL, optimize > 1, true);
+ free_rpo_vn ();
- scc_vn_restore_ssa_info ();
- free_scc_vn ();
+ if (optimize > 1)
+ loop_optimizer_finalize ();
return todo;
}
@@ -6040,3 +6769,5 @@ make_pass_fre (gcc::context *ctxt)
{
return new pass_fre (ctxt);
}
+
+#undef BB_EXECUTABLE
diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h
index 323c85f..ea4efd8 100644
--- a/gcc/tree-ssa-sccvn.h
+++ b/gcc/tree-ssa-sccvn.h
@@ -28,6 +28,18 @@ bool expressions_equal_p (tree, tree);
/* TOP of the VN lattice. */
extern tree VN_TOP;
+/* A predicated value. */
+struct vn_pval
+{
+ vn_pval *next;
+ /* The value of the expression this is attached to is RESULT in
+ case the expression is computed dominated by one of the blocks
+ in valid_dominated_by_p. */
+ tree result;
+ unsigned n;
+ int valid_dominated_by_p[1];
+};
+
/* N-ary operations in the hashtable consist of length operands, an
opcode, and a type. Result is the value number of the operation,
and hashcode is stored to avoid having to calculate it
@@ -36,12 +48,19 @@ extern tree VN_TOP;
typedef struct vn_nary_op_s
{
vn_nary_op_s *next;
+ vn_nary_op_s *unwind_to;
/* Unique identify that all expressions with the same value have. */
unsigned int value_id;
ENUM_BITFIELD(tree_code) opcode : 16;
unsigned length : 16;
hashval_t hashcode;
- tree result;
+ unsigned predicated_values : 1;
+ union {
+ /* If ! predicated_values this is the value of the expression. */
+ tree result;
+ /* If predicated_values this is a list of values of the expression. */
+ vn_pval *values;
+ } u;
tree type;
tree op[1];
} *vn_nary_op_t;
@@ -176,36 +195,23 @@ vn_constant_eq_with_type (tree c1, tree c2)
typedef struct vn_ssa_aux
{
+ /* SSA name this vn_ssa_aux is associated with in the lattice. */
+ tree name;
/* Value number. This may be an SSA name or a constant. */
tree valnum;
/* Statements to insert if needs_insertion is true. */
gimple_seq expr;
- /* Saved SSA name info. */
- tree_ssa_name::ssa_name_info_type info;
-
/* Unique identifier that all expressions with the same value have. */
unsigned int value_id;
- /* SCC information. */
- unsigned int dfsnum;
- unsigned int low;
+ /* Whether the SSA_NAME has been processed at least once. */
unsigned visited : 1;
- unsigned on_sccstack : 1;
-
- /* Whether the SSA_NAME has been value numbered already. This is
- only saying whether visit_use has been called on it at least
- once. It cannot be used to avoid visitation for SSA_NAME's
- involved in non-singleton SCC's. */
- unsigned use_processed : 1;
/* Whether the SSA_NAME has no defining statement and thus an
insertion of such with EXPR as definition is required before
a use can be created of it. */
unsigned needs_insertion : 1;
-
- /* Whether range-info is anti-range. */
- unsigned range_info_anti_range_p : 1;
} *vn_ssa_aux_t;
enum vn_lookup_kind { VN_NOWALK, VN_WALK, VN_WALKREWRITE };
@@ -213,11 +219,7 @@ enum vn_lookup_kind { VN_NOWALK, VN_WALK, VN_WALKREWRITE };
/* Return the value numbering info for an SSA_NAME. */
bool has_VN_INFO (tree);
extern vn_ssa_aux_t VN_INFO (tree);
-extern vn_ssa_aux_t VN_INFO_GET (tree);
tree vn_get_expr_for (tree);
-void run_scc_vn (vn_lookup_kind);
-unsigned int vn_eliminate (bitmap);
-void free_scc_vn (void);
void scc_vn_restore_ssa_info (void);
tree vn_nary_op_lookup (tree, vn_nary_op_t *);
tree vn_nary_op_lookup_stmt (gimple *, vn_nary_op_t *);
@@ -250,55 +252,17 @@ bool value_id_constant_p (unsigned int);
tree fully_constant_vn_reference_p (vn_reference_t);
tree vn_nary_simplify (vn_nary_op_t);
-/* Valueize NAME if it is an SSA name, otherwise just return it. */
-
-static inline tree
-vn_valueize (tree name)
-{
- if (TREE_CODE (name) == SSA_NAME)
- {
- tree tem = VN_INFO (name)->valnum;
- return tem == VN_TOP ? name : tem;
- }
- return name;
-}
+unsigned do_rpo_vn (function *, edge, bitmap);
+void run_rpo_vn (vn_lookup_kind);
+unsigned eliminate_with_rpo_vn (bitmap);
+void free_rpo_vn (void);
-/* Get at the original range info for NAME. */
+/* Valueize NAME if it is an SSA name, otherwise just return it. This hook
+ is initialized by run_scc_vn. */
+extern tree (*vn_valueize) (tree);
-inline range_info_def *
-VN_INFO_RANGE_INFO (tree name)
-{
- return (VN_INFO (name)->info.range_info
- ? VN_INFO (name)->info.range_info
- : SSA_NAME_RANGE_INFO (name));
-}
+/* Context that valueization should operate on. */
+extern basic_block vn_context_bb;
-/* Whether the original range info of NAME is an anti-range. */
-
-inline bool
-VN_INFO_ANTI_RANGE_P (tree name)
-{
- return (VN_INFO (name)->info.range_info
- ? VN_INFO (name)->range_info_anti_range_p
- : SSA_NAME_ANTI_RANGE_P (name));
-}
-
-/* Get at the original range info kind for NAME. */
-
-inline value_range_type
-VN_INFO_RANGE_TYPE (tree name)
-{
- return VN_INFO_ANTI_RANGE_P (name) ? VR_ANTI_RANGE : VR_RANGE;
-}
-
-/* Get at the original pointer info for NAME. */
-
-inline ptr_info_def *
-VN_INFO_PTR_INFO (tree name)
-{
- return (VN_INFO (name)->info.ptr_info
- ? VN_INFO (name)->info.ptr_info
- : SSA_NAME_PTR_INFO (name));
-}
#endif /* TREE_SSA_SCCVN_H */
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 1eaa9c5..3fa5ef5 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -291,8 +291,6 @@ get_addr_stridx (tree exp, tree ptr, unsigned HOST_WIDE_INT *offset_out)
static int
get_stridx (tree exp)
{
- tree s, o;
-
if (TREE_CODE (exp) == SSA_NAME)
{
if (ssa_ver_to_stridx[SSA_NAME_VERSION (exp)])
@@ -336,18 +334,10 @@ get_stridx (tree exp)
return idx;
}
- s = string_constant (exp, &o);
- if (s != NULL_TREE
- && (o == NULL_TREE || tree_fits_shwi_p (o))
- && TREE_STRING_LENGTH (s) > 0)
- {
- HOST_WIDE_INT offset = o ? tree_to_shwi (o) : 0;
- const char *p = TREE_STRING_POINTER (s);
- int max = TREE_STRING_LENGTH (s) - 1;
+ const char *p = c_getstr (exp);
+ if (p)
+ return ~(int) strlen (p);
- if (p[max] == '\0' && offset >= 0 && offset <= max)
- return ~(int) strlen (p + offset);
- }
return 0;
}
@@ -581,7 +571,7 @@ get_string_length (strinfo *si)
gcc_assert (is_gimple_call (stmt));
callee = gimple_call_fndecl (stmt);
- gcc_assert (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL);
+ gcc_assert (callee && fndecl_built_in_p (callee, BUILT_IN_NORMAL));
lhs = gimple_call_lhs (stmt);
/* unshare_strinfo is intentionally not called here. The (delayed)
transformation of strcpy or strcat into stpcpy is done at the place
@@ -1107,6 +1097,13 @@ adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat)
to store the extra '\0' in that case. */
if ((tree_to_uhwi (len) & 3) == 0)
return;
+
+ /* Don't fold away an out of bounds access, as this defeats proper
+ warnings. */
+ tree dst = gimple_call_arg (last.stmt, 0);
+ tree size = compute_objsize (dst, 0);
+ if (size && tree_int_cst_lt (size, len))
+ return;
}
else if (TREE_CODE (len) == SSA_NAME)
{
@@ -1153,7 +1150,9 @@ maybe_set_strlen_range (tree lhs, tree src, tree bound)
suggests if it's treated as a poor-man's flexible array member. */
src = TREE_OPERAND (src, 0);
bool src_is_array = TREE_CODE (TREE_TYPE (src)) == ARRAY_TYPE;
- if (src_is_array && !array_at_struct_end_p (src))
+ if (src_is_array
+ && TREE_CODE (src) != MEM_REF
+ && !array_at_struct_end_p (src))
{
tree type = TREE_TYPE (src);
if (tree size = TYPE_SIZE_UNIT (type))
@@ -1627,8 +1626,7 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
tree type = TREE_TYPE (oldlen);
oldlen = fold_build2 (PLUS_EXPR, type, oldlen,
build_int_cst (type, 1));
- check_bounds_or_overlap (as_a <gcall *>(stmt), olddsi->ptr, src,
- oldlen, NULL_TREE);
+ check_bounds_or_overlap (stmt, olddsi->ptr, src, oldlen, NULL_TREE);
}
return;
@@ -1715,8 +1713,7 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
if (const strinfo *chksi = olddsi ? olddsi : dsi)
if (si
- && !check_bounds_or_overlap (as_a <gcall *>(stmt), chksi->ptr, si->ptr,
- NULL_TREE, len))
+ && !check_bounds_or_overlap (stmt, chksi->ptr, si->ptr, NULL_TREE, len))
{
gimple_set_no_warning (stmt, true);
set_no_warning = true;
@@ -2031,8 +2028,6 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
lenrange[0] = wi::shwi (0, prec);
}
- gcall *call = as_a <gcall *> (stmt);
-
/* Set to true for strncat whose bound is derived from the length
of the destination (the expected usage pattern). */
bool cat_dstlen_bounded = false;
@@ -2048,7 +2043,7 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
"%G%qD output truncated before terminating nul "
"copying %E bytes from a string of the same "
"length",
- call, func, cnt);
+ stmt, func, cnt);
else if (!cat_dstlen_bounded)
{
if (wi::geu_p (lenrange[0], cntrange[1]))
@@ -2062,12 +2057,12 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
"from a string of length %wu",
"%G%qD output truncated copying %E bytes "
"from a string of length %wu",
- call, func, cnt, lenrange[0].to_uhwi ());
+ stmt, func, cnt, lenrange[0].to_uhwi ());
return warning_at (callloc, OPT_Wstringop_truncation,
"%G%qD output truncated copying between %wu "
"and %wu bytes from a string of length %wu",
- call, func, cntrange[0].to_uhwi (),
+ stmt, func, cntrange[0].to_uhwi (),
cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
}
else if (wi::geu_p (lenrange[1], cntrange[1]))
@@ -2081,12 +2076,12 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
"byte from a string of length %wu",
"%G%qD output may be truncated copying %E "
"bytes from a string of length %wu",
- call, func, cnt, lenrange[1].to_uhwi ());
+ stmt, func, cnt, lenrange[1].to_uhwi ());
return warning_at (callloc, OPT_Wstringop_truncation,
"%G%qD output may be truncated copying between "
"%wu and %wu bytes from a string of length %wu",
- call, func, cntrange[0].to_uhwi (),
+ stmt, func, cntrange[0].to_uhwi (),
cntrange[1].to_uhwi (), lenrange[1].to_uhwi ());
}
}
@@ -2102,7 +2097,7 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
return warning_at (callloc, OPT_Wstringop_truncation,
"%G%qD output may be truncated copying between "
"%wu and %wu bytes from a string of length %wu",
- call, func, cntrange[0].to_uhwi (),
+ stmt, func, cntrange[0].to_uhwi (),
cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
}
}
@@ -2122,7 +2117,7 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
if (cntrange[0] == cntrange[1])
return warning_at (callloc, OPT_Wstringop_truncation,
"%G%qD specified bound %E equals destination size",
- as_a <gcall *> (stmt), func, cnt);
+ stmt, func, cnt);
}
return false;
@@ -2180,8 +2175,7 @@ handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *gsi)
else
srcsize = NULL_TREE;
- if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, src,
- dstsize, srcsize))
+ if (!check_bounds_or_overlap (stmt, dst, src, dstsize, srcsize))
{
gimple_set_no_warning (stmt, true);
return;
@@ -2222,13 +2216,13 @@ handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *gsi)
&& warning_at (callloc, OPT_Wstringop_truncation,
"%G%qD output truncated before terminating nul "
"copying as many bytes from a string as its length",
- as_a <gcall *>(stmt), func))
+ stmt, func))
warned = true;
else if (silen && is_strlen_related_p (src, silen->ptr))
warned = warning_at (callloc, OPT_Wstringop_overflow_,
"%G%qD specified bound depends on the length "
"of the source argument",
- as_a <gcall *>(stmt), func);
+ stmt, func);
if (warned)
{
location_t strlenloc = pss->second;
@@ -2479,8 +2473,7 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
tree sptr = si && si->ptr ? si->ptr : src;
- if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, sptr,
- NULL_TREE, slen))
+ if (!check_bounds_or_overlap (stmt, dst, sptr, NULL_TREE, slen))
{
gimple_set_no_warning (stmt, true);
set_no_warning = true;
@@ -2590,8 +2583,7 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
tree sptr = si && si->ptr ? si->ptr : src;
- if (!check_bounds_or_overlap (as_a <gcall *>(stmt), dst, sptr,
- dstlen, srcsize))
+ if (!check_bounds_or_overlap (stmt, dst, sptr, dstlen, srcsize))
{
gimple_set_no_warning (stmt, true);
set_no_warning = true;
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index fd24f84..2255835 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -4075,7 +4075,7 @@ handle_lhs_call (gcall *stmt, tree lhs, int flags, vec<ce_s> rhsc,
initialized and thus may point to global memory. All
builtin functions with the malloc attribute behave in a sane way. */
if (!fndecl
- || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL)
+ || !fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
make_constraint_from (vi, nonlocal_id);
tmpc.var = vi->id;
tmpc.offset = 0;
@@ -4729,7 +4729,7 @@ find_func_aliases_for_call (struct function *fn, gcall *t)
varinfo_t fi;
if (fndecl != NULL_TREE
- && DECL_BUILT_IN (fndecl)
+ && fndecl_built_in_p (fndecl)
&& find_func_aliases_for_builtin_call (fn, t))
return;
diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
index 1583881..837679a 100644
--- a/gcc/tree-ssa-tail-merge.c
+++ b/gcc/tree-ssa-tail-merge.c
@@ -286,6 +286,21 @@ struct aux_bb_info
#define BB_VOP_AT_EXIT(bb) (((struct aux_bb_info *)bb->aux)->vop_at_exit)
#define BB_DEP_BB(bb) (((struct aux_bb_info *)bb->aux)->dep_bb)
+/* Valueization helper querying the VN lattice. */
+
+static tree
+tail_merge_valueize (tree name)
+{
+ if (TREE_CODE (name) == SSA_NAME
+ && has_VN_INFO (name))
+ {
+ tree tem = VN_INFO (name)->valnum;
+ if (tem != VN_TOP)
+ return tem;
+ }
+ return name;
+}
+
/* Returns true if the only effect a statement STMT has, is to define locally
used SSA_NAMEs. */
@@ -371,7 +386,7 @@ gvn_uses_equal (tree val1, tree val2)
if (val1 == val2)
return true;
- if (vn_valueize (val1) != vn_valueize (val2))
+ if (tail_merge_valueize (val1) != tail_merge_valueize (val2))
return false;
return ((TREE_CODE (val1) == SSA_NAME || CONSTANT_CLASS_P (val1))
@@ -481,7 +496,7 @@ same_succ_hash (const same_succ *e)
for (i = 0; i < gimple_call_num_args (stmt); i++)
{
arg = gimple_call_arg (stmt, i);
- arg = vn_valueize (arg);
+ arg = tail_merge_valueize (arg);
inchash::add_expr (arg, hstate);
}
}
@@ -1147,7 +1162,7 @@ gimple_equal_p (same_succ *same_succ, gimple *s1, gimple *s2)
if (lhs1 == NULL_TREE || lhs2 == NULL_TREE)
return false;
if (TREE_CODE (lhs1) == SSA_NAME && TREE_CODE (lhs2) == SSA_NAME)
- return vn_valueize (lhs1) == vn_valueize (lhs2);
+ return tail_merge_valueize (lhs1) == tail_merge_valueize (lhs2);
return operand_equal_p (lhs1, lhs2, 0);
case GIMPLE_ASSIGN:
diff --git a/gcc/tree-ssa-ter.c b/gcc/tree-ssa-ter.c
index 4339520..3396a5c 100644
--- a/gcc/tree-ssa-ter.c
+++ b/gcc/tree-ssa-ter.c
@@ -683,7 +683,7 @@ find_replaceable_in_bb (temp_expr_table *tab, basic_block bb)
insns instead of a true call. */
if (is_gimple_call (stmt)
&& !((fndecl = gimple_call_fndecl (stmt))
- && DECL_BUILT_IN (fndecl)))
+ && fndecl_built_in_p (fndecl)))
cur_call_cnt++;
/* Increment counter if this statement sets a local
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index dbc0bbd..a230449 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -977,7 +977,7 @@ thread_around_empty_blocks (edge taken_edge,
|| TREE_CODE (cond) == CASE_LABEL_EXPR))
{
if (TREE_CODE (cond) == CASE_LABEL_EXPR)
- taken_edge = find_edge (bb, label_to_block (CASE_LABEL (cond)));
+ taken_edge = find_edge (bb, label_to_block (cfun, CASE_LABEL (cond)));
else
taken_edge = find_taken_edge (bb, cond);
@@ -1109,7 +1109,7 @@ thread_through_normal_block (edge e,
edge taken_edge;
if (TREE_CODE (cond) == CASE_LABEL_EXPR)
taken_edge = find_edge (e->dest,
- label_to_block (CASE_LABEL (cond)));
+ label_to_block (cfun, CASE_LABEL (cond)));
else
taken_edge = find_taken_edge (e->dest, cond);
diff --git a/gcc/tree-ssa-uncprop.c b/gcc/tree-ssa-uncprop.c
index 7d863a7..98cc79e 100644
--- a/gcc/tree-ssa-uncprop.c
+++ b/gcc/tree-ssa-uncprop.c
@@ -184,7 +184,7 @@ associate_equivalences_with_edges (void)
for (i = 0; i < n_labels; i++)
{
tree label = gimple_switch_label (switch_stmt, i);
- basic_block bb = label_to_block (CASE_LABEL (label));
+ basic_block bb = label_to_block (cfun, CASE_LABEL (label));
if (CASE_HIGH (label)
|| !CASE_LOW (label)
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index 8ccbc85..f3e42dd 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -178,6 +178,7 @@ warn_uninit (enum opt_code wc, tree t, tree expr, tree var,
cfun_loc = DECL_SOURCE_LOCATION (cfun->decl);
xloc = expand_location (location);
floc = expand_location (cfun_loc);
+ auto_diagnostic_group d;
if (warning_at (location, wc, gmsgid, expr))
{
TREE_NO_WARNING (expr) = 1;
@@ -724,7 +725,7 @@ convert_control_dep_chain_into_preds (vec<edge> *dep_chains,
for (idx = 0; idx < gimple_switch_num_labels (gs); ++idx)
{
tree tl = gimple_switch_label (gs, idx);
- if (e->dest == label_to_block (CASE_LABEL (tl)))
+ if (e->dest == label_to_block (cfun, CASE_LABEL (tl)))
{
if (!l)
l = tl;
diff --git a/gcc/tree-stdarg.c b/gcc/tree-stdarg.c
index c859485..f40dc56 100644
--- a/gcc/tree-stdarg.c
+++ b/gcc/tree-stdarg.c
@@ -694,7 +694,7 @@ optimize_va_list_gpr_fpr_size (function *fun)
callee = gimple_call_fndecl (stmt);
if (!callee
- || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL)
+ || !fndecl_built_in_p (callee, BUILT_IN_NORMAL))
continue;
switch (DECL_FUNCTION_CODE (callee))
@@ -867,9 +867,8 @@ optimize_va_list_gpr_fpr_size (function *fun)
tree callee = gimple_call_fndecl (stmt);
if (callee
- && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL
- && (DECL_FUNCTION_CODE (callee) == BUILT_IN_VA_START
- || DECL_FUNCTION_CODE (callee) == BUILT_IN_VA_END))
+ && (fndecl_built_in_p (callee, BUILT_IN_VA_START)
+ || fndecl_built_in_p (callee, BUILT_IN_VA_END)))
continue;
}
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index 43cd9a4..8d8f869 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -769,7 +769,6 @@ static void
lto_input_ts_function_decl_tree_pointers (struct lto_input_block *ib,
struct data_in *data_in, tree expr)
{
- DECL_VINDEX (expr) = stream_read_tree (ib, data_in);
/* DECL_STRUCT_FUNCTION is loaded on demand by cgraph_get_body. */
DECL_FUNCTION_PERSONALITY (expr) = stream_read_tree (ib, data_in);
#ifndef ACCEL_COMPILER
@@ -820,7 +819,6 @@ lto_input_ts_type_common_tree_pointers (struct lto_input_block *ib,
TYPE_CONTEXT (expr) = stream_read_tree (ib, data_in);
/* TYPE_CANONICAL gets re-computed during type merging. */
TYPE_CANONICAL (expr) = NULL_TREE;
- TYPE_STUB_DECL (expr) = stream_read_tree (ib, data_in);
}
/* Read all pointer fields in the TS_TYPE_NON_COMMON structure of EXPR
diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
index a68cd4b..60ec178 100644
--- a/gcc/tree-streamer-out.c
+++ b/gcc/tree-streamer-out.c
@@ -657,7 +657,6 @@ static void
write_ts_function_decl_tree_pointers (struct output_block *ob, tree expr,
bool ref_p)
{
- stream_write_tree (ob, DECL_VINDEX (expr), ref_p);
/* DECL_STRUCT_FUNCTION is handled by lto_output_function. */
stream_write_tree (ob, DECL_FUNCTION_PERSONALITY (expr), ref_p);
/* Don't stream these when passing things to a different target. */
@@ -687,7 +686,9 @@ write_ts_type_common_tree_pointers (struct output_block *ob, tree expr,
stream_write_tree (ob, TYPE_CONTEXT (expr), ref_p);
/* TYPE_CANONICAL is re-computed during type merging, so no need
to stream it here. */
- stream_write_tree (ob, TYPE_STUB_DECL (expr), ref_p);
+ /* Do not stream TYPE_STUB_DECL; it is not needed by LTO but currently
+ it can not be freed by free_lang_data without triggering ICEs in
+ langhooks. */
}
/* Write all pointer fields in the TS_TYPE_NON_COMMON structure of EXPR
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index 9a594a0..64169a6 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -78,7 +78,6 @@ switch_conversion::collect (gswitch *swtch)
unsigned int i;
edge e, e_default, e_first;
edge_iterator ei;
- basic_block first;
m_switch = swtch;
@@ -87,9 +86,8 @@ switch_conversion::collect (gswitch *swtch)
Collect the bits we can deduce from the CFG. */
m_index_expr = gimple_switch_index (swtch);
m_switch_bb = gimple_bb (swtch);
- m_default_bb
- = label_to_block (CASE_LABEL (gimple_switch_default_label (swtch)));
- e_default = find_edge (m_switch_bb, m_default_bb);
+ e_default = gimple_switch_default_edge (cfun, swtch);
+ m_default_bb = e_default->dest;
m_default_prob = e_default->probability;
m_default_count = e_default->count ();
FOR_EACH_EDGE (e, ei, m_switch_bb->succs)
@@ -120,15 +118,9 @@ switch_conversion::collect (gswitch *swtch)
}
if (m_contiguous_range)
- {
- first = label_to_block (CASE_LABEL (gimple_switch_label (swtch, 1)));
- e_first = find_edge (m_switch_bb, first);
- }
+ e_first = gimple_switch_edge (cfun, swtch, 1);
else
- {
- first = m_default_bb;
- e_first = e_default;
- }
+ e_first = e_default;
/* See if there is one common successor block for all branch
targets. If it exists, record it in FINAL_BB.
@@ -306,8 +298,7 @@ switch_conversion::check_final_bb ()
unsigned int branch_num = gimple_switch_num_labels (m_switch);
for (unsigned int i = 1; i < branch_num; i++)
{
- tree lab = CASE_LABEL (gimple_switch_label (m_switch, i));
- if (label_to_block (lab) == bb)
+ if (gimple_switch_label_bb (cfun, m_switch, i) == bb)
{
m_reason = reason;
return false;
@@ -351,7 +342,7 @@ void
switch_conversion::gather_default_values (tree default_case)
{
gphi_iterator gsi;
- basic_block bb = label_to_block (CASE_LABEL (default_case));
+ basic_block bb = label_to_block (cfun, CASE_LABEL (default_case));
edge e;
int i = 0;
@@ -388,7 +379,7 @@ switch_conversion::build_constructors ()
for (i = 1; i < branch_num; i++)
{
tree cs = gimple_switch_label (m_switch, i);
- basic_block bb = label_to_block (CASE_LABEL (cs));
+ basic_block bb = label_to_block (cfun, CASE_LABEL (cs));
edge e;
tree high;
gphi_iterator gsi;
@@ -922,14 +913,7 @@ switch_conversion::expand (gswitch *swtch)
/* Group case labels so that we get the right results from the heuristics
that decide on the code generation approach for this switch. */
m_cfg_altered |= group_case_labels_stmt (swtch);
-
- /* If this switch is now a degenerate case with only a default label,
- there is nothing left for us to do. */
- if (gimple_switch_num_labels (swtch) < 2)
- {
- m_reason = "switch is a degenerate case";
- return;
- }
+ gcc_assert (gimple_switch_num_labels (swtch) >= 2);
collect (swtch);
@@ -1070,6 +1054,9 @@ void
jump_table_cluster::emit (tree index_expr, tree,
tree default_label_expr, basic_block default_bb)
{
+ unsigned HOST_WIDE_INT range = get_range (get_low (), get_high ());
+ unsigned HOST_WIDE_INT nondefault_range = 0;
+
/* For jump table we just emit a new gswitch statement that will
be latter lowered to jump table. */
auto_vec <tree> labels;
@@ -1086,6 +1073,39 @@ jump_table_cluster::emit (tree index_expr, tree,
unshare_expr (default_label_expr), labels);
gimple_stmt_iterator gsi = gsi_start_bb (m_case_bb);
gsi_insert_after (&gsi, s, GSI_NEW_STMT);
+
+ /* Set up even probabilities for all cases. */
+ for (unsigned i = 0; i < m_cases.length (); i++)
+ {
+ simple_cluster *sc = static_cast<simple_cluster *> (m_cases[i]);
+ edge case_edge = find_edge (m_case_bb, sc->m_case_bb);
+ unsigned HOST_WIDE_INT case_range
+ = sc->get_range (sc->get_low (), sc->get_high ());
+ nondefault_range += case_range;
+
+ /* case_edge->aux is number of values in a jump-table that are covered
+ by the case_edge. */
+ case_edge->aux = (void *) ((intptr_t) (case_edge->aux) + case_range);
+ }
+
+ edge default_edge = gimple_switch_default_edge (cfun, s);
+ default_edge->probability = profile_probability::never ();
+
+ for (unsigned i = 0; i < m_cases.length (); i++)
+ {
+ simple_cluster *sc = static_cast<simple_cluster *> (m_cases[i]);
+ edge case_edge = find_edge (m_case_bb, sc->m_case_bb);
+ case_edge->probability
+ = profile_probability::always ().apply_scale ((intptr_t)case_edge->aux,
+ range);
+ }
+
+ /* Number of non-default values is probability of default edge. */
+ default_edge->probability
+ += profile_probability::always ().apply_scale (nondefault_range,
+ range).invert ();
+
+ switch_decision_tree::reset_out_edges_aux (s);
}
/* Find jump tables of given CLUSTERS, where all members of the vector
@@ -1252,12 +1272,16 @@ bit_test_cluster::find_bit_tests (vec<cluster *> &clusters)
return clusters.copy ();
/* Find and build the clusters. */
- for (int end = l;;)
+ for (unsigned end = l;;)
{
int start = min[end].m_start;
if (is_beneficial (clusters, start, end - 1))
- output.safe_push (new bit_test_cluster (clusters, start, end - 1));
+ {
+ bool entire = start == 0 && end == clusters.length ();
+ output.safe_push (new bit_test_cluster (clusters, start, end - 1,
+ entire));
+ }
else
for (int i = end - 1; i >= start; i--)
output.safe_push (clusters[i]);
@@ -1407,6 +1431,7 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
tree minval = get_low ();
tree maxval = get_high ();
tree range = int_const_binop (MINUS_EXPR, maxval, minval);
+ unsigned HOST_WIDE_INT bt_range = get_range (minval, maxval);
/* Go through all case labels, and collect the case labels, profile
counts, and other information we need to build the branch tests. */
@@ -1425,11 +1450,11 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
test[k].mask = wi::zero (prec);
test[k].target_bb = n->m_case_bb;
test[k].label = n->m_case_label_expr;
- test[k].bits = 1;
+ test[k].bits = 0;
count++;
}
- else
- test[k].bits++;
+
+ test[k].bits += n->get_range (n->get_low (), n->get_high ());
lo = tree_to_uhwi (int_const_binop (MINUS_EXPR, n->get_low (), minval));
if (n->get_high () == NULL_TREE)
@@ -1486,14 +1511,20 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
/*simple=*/true, NULL_TREE,
/*before=*/true, GSI_SAME_STMT);
- /* if (idx > range) goto default */
- range = force_gimple_operand_gsi (&gsi,
+ if (m_handles_entire_switch)
+ {
+ /* if (idx > range) goto default */
+ range
+ = force_gimple_operand_gsi (&gsi,
fold_convert (unsigned_index_type, range),
/*simple=*/true, NULL_TREE,
/*before=*/true, GSI_SAME_STMT);
- tmp = fold_build2 (GT_EXPR, boolean_type_node, idx, range);
- basic_block new_bb = hoist_edge_and_branch_if_true (&gsi, tmp, default_bb);
- gsi = gsi_last_bb (new_bb);
+ tmp = fold_build2 (GT_EXPR, boolean_type_node, idx, range);
+ basic_block new_bb
+ = hoist_edge_and_branch_if_true (&gsi, tmp, default_bb,
+ profile_probability::unlikely ());
+ gsi = gsi_last_bb (new_bb);
+ }
/* csui = (1 << (word_mode) idx) */
csui = make_ssa_name (word_type_node);
@@ -1506,17 +1537,23 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
gsi_insert_before (&gsi, shift_stmt, GSI_SAME_STMT);
update_stmt (shift_stmt);
+ profile_probability prob = profile_probability::always ();
+
/* for each unique set of cases:
if (const & csui) goto target */
for (k = 0; k < count; k++)
{
+ prob = profile_probability::always ().apply_scale (test[k].bits,
+ bt_range);
+ bt_range -= test[k].bits;
tmp = wide_int_to_tree (word_type_node, test[k].mask);
tmp = fold_build2 (BIT_AND_EXPR, word_type_node, csui, tmp);
tmp = force_gimple_operand_gsi (&gsi, tmp,
/*simple=*/true, NULL_TREE,
/*before=*/true, GSI_SAME_STMT);
tmp = fold_build2 (NE_EXPR, boolean_type_node, tmp, word_mode_zero);
- new_bb = hoist_edge_and_branch_if_true (&gsi, tmp, test[k].target_bb);
+ basic_block new_bb
+ = hoist_edge_and_branch_if_true (&gsi, tmp, test[k].target_bb, prob);
gsi = gsi_last_bb (new_bb);
}
@@ -1524,7 +1561,8 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
gcc_assert (EDGE_COUNT (gsi_bb (gsi)->succs) == 0);
/* If nothing matched, go to the default label. */
- make_edge (gsi_bb (gsi), default_bb, EDGE_FALLTHRU);
+ edge e = make_edge (gsi_bb (gsi), default_bb, EDGE_FALLTHRU);
+ e->probability = profile_probability::always ();
}
/* Split the basic block at the statement pointed to by GSIP, and insert
@@ -1544,7 +1582,8 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
basic_block
bit_test_cluster::hoist_edge_and_branch_if_true (gimple_stmt_iterator *gsip,
- tree cond, basic_block case_bb)
+ tree cond, basic_block case_bb,
+ profile_probability prob)
{
tree tmp;
gcond *cond_stmt;
@@ -1552,6 +1591,7 @@ bit_test_cluster::hoist_edge_and_branch_if_true (gimple_stmt_iterator *gsip,
basic_block new_bb, split_bb = gsi_bb (*gsip);
edge e_true = make_edge (split_bb, case_bb, EDGE_TRUE_VALUE);
+ e_true->probability = prob;
gcc_assert (e_true->src == split_bb);
tmp = force_gimple_operand_gsi (gsip, cond, /*simple=*/true, NULL,
@@ -1577,15 +1617,11 @@ bit_test_cluster::hoist_edge_and_branch_if_true (gimple_stmt_iterator *gsip,
void
switch_decision_tree::compute_cases_per_edge ()
{
- basic_block bb = gimple_bb (m_switch);
- reset_out_edges_aux ();
+ reset_out_edges_aux (m_switch);
int ncases = gimple_switch_num_labels (m_switch);
for (int i = ncases - 1; i >= 1; --i)
{
- tree elt = gimple_switch_label (m_switch, i);
- tree lab = CASE_LABEL (elt);
- basic_block case_bb = label_to_block_fn (cfun, lab);
- edge case_edge = find_edge (bb, case_bb);
+ edge case_edge = gimple_switch_edge (cfun, m_switch, i);
case_edge->aux = (void *) ((intptr_t) (case_edge->aux) + 1);
}
}
@@ -1601,8 +1637,7 @@ switch_decision_tree::analyze_switch_statement ()
auto_vec<cluster *> clusters;
clusters.create (l - 1);
- tree default_label = CASE_LABEL (gimple_switch_default_label (m_switch));
- basic_block default_bb = label_to_block_fn (cfun, default_label);
+ basic_block default_bb = gimple_switch_default_bb (cfun, m_switch);
m_case_bbs.reserve (l);
m_case_bbs.quick_push (default_bb);
@@ -1612,18 +1647,19 @@ switch_decision_tree::analyze_switch_statement ()
{
tree elt = gimple_switch_label (m_switch, i);
tree lab = CASE_LABEL (elt);
- basic_block case_bb = label_to_block_fn (cfun, lab);
+ basic_block case_bb = label_to_block (cfun, lab);
edge case_edge = find_edge (bb, case_bb);
tree low = CASE_LOW (elt);
tree high = CASE_HIGH (elt);
profile_probability p
= case_edge->probability.apply_scale (1, (intptr_t) (case_edge->aux));
- clusters.quick_push (new simple_cluster (low, high, elt, case_bb, p));
- m_case_bbs.quick_push (case_bb);
+ clusters.quick_push (new simple_cluster (low, high, elt, case_edge->dest,
+ p));
+ m_case_bbs.quick_push (case_edge->dest);
}
- reset_out_edges_aux ();
+ reset_out_edges_aux (m_switch);
/* Find jump table clusters. */
vec<cluster *> output = jump_table_cluster::find_jump_tables (clusters);
@@ -1694,9 +1730,8 @@ switch_decision_tree::try_switch_expansion (vec<cluster *> &clusters)
return false;
/* Find the default case target label. */
- tree default_label_expr = CASE_LABEL (gimple_switch_default_label (m_switch));
- m_default_bb = label_to_block_fn (cfun, default_label_expr);
- edge default_edge = find_edge (bb, m_default_bb);
+ edge default_edge = gimple_switch_default_edge (cfun, m_switch);
+ m_default_bb = default_edge->dest;
/* Do the insertion of a case label into m_case_list. The labels are
fed to us in descending order from the sorted vector of case labels used
@@ -1879,6 +1914,7 @@ switch_decision_tree::balance_case_nodes (case_tree_node **head,
int ranges = 0;
case_tree_node **npp;
case_tree_node *left;
+ profile_probability prob = profile_probability::never ();
/* Count the number of entries on branch. Also count the ranges. */
@@ -1888,6 +1924,7 @@ switch_decision_tree::balance_case_nodes (case_tree_node **head,
ranges++;
i++;
+ prob += np->m_c->m_prob;
np = np->m_right;
}
@@ -1896,39 +1933,35 @@ switch_decision_tree::balance_case_nodes (case_tree_node **head,
/* Split this list if it is long enough for that to help. */
npp = head;
left = *npp;
+ profile_probability pivot_prob = prob.apply_scale (1, 2);
- /* If there are just three nodes, split at the middle one. */
- if (i == 3)
- npp = &(*npp)->m_right;
- else
+ /* Find the place in the list that bisects the list's total cost,
+ where ranges count as 2. */
+ while (1)
{
- /* Find the place in the list that bisects the list's total cost,
- where ranges count as 2.
- Here I gets half the total cost. */
- i = (i + ranges + 1) / 2;
- while (1)
- {
- /* Skip nodes while their cost does not reach that amount. */
- if (!tree_int_cst_equal ((*npp)->m_c->get_low (),
- (*npp)->m_c->get_high ()))
- i--;
- i--;
- if (i <= 0)
- break;
- npp = &(*npp)->m_right;
- }
+ /* Skip nodes while their probability does not reach
+ that amount. */
+ prob -= (*npp)->m_c->m_prob;
+ if ((prob.initialized_p () && prob < pivot_prob)
+ || ! (*npp)->m_right)
+ break;
+ npp = &(*npp)->m_right;
}
- *head = np = *npp;
- *npp = 0;
+
+ np = *npp;
+ *npp = 0;
+ *head = np;
np->m_parent = parent;
- np->m_left = left;
+ np->m_left = left == np ? NULL : left;
/* Optimize each of the two split parts. */
balance_case_nodes (&np->m_left, np);
balance_case_nodes (&np->m_right, np);
np->m_c->m_subtree_prob = np->m_c->m_prob;
- np->m_c->m_subtree_prob += np->m_left->m_c->m_subtree_prob;
- np->m_c->m_subtree_prob += np->m_right->m_c->m_subtree_prob;
+ if (np->m_left)
+ np->m_c->m_subtree_prob += np->m_left->m_c->m_subtree_prob;
+ if (np->m_right)
+ np->m_c->m_subtree_prob += np->m_right->m_c->m_subtree_prob;
}
else
{
@@ -1962,7 +1995,9 @@ switch_decision_tree::dump_case_nodes (FILE *f, case_tree_node *root,
fprintf (f, "%*s", indent_step * indent_level, "");
root->m_c->dump (f);
root->m_c->m_prob.dump (f);
- fputs ("\n", f);
+ fputs (" subtree: ", f);
+ root->m_c->m_subtree_prob.dump (f);
+ fputs (")\n", f);
dump_case_nodes (f, root->m_right, indent_step, indent_level);
}
@@ -2008,6 +2043,34 @@ switch_decision_tree::emit_cmp_and_jump_insns (basic_block bb, tree op0,
return false_edge->dest;
}
+/* Generate code to jump to LABEL if OP0 and OP1 are equal.
+ PROB is the probability of jumping to LABEL_BB.
+ BB is a basic block where the new condition will be placed. */
+
+basic_block
+switch_decision_tree::do_jump_if_equal (basic_block bb, tree op0, tree op1,
+ basic_block label_bb,
+ profile_probability prob)
+{
+ op1 = fold_convert (TREE_TYPE (op0), op1);
+
+ gcond *cond = gimple_build_cond (EQ_EXPR, op0, op1, NULL_TREE, NULL_TREE);
+ gimple_stmt_iterator gsi = gsi_last_bb (bb);
+ gsi_insert_before (&gsi, cond, GSI_SAME_STMT);
+
+ gcc_assert (single_succ_p (bb));
+
+ /* Make a new basic block where false branch will take place. */
+ edge false_edge = split_block (bb, cond);
+ false_edge->flags = EDGE_FALSE_VALUE;
+ false_edge->probability = prob.invert ();
+
+ edge true_edge = make_edge (bb, label_bb, EDGE_TRUE_VALUE);
+ true_edge->probability = prob;
+
+ return false_edge->dest;
+}
+
/* Emit step-by-step code to select a case for the value of INDEX.
The thus generated decision tree follows the form of the
case-node binary tree NODE, whose nodes represent test conditions.
@@ -2020,41 +2083,193 @@ switch_decision_tree::emit_case_nodes (basic_block bb, tree index,
profile_probability default_prob,
tree index_type)
{
+ profile_probability p;
+
/* If node is null, we are done. */
if (node == NULL)
return bb;
- /* Branch to a label where we will handle it later. */
- basic_block test_bb = split_edge (single_succ_edge (bb));
- redirect_edge_succ (single_pred_edge (test_bb),
- single_succ_edge (bb)->dest);
-
- profile_probability probability
- = (node->m_right
- ? node->m_right->m_c->m_subtree_prob : profile_probability::never ());
- probability = ((probability + default_prob.apply_scale (1, 2))
- / (node->m_c->m_subtree_prob + default_prob));
- bb = emit_cmp_and_jump_insns (bb, index, node->m_c->get_high (), GT_EXPR,
- test_bb, probability);
- default_prob = default_prob.apply_scale (1, 2);
-
- /* Value belongs to this node or to the left-hand subtree. */
- probability = node->m_c->m_prob /
- (node->m_c->m_subtree_prob + default_prob);
- bb = emit_cmp_and_jump_insns (bb, index, node->m_c->get_low (), GE_EXPR,
- node->m_c->m_case_bb, probability);
-
- /* Handle the left-hand subtree. */
- bb = emit_case_nodes (bb, index, node->m_left,
- default_prob, index_type);
-
- /* If the left-hand subtree fell through,
- don't let it fall into the right-hand subtree. */
- if (m_default_bb)
- emit_jump (bb, m_default_bb);
+ /* Single value case. */
+ if (node->m_c->is_single_value_p ())
+ {
+ /* Node is single valued. First see if the index expression matches
+ this node and then check our children, if any. */
+ p = node->m_c->m_prob / (node->m_c->m_subtree_prob + default_prob);
+ bb = do_jump_if_equal (bb, index, node->m_c->get_low (),
+ node->m_c->m_case_bb, p);
+ /* Since this case is taken at this point, reduce its weight from
+ subtree_weight. */
+ node->m_c->m_subtree_prob -= p;
+
+ if (node->m_left != NULL && node->m_right != NULL)
+ {
+ /* 1) the node has both children
+
+ If both children are single-valued cases with no
+ children, finish up all the work. This way, we can save
+ one ordered comparison. */
+
+ if (!node->m_left->has_child ()
+ && node->m_left->m_c->is_single_value_p ()
+ && !node->m_right->has_child ()
+ && node->m_right->m_c->is_single_value_p ())
+ {
+ p = (node->m_right->m_c->m_prob
+ / (node->m_c->m_subtree_prob + default_prob));
+ bb = do_jump_if_equal (bb, index, node->m_right->m_c->get_low (),
+ node->m_right->m_c->m_case_bb, p);
+
+ p = (node->m_left->m_c->m_prob
+ / (node->m_c->m_subtree_prob + default_prob));
+ bb = do_jump_if_equal (bb, index, node->m_left->m_c->get_low (),
+ node->m_left->m_c->m_case_bb, p);
+ }
+ else
+ {
+ /* Branch to a label where we will handle it later. */
+ basic_block test_bb = split_edge (single_succ_edge (bb));
+ redirect_edge_succ (single_pred_edge (test_bb),
+ single_succ_edge (bb)->dest);
+
+ p = ((node->m_right->m_c->m_subtree_prob
+ + default_prob.apply_scale (1, 2))
+ / (node->m_c->m_subtree_prob + default_prob));
+ bb = emit_cmp_and_jump_insns (bb, index, node->m_c->get_high (),
+ GT_EXPR, test_bb, p);
+ default_prob = default_prob.apply_scale (1, 2);
+
+ /* Handle the left-hand subtree. */
+ bb = emit_case_nodes (bb, index, node->m_left,
+ default_prob, index_type);
+
+ /* If the left-hand subtree fell through,
+ don't let it fall into the right-hand subtree. */
+ if (bb && m_default_bb)
+ emit_jump (bb, m_default_bb);
+
+ bb = emit_case_nodes (test_bb, index, node->m_right,
+ default_prob, index_type);
+ }
+ }
+ else if (node->m_left == NULL && node->m_right != NULL)
+ {
+ /* 2) the node has only right child. */
+
+ /* Here we have a right child but no left so we issue a conditional
+ branch to default and process the right child.
+
+ Omit the conditional branch to default if the right child
+ does not have any children and is single valued; it would
+ cost too much space to save so little time. */
- bb = emit_case_nodes (test_bb, index, node->m_right,
- default_prob, index_type);
+ if (node->m_right->has_child ()
+ || !node->m_right->m_c->is_single_value_p ())
+ {
+ p = (default_prob.apply_scale (1, 2)
+ / (node->m_c->m_subtree_prob + default_prob));
+ bb = emit_cmp_and_jump_insns (bb, index, node->m_c->get_low (),
+ LT_EXPR, m_default_bb, p);
+ default_prob = default_prob.apply_scale (1, 2);
+
+ bb = emit_case_nodes (bb, index, node->m_right, default_prob,
+ index_type);
+ }
+ else
+ {
+ /* We cannot process node->right normally
+ since we haven't ruled out the numbers less than
+ this node's value. So handle node->right explicitly. */
+ p = (node->m_right->m_c->m_subtree_prob
+ / (node->m_c->m_subtree_prob + default_prob));
+ bb = do_jump_if_equal (bb, index, node->m_right->m_c->get_low (),
+ node->m_right->m_c->m_case_bb, p);
+ }
+ }
+ else if (node->m_left != NULL && node->m_right == NULL)
+ {
+ /* 3) just one subtree, on the left. Similar case as previous. */
+
+ if (node->m_left->has_child ()
+ || !node->m_left->m_c->is_single_value_p ())
+ {
+ p = (default_prob.apply_scale (1, 2)
+ / (node->m_c->m_subtree_prob + default_prob));
+ bb = emit_cmp_and_jump_insns (bb, index, node->m_c->get_high (),
+ GT_EXPR, m_default_bb, p);
+ default_prob = default_prob.apply_scale (1, 2);
+
+ bb = emit_case_nodes (bb, index, node->m_left, default_prob,
+ index_type);
+ }
+ else
+ {
+ /* We cannot process node->left normally
+ since we haven't ruled out the numbers less than
+ this node's value. So handle node->left explicitly. */
+ p = (node->m_left->m_c->m_subtree_prob
+ / (node->m_c->m_subtree_prob + default_prob));
+ bb = do_jump_if_equal (bb, index, node->m_left->m_c->get_low (),
+ node->m_left->m_c->m_case_bb, p);
+ }
+ }
+ }
+ else
+ {
+ /* Node is a range. These cases are very similar to those for a single
+ value, except that we do not start by testing whether this node
+ is the one to branch to. */
+ if (node->has_child () || node->m_c->get_type () != SIMPLE_CASE)
+ {
+ /* Branch to a label where we will handle it later. */
+ basic_block test_bb = split_edge (single_succ_edge (bb));
+ redirect_edge_succ (single_pred_edge (test_bb),
+ single_succ_edge (bb)->dest);
+
+
+ profile_probability right_prob = profile_probability::never ();
+ if (node->m_right)
+ right_prob = node->m_right->m_c->m_subtree_prob;
+ p = ((right_prob + default_prob.apply_scale (1, 2))
+ / (node->m_c->m_subtree_prob + default_prob));
+
+ bb = emit_cmp_and_jump_insns (bb, index, node->m_c->get_high (),
+ GT_EXPR, test_bb, p);
+ default_prob = default_prob.apply_scale (1, 2);
+
+ /* Value belongs to this node or to the left-hand subtree. */
+ p = node->m_c->m_prob / (node->m_c->m_subtree_prob + default_prob);
+ bb = emit_cmp_and_jump_insns (bb, index, node->m_c->get_low (),
+ GE_EXPR, node->m_c->m_case_bb, p);
+
+ /* Handle the left-hand subtree. */
+ bb = emit_case_nodes (bb, index, node->m_left,
+ default_prob, index_type);
+
+ /* If the left-hand subtree fell through,
+ don't let it fall into the right-hand subtree. */
+ if (bb && m_default_bb)
+ emit_jump (bb, m_default_bb);
+
+ bb = emit_case_nodes (test_bb, index, node->m_right,
+ default_prob, index_type);
+ }
+ else
+ {
+ /* Node has no children so we check low and high bounds to remove
+ redundant tests. Only one of the bounds can exist,
+ since otherwise this node is bounded--a case tested already. */
+ tree lhs, rhs;
+ generate_range_test (bb, index, node->m_c->get_low (),
+ node->m_c->get_high (), &lhs, &rhs);
+ p = default_prob / (node->m_c->m_subtree_prob + default_prob);
+
+ bb = emit_cmp_and_jump_insns (bb, lhs, rhs, GT_EXPR,
+ m_default_bb, p);
+
+ emit_jump (bb, node->m_c->m_case_bb);
+ return NULL;
+ }
+ }
return bb;
}
@@ -2204,8 +2419,13 @@ pass_lower_switch<O0>::execute (function *fun)
FOR_EACH_BB_FN (bb, fun)
{
gimple *stmt = last_stmt (bb);
- if (stmt && gimple_code (stmt) == GIMPLE_SWITCH)
- switch_statements.safe_push (stmt);
+ gswitch *swtch;
+ if (stmt && (swtch = dyn_cast<gswitch *> (stmt)))
+ {
+ if (!O0)
+ group_case_labels_stmt (swtch);
+ switch_statements.safe_push (swtch);
+ }
}
for (unsigned i = 0; i < switch_statements.length (); i++)
diff --git a/gcc/tree-switch-conversion.h b/gcc/tree-switch-conversion.h
index 4beac78..37ed219 100644
--- a/gcc/tree-switch-conversion.h
+++ b/gcc/tree-switch-conversion.h
@@ -72,6 +72,13 @@ struct cluster
/* Emit GIMPLE code to handle the cluster. */
virtual void emit (tree, tree, tree, basic_block) = 0;
+ /* Return true if a cluster handles only a single case value and the
+ value is not a range. */
+ virtual bool is_single_value_p ()
+ {
+ return false;
+ }
+
/* Return range of a cluster. If value would overflow in type of LOW,
then return 0. */
static unsigned HOST_WIDE_INT get_range (tree low, tree high)
@@ -161,6 +168,11 @@ struct simple_cluster: public cluster
gcc_unreachable ();
}
+ bool is_single_value_p ()
+ {
+ return tree_int_cst_equal (get_low (), get_high ());
+ }
+
/* Low value of the case. */
tree m_low;
@@ -329,8 +341,10 @@ This transformation was contributed by Roger Sayle, see this e-mail:
struct bit_test_cluster: public group_cluster
{
/* Constructor. */
- bit_test_cluster (vec<cluster *> &clusters, unsigned start, unsigned end)
- :group_cluster (clusters, start, end)
+ bit_test_cluster (vec<cluster *> &clusters, unsigned start, unsigned end,
+ bool handles_entire_switch)
+ :group_cluster (clusters, start, end),
+ m_handles_entire_switch (handles_entire_switch)
{}
cluster_type
@@ -396,7 +410,11 @@ struct bit_test_cluster: public group_cluster
Returns the newly created basic block. */
static basic_block hoist_edge_and_branch_if_true (gimple_stmt_iterator *gsip,
tree cond,
- basic_block case_bb);
+ basic_block case_bb,
+ profile_probability prob);
+
+ /* True when the jump table handles an entire switch statement. */
+ bool m_handles_entire_switch;
/* Maximum number of different basic blocks that can be handled by
a bit test. */
@@ -429,6 +447,12 @@ struct case_tree_node
/* Empty Constructor. */
case_tree_node ();
+ /* Return true when it has a child. */
+ bool has_child ()
+ {
+ return m_left != NULL || m_right != NULL;
+ }
+
/* Left son in binary tree. */
case_tree_node *m_left;
@@ -513,10 +537,6 @@ struct switch_decision_tree
/* Attempt to expand CLUSTERS as a decision tree. Return true when
expanded. */
bool try_switch_expansion (vec<cluster *> &clusters);
-
- /* Reset the aux field of all outgoing edges of switch basic block. */
- inline void reset_out_edges_aux ();
-
/* Compute the number of case labels that correspond to each outgoing edge of
switch statement. Record this information in the aux field of the edge.
*/
@@ -576,6 +596,15 @@ struct switch_decision_tree
basic_block label_bb,
profile_probability prob);
+ /* Generate code to jump to LABEL if OP0 and OP1 are equal in mode MODE.
+ PROB is the probability of jumping to LABEL_BB. */
+ static basic_block do_jump_if_equal (basic_block bb, tree op0, tree op1,
+ basic_block label_bb,
+ profile_probability prob);
+
+ /* Reset the aux field of all outgoing edges of switch basic block. */
+ static inline void reset_out_edges_aux (gswitch *swtch);
+
/* Switch statement. */
gswitch *m_switch;
@@ -838,9 +867,9 @@ struct switch_conversion
};
void
-switch_decision_tree::reset_out_edges_aux ()
+switch_decision_tree::reset_out_edges_aux (gswitch *swtch)
{
- basic_block bb = gimple_bb (m_switch);
+ basic_block bb = gimple_bb (swtch);
edge e;
edge_iterator ei;
FOR_EACH_EDGE (e, ei, bb->succs)
diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c
index 9ebed9d..8e9c2cb 100644
--- a/gcc/tree-tailcall.c
+++ b/gcc/tree-tailcall.c
@@ -476,7 +476,7 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
tail_recursion = false;
func = gimple_call_fndecl (call);
if (func
- && !DECL_BUILT_IN (func)
+ && !fndecl_built_in_p (func)
&& recursive_call_p (current_function_decl, func))
{
tree arg;
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 63429a3..56b7968 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -74,8 +74,7 @@ vect_lanes_optab_supported_p (const char *name, convert_optab optab,
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "no array mode for %s["
- HOST_WIDE_INT_PRINT_DEC "]\n",
+ "no array mode for %s[%wu]\n",
GET_MODE_NAME (mode), count);
return false;
}
@@ -99,7 +98,7 @@ vect_lanes_optab_supported_p (const char *name, convert_optab optab,
}
-/* Return the smallest scalar part of STMT.
+/* Return the smallest scalar part of STMT_INFO.
This is used to determine the vectype of the stmt. We generally set the
vectype according to the type of the result (lhs). For stmts whose
result-type is different than the type of the arguments (e.g., demotion,
@@ -117,10 +116,11 @@ vect_lanes_optab_supported_p (const char *name, convert_optab optab,
types. */
tree
-vect_get_smallest_scalar_type (gimple *stmt, HOST_WIDE_INT *lhs_size_unit,
- HOST_WIDE_INT *rhs_size_unit)
+vect_get_smallest_scalar_type (stmt_vec_info stmt_info,
+ HOST_WIDE_INT *lhs_size_unit,
+ HOST_WIDE_INT *rhs_size_unit)
{
- tree scalar_type = gimple_expr_type (stmt);
+ tree scalar_type = gimple_expr_type (stmt_info->stmt);
HOST_WIDE_INT lhs, rhs;
/* During the analysis phase, this function is called on arbitrary
@@ -130,15 +130,16 @@ vect_get_smallest_scalar_type (gimple *stmt, HOST_WIDE_INT *lhs_size_unit,
lhs = rhs = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (scalar_type));
- if (is_gimple_assign (stmt)
- && (gimple_assign_cast_p (stmt)
- || gimple_assign_rhs_code (stmt) == DOT_PROD_EXPR
- || gimple_assign_rhs_code (stmt) == WIDEN_SUM_EXPR
- || gimple_assign_rhs_code (stmt) == WIDEN_MULT_EXPR
- || gimple_assign_rhs_code (stmt) == WIDEN_LSHIFT_EXPR
- || gimple_assign_rhs_code (stmt) == FLOAT_EXPR))
+ gassign *assign = dyn_cast <gassign *> (stmt_info->stmt);
+ if (assign
+ && (gimple_assign_cast_p (assign)
+ || gimple_assign_rhs_code (assign) == DOT_PROD_EXPR
+ || gimple_assign_rhs_code (assign) == WIDEN_SUM_EXPR
+ || gimple_assign_rhs_code (assign) == WIDEN_MULT_EXPR
+ || gimple_assign_rhs_code (assign) == WIDEN_LSHIFT_EXPR
+ || gimple_assign_rhs_code (assign) == FLOAT_EXPR))
{
- tree rhs_type = TREE_TYPE (gimple_assign_rhs1 (stmt));
+ tree rhs_type = TREE_TYPE (gimple_assign_rhs1 (assign));
rhs = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (rhs_type));
if (rhs < lhs)
@@ -182,23 +183,21 @@ vect_check_nonzero_value (loop_vec_info loop_vinfo, tree value)
return;
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "need run-time check that ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, value);
- dump_printf (MSG_NOTE, " is nonzero\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "need run-time check that %T is nonzero\n",
+ value);
LOOP_VINFO_CHECK_NONZERO (loop_vinfo).safe_push (value);
}
-/* Return true if we know that the order of vectorized STMT_A and
- vectorized STMT_B will be the same as the order of STMT_A and STMT_B.
- At least one of the statements is a write. */
+/* Return true if we know that the order of vectorized DR_INFO_A and
+ vectorized DR_INFO_B will be the same as the order of DR_INFO_A and
+ DR_INFO_B. At least one of the accesses is a write. */
static bool
-vect_preserves_scalar_order_p (gimple *stmt_a, gimple *stmt_b)
+vect_preserves_scalar_order_p (dr_vec_info *dr_info_a, dr_vec_info *dr_info_b)
{
- stmt_vec_info stmtinfo_a = vinfo_for_stmt (stmt_a);
- stmt_vec_info stmtinfo_b = vinfo_for_stmt (stmt_b);
+ stmt_vec_info stmtinfo_a = dr_info_a->stmt;
+ stmt_vec_info stmtinfo_b = dr_info_b->stmt;
/* Single statements are always kept in their original order. */
if (!STMT_VINFO_GROUPED_ACCESS (stmtinfo_a)
@@ -212,12 +211,10 @@ vect_preserves_scalar_order_p (gimple *stmt_a, gimple *stmt_b)
(but could happen later) while reads will happen no later than their
current position (but could happen earlier). Reordering is therefore
only possible if the first access is a write. */
- if (is_pattern_stmt_p (stmtinfo_a))
- stmt_a = STMT_VINFO_RELATED_STMT (stmtinfo_a);
- if (is_pattern_stmt_p (stmtinfo_b))
- stmt_b = STMT_VINFO_RELATED_STMT (stmtinfo_b);
- gimple *earlier_stmt = get_earlier_stmt (stmt_a, stmt_b);
- return !DR_IS_WRITE (STMT_VINFO_DATA_REF (vinfo_for_stmt (earlier_stmt)));
+ stmtinfo_a = vect_orig_stmt (stmtinfo_a);
+ stmtinfo_b = vect_orig_stmt (stmtinfo_b);
+ stmt_vec_info earlier_stmt_info = get_earlier_stmt (stmtinfo_a, stmtinfo_b);
+ return !DR_IS_WRITE (STMT_VINFO_DATA_REF (earlier_stmt_info));
}
/* A subroutine of vect_analyze_data_ref_dependence. Handle
@@ -267,10 +264,10 @@ vect_analyze_possibly_independent_ddr (data_dependence_relation *ddr,
Note that the alias checks will be removed if the VF ends up
being small enough. */
- return (!STMT_VINFO_GATHER_SCATTER_P
- (vinfo_for_stmt (DR_STMT (DDR_A (ddr))))
- && !STMT_VINFO_GATHER_SCATTER_P
- (vinfo_for_stmt (DR_STMT (DDR_B (ddr))))
+ dr_vec_info *dr_info_a = loop_vinfo->lookup_dr (DDR_A (ddr));
+ dr_vec_info *dr_info_b = loop_vinfo->lookup_dr (DDR_B (ddr));
+ return (!STMT_VINFO_GATHER_SCATTER_P (dr_info_a->stmt)
+ && !STMT_VINFO_GATHER_SCATTER_P (dr_info_b->stmt)
&& vect_mark_for_runtime_alias_test (ddr, loop_vinfo));
}
}
@@ -294,8 +291,10 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
struct data_reference *dra = DDR_A (ddr);
struct data_reference *drb = DDR_B (ddr);
- stmt_vec_info stmtinfo_a = vinfo_for_stmt (vect_dr_stmt (dra));
- stmt_vec_info stmtinfo_b = vinfo_for_stmt (vect_dr_stmt (drb));
+ dr_vec_info *dr_info_a = loop_vinfo->lookup_dr (dra);
+ dr_vec_info *dr_info_b = loop_vinfo->lookup_dr (drb);
+ stmt_vec_info stmtinfo_a = dr_info_a->stmt;
+ stmt_vec_info stmtinfo_b = dr_info_b->stmt;
lambda_vector dist_v;
unsigned int loop_depth;
@@ -350,32 +349,18 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
|| STMT_VINFO_GATHER_SCATTER_P (stmtinfo_b))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "versioning for alias not supported for: "
- "can't determine dependence between ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- DR_REF (dra));
- dump_printf (MSG_MISSED_OPTIMIZATION, " and ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- DR_REF (drb));
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "versioning for alias not supported for: "
+ "can't determine dependence between %T and %T\n",
+ DR_REF (dra), DR_REF (drb));
return true;
}
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "versioning for alias required: "
- "can't determine dependence between ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- DR_REF (dra));
- dump_printf (MSG_MISSED_OPTIMIZATION, " and ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- DR_REF (drb));
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "versioning for alias required: "
+ "can't determine dependence between %T and %T\n",
+ DR_REF (dra), DR_REF (drb));
/* Add to list of ddrs that need to be tested at run-time. */
return !vect_mark_for_runtime_alias_test (ddr, loop_vinfo);
@@ -398,30 +383,18 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
|| STMT_VINFO_GATHER_SCATTER_P (stmtinfo_b))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "versioning for alias not supported for: "
- "bad dist vector for ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- DR_REF (dra));
- dump_printf (MSG_MISSED_OPTIMIZATION, " and ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- DR_REF (drb));
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "versioning for alias not supported for: "
+ "bad dist vector for %T and %T\n",
+ DR_REF (dra), DR_REF (drb));
return true;
}
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "versioning for alias required: "
- "bad dist vector for ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, DR_REF (dra));
- dump_printf (MSG_MISSED_OPTIMIZATION, " and ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, DR_REF (drb));
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "versioning for alias required: "
+ "bad dist vector for %T and %T\n",
+ DR_REF (dra), DR_REF (drb));
/* Add to list of ddrs that need to be tested at run-time. */
return !vect_mark_for_runtime_alias_test (ddr, loop_vinfo);
}
@@ -444,14 +417,9 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
if (dist == 0)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "dependence distance == 0 between ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dra));
- dump_printf (MSG_NOTE, " and ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (drb));
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "dependence distance == 0 between %T and %T\n",
+ DR_REF (dra), DR_REF (drb));
/* When we perform grouped accesses and perform implicit CSE
by detecting equal accesses and doing disambiguation with
@@ -471,8 +439,7 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
... = a[i];
a[i+1] = ...;
where loads from the group interleave with the store. */
- if (!vect_preserves_scalar_order_p (vect_dr_stmt(dra),
- vect_dr_stmt (drb)))
+ if (!vect_preserves_scalar_order_p (dr_info_a, dr_info_b))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -537,15 +504,10 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
}
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized, possible dependence "
- "between data-refs ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dra));
- dump_printf (MSG_NOTE, " and ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (drb));
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized, possible dependence "
+ "between data-refs %T and %T\n",
+ DR_REF (dra), DR_REF (drb));
return true;
}
@@ -601,15 +563,18 @@ vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo,
/* Function vect_slp_analyze_data_ref_dependence.
Return TRUE if there (might) exist a dependence between a memory-reference
- DRA and a memory-reference DRB. When versioning for alias may check a
- dependence at run-time, return FALSE. Adjust *MAX_VF according to
- the data dependence. */
+ DRA and a memory-reference DRB for VINFO. When versioning for alias
+ may check a dependence at run-time, return FALSE. Adjust *MAX_VF
+ according to the data dependence. */
static bool
-vect_slp_analyze_data_ref_dependence (struct data_dependence_relation *ddr)
+vect_slp_analyze_data_ref_dependence (vec_info *vinfo,
+ struct data_dependence_relation *ddr)
{
struct data_reference *dra = DDR_A (ddr);
struct data_reference *drb = DDR_B (ddr);
+ dr_vec_info *dr_info_a = vinfo->lookup_dr (dra);
+ dr_vec_info *dr_info_b = vinfo->lookup_dr (drb);
/* We need to check dependences of statements marked as unvectorizable
as well, they still can prohibit vectorization. */
@@ -627,33 +592,23 @@ vect_slp_analyze_data_ref_dependence (struct data_dependence_relation *ddr)
/* If dra and drb are part of the same interleaving chain consider
them independent. */
- if (STMT_VINFO_GROUPED_ACCESS (vinfo_for_stmt (vect_dr_stmt (dra)))
- && (DR_GROUP_FIRST_ELEMENT (vinfo_for_stmt (vect_dr_stmt (dra)))
- == DR_GROUP_FIRST_ELEMENT (vinfo_for_stmt (vect_dr_stmt (drb)))))
+ if (STMT_VINFO_GROUPED_ACCESS (dr_info_a->stmt)
+ && (DR_GROUP_FIRST_ELEMENT (dr_info_a->stmt)
+ == DR_GROUP_FIRST_ELEMENT (dr_info_b->stmt)))
return false;
/* Unknown data dependence. */
if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "can't determine dependence between ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, DR_REF (dra));
- dump_printf (MSG_MISSED_OPTIMIZATION, " and ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, DR_REF (drb));
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "can't determine dependence between %T and %T\n",
+ DR_REF (dra), DR_REF (drb));
}
else if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "determined dependence between ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dra));
- dump_printf (MSG_NOTE, " and ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (drb));
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "determined dependence between %T and %T\n",
+ DR_REF (dra), DR_REF (drb));
return true;
}
@@ -665,22 +620,24 @@ vect_slp_analyze_data_ref_dependence (struct data_dependence_relation *ddr)
static bool
vect_slp_analyze_node_dependences (slp_instance instance, slp_tree node,
- vec<gimple *> stores, gimple *last_store)
+ vec<stmt_vec_info> stores,
+ stmt_vec_info last_store_info)
{
/* This walks over all stmts involved in the SLP load/store done
in NODE verifying we can sink them up to the last stmt in the
group. */
- gimple *last_access = vect_find_last_scalar_stmt_in_slp (node);
+ stmt_vec_info last_access_info = vect_find_last_scalar_stmt_in_slp (node);
+ vec_info *vinfo = last_access_info->vinfo;
for (unsigned k = 0; k < SLP_INSTANCE_GROUP_SIZE (instance); ++k)
{
- gimple *access = SLP_TREE_SCALAR_STMTS (node)[k];
- if (access == last_access)
+ stmt_vec_info access_info = SLP_TREE_SCALAR_STMTS (node)[k];
+ if (access_info == last_access_info)
continue;
- data_reference *dr_a = STMT_VINFO_DATA_REF (vinfo_for_stmt (access));
+ data_reference *dr_a = STMT_VINFO_DATA_REF (access_info);
ao_ref ref;
bool ref_initialized_p = false;
- for (gimple_stmt_iterator gsi = gsi_for_stmt (access);
- gsi_stmt (gsi) != last_access; gsi_next (&gsi))
+ for (gimple_stmt_iterator gsi = gsi_for_stmt (access_info->stmt);
+ gsi_stmt (gsi) != last_access_info->stmt; gsi_next (&gsi))
{
gimple *stmt = gsi_stmt (gsi);
if (! gimple_vuse (stmt)
@@ -689,7 +646,8 @@ vect_slp_analyze_node_dependences (slp_instance instance, slp_tree node,
/* If we couldn't record a (single) data reference for this
stmt we have to resort to the alias oracle. */
- data_reference *dr_b = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt));
+ stmt_vec_info stmt_info = vinfo->lookup_stmt (stmt);
+ data_reference *dr_b = STMT_VINFO_DATA_REF (stmt_info);
if (!dr_b)
{
/* We are moving a store or sinking a load - this means
@@ -709,17 +667,17 @@ vect_slp_analyze_node_dependences (slp_instance instance, slp_tree node,
been sunk to (and we verify if we can do that as well). */
if (gimple_visited_p (stmt))
{
- if (stmt != last_store)
+ if (stmt_info != last_store_info)
continue;
unsigned i;
- gimple *store;
- FOR_EACH_VEC_ELT (stores, i, store)
+ stmt_vec_info store_info;
+ FOR_EACH_VEC_ELT (stores, i, store_info)
{
- data_reference *store_dr
- = STMT_VINFO_DATA_REF (vinfo_for_stmt (store));
+ data_reference *store_dr = STMT_VINFO_DATA_REF (store_info);
ddr_p ddr = initialize_data_dependence_relation
(dr_a, store_dr, vNULL);
- dependent = vect_slp_analyze_data_ref_dependence (ddr);
+ dependent
+ = vect_slp_analyze_data_ref_dependence (vinfo, ddr);
free_dependence_relation (ddr);
if (dependent)
break;
@@ -729,7 +687,7 @@ vect_slp_analyze_node_dependences (slp_instance instance, slp_tree node,
{
ddr_p ddr = initialize_data_dependence_relation (dr_a,
dr_b, vNULL);
- dependent = vect_slp_analyze_data_ref_dependence (ddr);
+ dependent = vect_slp_analyze_data_ref_dependence (vinfo, ddr);
free_dependence_relation (ddr);
}
if (dependent)
@@ -753,20 +711,20 @@ vect_slp_analyze_instance_dependence (slp_instance instance)
/* The stores of this instance are at the root of the SLP tree. */
slp_tree store = SLP_INSTANCE_TREE (instance);
- if (! STMT_VINFO_DATA_REF (vinfo_for_stmt (SLP_TREE_SCALAR_STMTS (store)[0])))
+ if (! STMT_VINFO_DATA_REF (SLP_TREE_SCALAR_STMTS (store)[0]))
store = NULL;
/* Verify we can sink stores to the vectorized stmt insert location. */
- gimple *last_store = NULL;
+ stmt_vec_info last_store_info = NULL;
if (store)
{
if (! vect_slp_analyze_node_dependences (instance, store, vNULL, NULL))
return false;
/* Mark stores in this instance and remember the last one. */
- last_store = vect_find_last_scalar_stmt_in_slp (store);
+ last_store_info = vect_find_last_scalar_stmt_in_slp (store);
for (unsigned k = 0; k < SLP_INSTANCE_GROUP_SIZE (instance); ++k)
- gimple_set_visited (SLP_TREE_SCALAR_STMTS (store)[k], true);
+ gimple_set_visited (SLP_TREE_SCALAR_STMTS (store)[k]->stmt, true);
}
bool res = true;
@@ -779,7 +737,7 @@ vect_slp_analyze_instance_dependence (slp_instance instance)
if (! vect_slp_analyze_node_dependences (instance, load,
store
? SLP_TREE_SCALAR_STMTS (store)
- : vNULL, last_store))
+ : vNULL, last_store_info))
{
res = false;
break;
@@ -788,19 +746,19 @@ vect_slp_analyze_instance_dependence (slp_instance instance)
/* Unset the visited flag. */
if (store)
for (unsigned k = 0; k < SLP_INSTANCE_GROUP_SIZE (instance); ++k)
- gimple_set_visited (SLP_TREE_SCALAR_STMTS (store)[k], false);
+ gimple_set_visited (SLP_TREE_SCALAR_STMTS (store)[k]->stmt, false);
return res;
}
-/* Record in VINFO the base alignment guarantee given by DRB. STMT is
- the statement that contains DRB, which is useful for recording in the
- dump file. */
+/* Record the base alignment guarantee given by DRB, which occurs
+ in STMT_INFO. */
static void
-vect_record_base_alignment (vec_info *vinfo, gimple *stmt,
+vect_record_base_alignment (stmt_vec_info stmt_info,
innermost_loop_behavior *drb)
{
+ vec_info *vinfo = stmt_info->vinfo;
bool existed;
innermost_loop_behavior *&entry
= vinfo->base_alignments.get_or_insert (drb->base_address, &existed);
@@ -808,19 +766,15 @@ vect_record_base_alignment (vec_info *vinfo, gimple *stmt,
{
entry = drb;
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "recording new base alignment for ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, drb->base_address);
- dump_printf (MSG_NOTE, "\n");
- dump_printf_loc (MSG_NOTE, vect_location,
- " alignment: %d\n", drb->base_alignment);
- dump_printf_loc (MSG_NOTE, vect_location,
- " misalignment: %d\n", drb->base_misalignment);
- dump_printf_loc (MSG_NOTE, vect_location,
- " based on: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "recording new base alignment for %T\n"
+ " alignment: %d\n"
+ " misalignment: %d\n"
+ " based on: %G",
+ drb->base_address,
+ drb->base_alignment,
+ drb->base_misalignment,
+ stmt_info->stmt);
}
}
@@ -841,53 +795,50 @@ vect_record_base_alignments (vec_info *vinfo)
unsigned int i;
FOR_EACH_VEC_ELT (vinfo->shared->datarefs, i, dr)
{
- gimple *stmt = vect_dr_stmt (dr);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ dr_vec_info *dr_info = vinfo->lookup_dr (dr);
+ stmt_vec_info stmt_info = dr_info->stmt;
if (!DR_IS_CONDITIONAL_IN_STMT (dr)
&& STMT_VINFO_VECTORIZABLE (stmt_info)
&& !STMT_VINFO_GATHER_SCATTER_P (stmt_info))
{
- vect_record_base_alignment (vinfo, stmt, &DR_INNERMOST (dr));
+ vect_record_base_alignment (stmt_info, &DR_INNERMOST (dr));
/* If DR is nested in the loop that is being vectorized, we can also
record the alignment of the base wrt the outer loop. */
- if (loop && nested_in_vect_loop_p (loop, stmt))
+ if (loop && nested_in_vect_loop_p (loop, stmt_info))
vect_record_base_alignment
- (vinfo, stmt, &STMT_VINFO_DR_WRT_VEC_LOOP (stmt_info));
+ (stmt_info, &STMT_VINFO_DR_WRT_VEC_LOOP (stmt_info));
}
}
}
-/* Return the target alignment for the vectorized form of DR. */
+/* Return the target alignment for the vectorized form of DR_INFO. */
static unsigned int
-vect_calculate_target_alignment (struct data_reference *dr)
+vect_calculate_target_alignment (dr_vec_info *dr_info)
{
- gimple *stmt = vect_dr_stmt (dr);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
- tree vectype = STMT_VINFO_VECTYPE (stmt_info);
+ tree vectype = STMT_VINFO_VECTYPE (dr_info->stmt);
return targetm.vectorize.preferred_vector_alignment (vectype);
}
/* Function vect_compute_data_ref_alignment
- Compute the misalignment of the data reference DR.
+ Compute the misalignment of the data reference DR_INFO.
Output:
- 1. DR_MISALIGNMENT (DR) is defined.
+ 1. DR_MISALIGNMENT (DR_INFO) is defined.
FOR NOW: No analysis is actually performed. Misalignment is calculated
only for trivial cases. TODO. */
static void
-vect_compute_data_ref_alignment (struct data_reference *dr)
+vect_compute_data_ref_alignment (dr_vec_info *dr_info)
{
- gimple *stmt = vect_dr_stmt (dr);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ stmt_vec_info stmt_info = dr_info->stmt;
vec_base_alignments *base_alignments = &stmt_info->vinfo->base_alignments;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
struct loop *loop = NULL;
- tree ref = DR_REF (dr);
+ tree ref = DR_REF (dr_info->dr);
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
if (dump_enabled_p ())
@@ -898,17 +849,17 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
loop = LOOP_VINFO_LOOP (loop_vinfo);
/* Initialize misalignment to unknown. */
- SET_DR_MISALIGNMENT (dr, DR_MISALIGNMENT_UNKNOWN);
+ SET_DR_MISALIGNMENT (dr_info, DR_MISALIGNMENT_UNKNOWN);
if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
return;
- innermost_loop_behavior *drb = vect_dr_behavior (dr);
+ innermost_loop_behavior *drb = vect_dr_behavior (dr_info);
bool step_preserves_misalignment_p;
unsigned HOST_WIDE_INT vector_alignment
- = vect_calculate_target_alignment (dr) / BITS_PER_UNIT;
- DR_TARGET_ALIGNMENT (dr) = vector_alignment;
+ = vect_calculate_target_alignment (dr_info) / BITS_PER_UNIT;
+ DR_TARGET_ALIGNMENT (dr_info) = vector_alignment;
/* No step for BB vectorization. */
if (!loop)
@@ -923,10 +874,10 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
stays the same throughout the execution of the inner-loop, which is why
we have to check that the stride of the dataref in the inner-loop evenly
divides by the vector alignment. */
- else if (nested_in_vect_loop_p (loop, stmt))
+ else if (nested_in_vect_loop_p (loop, stmt_info))
{
step_preserves_misalignment_p
- = (DR_STEP_ALIGNMENT (dr) % vector_alignment) == 0;
+ = (DR_STEP_ALIGNMENT (dr_info->dr) % vector_alignment) == 0;
if (dump_enabled_p ())
{
@@ -948,7 +899,7 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
{
poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
step_preserves_misalignment_p
- = multiple_p (DR_STEP_ALIGNMENT (dr) * vf, vector_alignment);
+ = multiple_p (DR_STEP_ALIGNMENT (dr_info->dr) * vf, vector_alignment);
if (!step_preserves_misalignment_p && dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -974,12 +925,8 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
|| TREE_CODE (drb->step) != INTEGER_CST)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Unknown alignment for access: ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, ref);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Unknown alignment for access: %T\n", ref);
return;
}
@@ -992,12 +939,8 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
vector_alignment * BITS_PER_UNIT))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "can't force alignment of ref: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, ref);
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "can't force alignment of ref: %T\n", ref);
return;
}
@@ -1005,14 +948,11 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
NOTE: This is the only change to the code we make during
the analysis phase, before deciding to vectorize the loop. */
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "force alignment of ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, ref);
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "force alignment of %T\n", ref);
- DR_VECT_AUX (dr)->base_decl = base;
- DR_VECT_AUX (dr)->base_misaligned = true;
+ dr_info->base_decl = base;
+ dr_info->base_misaligned = true;
base_misalignment = 0;
}
poly_int64 misalignment
@@ -1031,107 +971,100 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
&const_misalignment))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Non-constant misalignment for access: ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, ref);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Non-constant misalignment for access: %T\n", ref);
return;
}
- SET_DR_MISALIGNMENT (dr, const_misalignment);
+ SET_DR_MISALIGNMENT (dr_info, const_misalignment);
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "misalign = %d bytes of ref ", DR_MISALIGNMENT (dr));
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, ref);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "misalign = %d bytes of ref %T\n",
+ DR_MISALIGNMENT (dr_info), ref);
return;
}
/* Function vect_update_misalignment_for_peel.
- Sets DR's misalignment
- - to 0 if it has the same alignment as DR_PEEL,
- - to the misalignment computed using NPEEL if DR's salignment is known,
+ Sets DR_INFO's misalignment
+ - to 0 if it has the same alignment as DR_PEEL_INFO,
+ - to the misalignment computed using NPEEL if DR_INFO's salignment is known,
- to -1 (unknown) otherwise.
- DR - the data reference whose misalignment is to be adjusted.
- DR_PEEL - the data reference whose misalignment is being made
- zero in the vector loop by the peel.
+ DR_INFO - the data reference whose misalignment is to be adjusted.
+ DR_PEEL_INFO - the data reference whose misalignment is being made
+ zero in the vector loop by the peel.
NPEEL - the number of iterations in the peel loop if the misalignment
- of DR_PEEL is known at compile time. */
+ of DR_PEEL_INFO is known at compile time. */
static void
-vect_update_misalignment_for_peel (struct data_reference *dr,
- struct data_reference *dr_peel, int npeel)
+vect_update_misalignment_for_peel (dr_vec_info *dr_info,
+ dr_vec_info *dr_peel_info, int npeel)
{
unsigned int i;
vec<dr_p> same_aligned_drs;
struct data_reference *current_dr;
- int dr_size = vect_get_scalar_dr_size (dr);
- int dr_peel_size = vect_get_scalar_dr_size (dr_peel);
- stmt_vec_info stmt_info = vinfo_for_stmt (vect_dr_stmt (dr));
- stmt_vec_info peel_stmt_info = vinfo_for_stmt (vect_dr_stmt (dr_peel));
+ int dr_size = vect_get_scalar_dr_size (dr_info);
+ int dr_peel_size = vect_get_scalar_dr_size (dr_peel_info);
+ stmt_vec_info stmt_info = dr_info->stmt;
+ stmt_vec_info peel_stmt_info = dr_peel_info->stmt;
/* For interleaved data accesses the step in the loop must be multiplied by
the size of the interleaving group. */
if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
- dr_size *= DR_GROUP_SIZE (vinfo_for_stmt (DR_GROUP_FIRST_ELEMENT (stmt_info)));
+ dr_size *= DR_GROUP_SIZE (DR_GROUP_FIRST_ELEMENT (stmt_info));
if (STMT_VINFO_GROUPED_ACCESS (peel_stmt_info))
dr_peel_size *= DR_GROUP_SIZE (peel_stmt_info);
/* It can be assumed that the data refs with the same alignment as dr_peel
are aligned in the vector loop. */
- same_aligned_drs
- = STMT_VINFO_SAME_ALIGN_REFS (vinfo_for_stmt (vect_dr_stmt (dr_peel)));
+ same_aligned_drs = STMT_VINFO_SAME_ALIGN_REFS (peel_stmt_info);
FOR_EACH_VEC_ELT (same_aligned_drs, i, current_dr)
{
- if (current_dr != dr)
+ if (current_dr != dr_info->dr)
continue;
- gcc_assert (!known_alignment_for_access_p (dr)
- || !known_alignment_for_access_p (dr_peel)
- || (DR_MISALIGNMENT (dr) / dr_size
- == DR_MISALIGNMENT (dr_peel) / dr_peel_size));
- SET_DR_MISALIGNMENT (dr, 0);
+ gcc_assert (!known_alignment_for_access_p (dr_info)
+ || !known_alignment_for_access_p (dr_peel_info)
+ || (DR_MISALIGNMENT (dr_info) / dr_size
+ == DR_MISALIGNMENT (dr_peel_info) / dr_peel_size));
+ SET_DR_MISALIGNMENT (dr_info, 0);
return;
}
- if (known_alignment_for_access_p (dr)
- && known_alignment_for_access_p (dr_peel))
+ if (known_alignment_for_access_p (dr_info)
+ && known_alignment_for_access_p (dr_peel_info))
{
- bool negative = tree_int_cst_compare (DR_STEP (dr), size_zero_node) < 0;
- int misal = DR_MISALIGNMENT (dr);
+ bool negative = tree_int_cst_compare (DR_STEP (dr_info->dr),
+ size_zero_node) < 0;
+ int misal = DR_MISALIGNMENT (dr_info);
misal += negative ? -npeel * dr_size : npeel * dr_size;
- misal &= DR_TARGET_ALIGNMENT (dr) - 1;
- SET_DR_MISALIGNMENT (dr, misal);
+ misal &= DR_TARGET_ALIGNMENT (dr_info) - 1;
+ SET_DR_MISALIGNMENT (dr_info, misal);
return;
}
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location, "Setting misalignment " \
"to unknown (-1).\n");
- SET_DR_MISALIGNMENT (dr, DR_MISALIGNMENT_UNKNOWN);
+ SET_DR_MISALIGNMENT (dr_info, DR_MISALIGNMENT_UNKNOWN);
}
/* Function verify_data_ref_alignment
- Return TRUE if DR can be handled with respect to alignment. */
+ Return TRUE if DR_INFO can be handled with respect to alignment. */
static bool
-verify_data_ref_alignment (data_reference_p dr)
+verify_data_ref_alignment (dr_vec_info *dr_info)
{
enum dr_alignment_support supportable_dr_alignment
- = vect_supportable_dr_alignment (dr, false);
+ = vect_supportable_dr_alignment (dr_info, false);
if (!supportable_dr_alignment)
{
if (dump_enabled_p ())
{
- if (DR_IS_READ (dr))
+ if (DR_IS_READ (dr_info->dr))
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"not vectorized: unsupported unaligned load.");
else
@@ -1139,9 +1072,7 @@ verify_data_ref_alignment (data_reference_p dr)
"not vectorized: unsupported unaligned "
"store.");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- DR_REF (dr));
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
+ dump_printf (MSG_MISSED_OPTIMIZATION, "%T\n", DR_REF (dr_info->dr));
}
return false;
}
@@ -1167,15 +1098,15 @@ vect_verify_datarefs_alignment (loop_vec_info vinfo)
FOR_EACH_VEC_ELT (datarefs, i, dr)
{
- gimple *stmt = vect_dr_stmt (dr);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ dr_vec_info *dr_info = vinfo->lookup_dr (dr);
+ stmt_vec_info stmt_info = dr_info->stmt;
if (!STMT_VINFO_RELEVANT_P (stmt_info))
continue;
/* For interleaving, only the alignment of the first access matters. */
if (STMT_VINFO_GROUPED_ACCESS (stmt_info)
- && DR_GROUP_FIRST_ELEMENT (stmt_info) != stmt)
+ && DR_GROUP_FIRST_ELEMENT (stmt_info) != stmt_info)
continue;
/* Strided accesses perform only component accesses, alignment is
@@ -1184,7 +1115,7 @@ vect_verify_datarefs_alignment (loop_vec_info vinfo)
&& !STMT_VINFO_GROUPED_ACCESS (stmt_info))
continue;
- if (! verify_data_ref_alignment (dr))
+ if (! verify_data_ref_alignment (dr_info))
return false;
}
@@ -1206,14 +1137,13 @@ not_size_aligned (tree exp)
/* Function vector_alignment_reachable_p
- Return true if vector alignment for DR is reachable by peeling
+ Return true if vector alignment for DR_INFO is reachable by peeling
a few loop iterations. Return false otherwise. */
static bool
-vector_alignment_reachable_p (struct data_reference *dr)
+vector_alignment_reachable_p (dr_vec_info *dr_info)
{
- gimple *stmt = vect_dr_stmt (dr);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ stmt_vec_info stmt_info = dr_info->stmt;
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
@@ -1224,13 +1154,13 @@ vector_alignment_reachable_p (struct data_reference *dr)
int elem_size, mis_in_elements;
/* FORNOW: handle only known alignment. */
- if (!known_alignment_for_access_p (dr))
+ if (!known_alignment_for_access_p (dr_info))
return false;
poly_uint64 nelements = TYPE_VECTOR_SUBPARTS (vectype);
poly_uint64 vector_size = GET_MODE_SIZE (TYPE_MODE (vectype));
elem_size = vector_element_size (vector_size, nelements);
- mis_in_elements = DR_MISALIGNMENT (dr) / elem_size;
+ mis_in_elements = DR_MISALIGNMENT (dr_info) / elem_size;
if (!multiple_p (nelements - mis_in_elements, DR_GROUP_SIZE (stmt_info)))
return false;
@@ -1238,18 +1168,17 @@ vector_alignment_reachable_p (struct data_reference *dr)
/* If misalignment is known at the compile time then allow peeling
only if natural alignment is reachable through peeling. */
- if (known_alignment_for_access_p (dr) && !aligned_access_p (dr))
+ if (known_alignment_for_access_p (dr_info) && !aligned_access_p (dr_info))
{
HOST_WIDE_INT elmsize =
int_cst_value (TYPE_SIZE_UNIT (TREE_TYPE (vectype)));
if (dump_enabled_p ())
{
dump_printf_loc (MSG_NOTE, vect_location,
- "data size =" HOST_WIDE_INT_PRINT_DEC, elmsize);
- dump_printf (MSG_NOTE,
- ". misalignment = %d.\n", DR_MISALIGNMENT (dr));
+ "data size = %wd. misalignment = %d.\n", elmsize,
+ DR_MISALIGNMENT (dr_info));
}
- if (DR_MISALIGNMENT (dr) % elmsize)
+ if (DR_MISALIGNMENT (dr_info) % elmsize)
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -1258,10 +1187,10 @@ vector_alignment_reachable_p (struct data_reference *dr)
}
}
- if (!known_alignment_for_access_p (dr))
+ if (!known_alignment_for_access_p (dr_info))
{
- tree type = TREE_TYPE (DR_REF (dr));
- bool is_packed = not_size_aligned (DR_REF (dr));
+ tree type = TREE_TYPE (DR_REF (dr_info->dr));
+ bool is_packed = not_size_aligned (DR_REF (dr_info->dr));
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"Unknown misalignment, %snaturally aligned\n",
@@ -1273,17 +1202,16 @@ vector_alignment_reachable_p (struct data_reference *dr)
}
-/* Calculate the cost of the memory access represented by DR. */
+/* Calculate the cost of the memory access represented by DR_INFO. */
static void
-vect_get_data_access_cost (struct data_reference *dr,
+vect_get_data_access_cost (dr_vec_info *dr_info,
unsigned int *inside_cost,
unsigned int *outside_cost,
stmt_vector_for_cost *body_cost_vec,
stmt_vector_for_cost *prologue_cost_vec)
{
- gimple *stmt = vect_dr_stmt (dr);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ stmt_vec_info stmt_info = dr_info->stmt;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
int ncopies;
@@ -1292,7 +1220,7 @@ vect_get_data_access_cost (struct data_reference *dr,
else
ncopies = vect_get_num_copies (loop_vinfo, STMT_VINFO_VECTYPE (stmt_info));
- if (DR_IS_READ (dr))
+ if (DR_IS_READ (dr_info->dr))
vect_get_load_cost (stmt_info, ncopies, true, inside_cost, outside_cost,
prologue_cost_vec, body_cost_vec, false);
else
@@ -1307,7 +1235,7 @@ vect_get_data_access_cost (struct data_reference *dr,
typedef struct _vect_peel_info
{
- struct data_reference *dr;
+ dr_vec_info *dr_info;
int npeel;
unsigned int count;
} *vect_peel_info;
@@ -1341,16 +1269,17 @@ peel_info_hasher::equal (const _vect_peel_info *a, const _vect_peel_info *b)
}
-/* Insert DR into peeling hash table with NPEEL as key. */
+/* Insert DR_INFO into peeling hash table with NPEEL as key. */
static void
vect_peeling_hash_insert (hash_table<peel_info_hasher> *peeling_htab,
- loop_vec_info loop_vinfo, struct data_reference *dr,
+ loop_vec_info loop_vinfo, dr_vec_info *dr_info,
int npeel)
{
struct _vect_peel_info elem, *slot;
_vect_peel_info **new_slot;
- bool supportable_dr_alignment = vect_supportable_dr_alignment (dr, true);
+ bool supportable_dr_alignment
+ = vect_supportable_dr_alignment (dr_info, true);
elem.npeel = npeel;
slot = peeling_htab->find (&elem);
@@ -1360,7 +1289,7 @@ vect_peeling_hash_insert (hash_table<peel_info_hasher> *peeling_htab,
{
slot = XNEW (struct _vect_peel_info);
slot->npeel = npeel;
- slot->dr = dr;
+ slot->dr_info = dr_info;
slot->count = 1;
new_slot = peeling_htab->find_slot (slot, INSERT);
*new_slot = slot;
@@ -1387,19 +1316,19 @@ vect_peeling_hash_get_most_frequent (_vect_peel_info **slot,
{
max->peel_info.npeel = elem->npeel;
max->peel_info.count = elem->count;
- max->peel_info.dr = elem->dr;
+ max->peel_info.dr_info = elem->dr_info;
}
return 1;
}
-/* Get the costs of peeling NPEEL iterations checking data access costs
- for all data refs. If UNKNOWN_MISALIGNMENT is true, we assume DR0's
- misalignment will be zero after peeling. */
+/* Get the costs of peeling NPEEL iterations for LOOP_VINFO, checking
+ data access costs for all data refs. If UNKNOWN_MISALIGNMENT is true,
+ we assume DR0_INFO's misalignment will be zero after peeling. */
static void
-vect_get_peeling_costs_all_drs (vec<data_reference_p> datarefs,
- struct data_reference *dr0,
+vect_get_peeling_costs_all_drs (loop_vec_info loop_vinfo,
+ dr_vec_info *dr0_info,
unsigned int *inside_cost,
unsigned int *outside_cost,
stmt_vector_for_cost *body_cost_vec,
@@ -1407,21 +1336,22 @@ vect_get_peeling_costs_all_drs (vec<data_reference_p> datarefs,
unsigned int npeel,
bool unknown_misalignment)
{
+ vec<data_reference_p> datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
unsigned i;
data_reference *dr;
FOR_EACH_VEC_ELT (datarefs, i, dr)
{
- gimple *stmt = vect_dr_stmt (dr);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ dr_vec_info *dr_info = loop_vinfo->lookup_dr (dr);
+ stmt_vec_info stmt_info = dr_info->stmt;
if (!STMT_VINFO_RELEVANT_P (stmt_info))
continue;
/* For interleaving, only the alignment of the first access
matters. */
if (STMT_VINFO_GROUPED_ACCESS (stmt_info)
- && DR_GROUP_FIRST_ELEMENT (stmt_info) != stmt)
- continue;
+ && DR_GROUP_FIRST_ELEMENT (stmt_info) != stmt_info)
+ continue;
/* Strided accesses perform only component accesses, alignment is
irrelevant for them. */
@@ -1430,16 +1360,16 @@ vect_get_peeling_costs_all_drs (vec<data_reference_p> datarefs,
continue;
int save_misalignment;
- save_misalignment = DR_MISALIGNMENT (dr);
+ save_misalignment = DR_MISALIGNMENT (dr_info);
if (npeel == 0)
;
- else if (unknown_misalignment && dr == dr0)
- SET_DR_MISALIGNMENT (dr, 0);
+ else if (unknown_misalignment && dr_info == dr0_info)
+ SET_DR_MISALIGNMENT (dr_info, 0);
else
- vect_update_misalignment_for_peel (dr, dr0, npeel);
- vect_get_data_access_cost (dr, inside_cost, outside_cost,
+ vect_update_misalignment_for_peel (dr_info, dr0_info, npeel);
+ vect_get_data_access_cost (dr_info, inside_cost, outside_cost,
body_cost_vec, prologue_cost_vec);
- SET_DR_MISALIGNMENT (dr, save_misalignment);
+ SET_DR_MISALIGNMENT (dr_info, save_misalignment);
}
}
@@ -1453,8 +1383,7 @@ vect_peeling_hash_get_lowest_cost (_vect_peel_info **slot,
vect_peel_info elem = *slot;
int dummy;
unsigned int inside_cost = 0, outside_cost = 0;
- gimple *stmt = vect_dr_stmt (elem->dr);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ stmt_vec_info stmt_info = elem->dr_info->stmt;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
stmt_vector_for_cost prologue_cost_vec, body_cost_vec,
epilogue_cost_vec;
@@ -1463,10 +1392,9 @@ vect_peeling_hash_get_lowest_cost (_vect_peel_info **slot,
body_cost_vec.create (2);
epilogue_cost_vec.create (2);
- vect_get_peeling_costs_all_drs (LOOP_VINFO_DATAREFS (loop_vinfo),
- elem->dr, &inside_cost, &outside_cost,
- &body_cost_vec, &prologue_cost_vec,
- elem->npeel, false);
+ vect_get_peeling_costs_all_drs (loop_vinfo, elem->dr_info, &inside_cost,
+ &outside_cost, &body_cost_vec,
+ &prologue_cost_vec, elem->npeel, false);
body_cost_vec.release ();
@@ -1488,7 +1416,7 @@ vect_peeling_hash_get_lowest_cost (_vect_peel_info **slot,
{
min->inside_cost = inside_cost;
min->outside_cost = outside_cost;
- min->peel_info.dr = elem->dr;
+ min->peel_info.dr_info = elem->dr_info;
min->peel_info.npeel = elem->npeel;
min->peel_info.count = elem->count;
}
@@ -1507,7 +1435,7 @@ vect_peeling_hash_choose_best_peeling (hash_table<peel_info_hasher> *peeling_hta
{
struct _vect_peel_extended_info res;
- res.peel_info.dr = NULL;
+ res.peel_info.dr_info = NULL;
if (!unlimited_cost_model (LOOP_VINFO_LOOP (loop_vinfo)))
{
@@ -1531,14 +1459,12 @@ vect_peeling_hash_choose_best_peeling (hash_table<peel_info_hasher> *peeling_hta
/* Return true if the new peeling NPEEL is supported. */
static bool
-vect_peeling_supportable (loop_vec_info loop_vinfo, struct data_reference *dr0,
+vect_peeling_supportable (loop_vec_info loop_vinfo, dr_vec_info *dr0_info,
unsigned npeel)
{
unsigned i;
struct data_reference *dr = NULL;
vec<data_reference_p> datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
- gimple *stmt;
- stmt_vec_info stmt_info;
enum dr_alignment_support supportable_dr_alignment;
/* Ensure that all data refs can be vectorized after the peel. */
@@ -1546,15 +1472,15 @@ vect_peeling_supportable (loop_vec_info loop_vinfo, struct data_reference *dr0,
{
int save_misalignment;
- if (dr == dr0)
+ if (dr == dr0_info->dr)
continue;
- stmt = vect_dr_stmt (dr);
- stmt_info = vinfo_for_stmt (stmt);
+ dr_vec_info *dr_info = loop_vinfo->lookup_dr (dr);
+ stmt_vec_info stmt_info = dr_info->stmt;
/* For interleaving, only the alignment of the first access
matters. */
if (STMT_VINFO_GROUPED_ACCESS (stmt_info)
- && DR_GROUP_FIRST_ELEMENT (stmt_info) != stmt)
+ && DR_GROUP_FIRST_ELEMENT (stmt_info) != stmt_info)
continue;
/* Strided accesses perform only component accesses, alignment is
@@ -1563,10 +1489,11 @@ vect_peeling_supportable (loop_vec_info loop_vinfo, struct data_reference *dr0,
&& !STMT_VINFO_GROUPED_ACCESS (stmt_info))
continue;
- save_misalignment = DR_MISALIGNMENT (dr);
- vect_update_misalignment_for_peel (dr, dr0, npeel);
- supportable_dr_alignment = vect_supportable_dr_alignment (dr, false);
- SET_DR_MISALIGNMENT (dr, save_misalignment);
+ save_misalignment = DR_MISALIGNMENT (dr_info);
+ vect_update_misalignment_for_peel (dr_info, dr0_info, npeel);
+ supportable_dr_alignment
+ = vect_supportable_dr_alignment (dr_info, false);
+ SET_DR_MISALIGNMENT (dr_info, save_misalignment);
if (!supportable_dr_alignment)
return false;
@@ -1672,19 +1599,18 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
vec<data_reference_p> datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
enum dr_alignment_support supportable_dr_alignment;
- struct data_reference *dr0 = NULL, *first_store = NULL;
+ dr_vec_info *first_store = NULL;
+ dr_vec_info *dr0_info = NULL;
struct data_reference *dr;
unsigned int i, j;
bool do_peeling = false;
bool do_versioning = false;
bool stat;
- gimple *stmt;
- stmt_vec_info stmt_info;
unsigned int npeel = 0;
bool one_misalignment_known = false;
bool one_misalignment_unknown = false;
bool one_dr_unsupportable = false;
- struct data_reference *unsupportable_dr = NULL;
+ dr_vec_info *unsupportable_dr_info = NULL;
poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
unsigned possible_npeel_number = 1;
tree vectype;
@@ -1731,8 +1657,8 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
FOR_EACH_VEC_ELT (datarefs, i, dr)
{
- stmt = vect_dr_stmt (dr);
- stmt_info = vinfo_for_stmt (stmt);
+ dr_vec_info *dr_info = loop_vinfo->lookup_dr (dr);
+ stmt_vec_info stmt_info = dr_info->stmt;
if (!STMT_VINFO_RELEVANT_P (stmt_info))
continue;
@@ -1740,8 +1666,8 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
/* For interleaving, only the alignment of the first access
matters. */
if (STMT_VINFO_GROUPED_ACCESS (stmt_info)
- && DR_GROUP_FIRST_ELEMENT (stmt_info) != stmt)
- continue;
+ && DR_GROUP_FIRST_ELEMENT (stmt_info) != stmt_info)
+ continue;
/* For scatter-gather or invariant accesses there is nothing
to enhance. */
@@ -1755,21 +1681,23 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
&& !STMT_VINFO_GROUPED_ACCESS (stmt_info))
continue;
- supportable_dr_alignment = vect_supportable_dr_alignment (dr, true);
- do_peeling = vector_alignment_reachable_p (dr);
+ supportable_dr_alignment = vect_supportable_dr_alignment (dr_info, true);
+ do_peeling = vector_alignment_reachable_p (dr_info);
if (do_peeling)
{
- if (known_alignment_for_access_p (dr))
+ if (known_alignment_for_access_p (dr_info))
{
unsigned int npeel_tmp = 0;
bool negative = tree_int_cst_compare (DR_STEP (dr),
size_zero_node) < 0;
vectype = STMT_VINFO_VECTYPE (stmt_info);
- unsigned int target_align = DR_TARGET_ALIGNMENT (dr);
- unsigned int dr_size = vect_get_scalar_dr_size (dr);
- mis = (negative ? DR_MISALIGNMENT (dr) : -DR_MISALIGNMENT (dr));
- if (DR_MISALIGNMENT (dr) != 0)
+ unsigned int target_align = DR_TARGET_ALIGNMENT (dr_info);
+ unsigned int dr_size = vect_get_scalar_dr_size (dr_info);
+ mis = (negative
+ ? DR_MISALIGNMENT (dr_info)
+ : -DR_MISALIGNMENT (dr_info));
+ if (DR_MISALIGNMENT (dr_info) != 0)
npeel_tmp = (mis & (target_align - 1)) / dr_size;
/* For multiple types, it is possible that the bigger type access
@@ -1794,7 +1722,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
/* NPEEL_TMP is 0 when there is no misalignment, but also
allow peeling NELEMENTS. */
- if (DR_MISALIGNMENT (dr) == 0)
+ if (DR_MISALIGNMENT (dr_info) == 0)
possible_npeel_number++;
}
@@ -1803,7 +1731,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
for (j = 0; j < possible_npeel_number; j++)
{
vect_peeling_hash_insert (&peeling_htab, loop_vinfo,
- dr, npeel_tmp);
+ dr_info, npeel_tmp);
npeel_tmp += target_align / dr_size;
}
@@ -1817,11 +1745,11 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
stores over load. */
unsigned same_align_drs
= STMT_VINFO_SAME_ALIGN_REFS (stmt_info).length ();
- if (!dr0
+ if (!dr0_info
|| same_align_drs_max < same_align_drs)
{
same_align_drs_max = same_align_drs;
- dr0 = dr;
+ dr0_info = dr_info;
}
/* For data-refs with the same number of related
accesses prefer the one where the misalign
@@ -1830,13 +1758,13 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
{
struct loop *ivloop0, *ivloop;
ivloop0 = outermost_invariant_loop_for_expr
- (loop, DR_BASE_ADDRESS (dr0));
+ (loop, DR_BASE_ADDRESS (dr0_info->dr));
ivloop = outermost_invariant_loop_for_expr
(loop, DR_BASE_ADDRESS (dr));
if ((ivloop && !ivloop0)
|| (ivloop && ivloop0
&& flow_loop_nested_p (ivloop, ivloop0)))
- dr0 = dr;
+ dr0_info = dr_info;
}
one_misalignment_unknown = true;
@@ -1846,16 +1774,16 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
if (!supportable_dr_alignment)
{
one_dr_unsupportable = true;
- unsupportable_dr = dr;
+ unsupportable_dr_info = dr_info;
}
if (!first_store && DR_IS_WRITE (dr))
- first_store = dr;
+ first_store = dr_info;
}
}
else
{
- if (!aligned_access_p (dr))
+ if (!aligned_access_p (dr_info))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -1893,7 +1821,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
stmt_vector_for_cost dummy;
dummy.create (2);
- vect_get_peeling_costs_all_drs (datarefs, dr0,
+ vect_get_peeling_costs_all_drs (loop_vinfo, dr0_info,
&load_inside_cost,
&load_outside_cost,
&dummy, &dummy, estimated_npeels, true);
@@ -1902,7 +1830,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
if (first_store)
{
dummy.create (2);
- vect_get_peeling_costs_all_drs (datarefs, first_store,
+ vect_get_peeling_costs_all_drs (loop_vinfo, first_store,
&store_inside_cost,
&store_outside_cost,
&dummy, &dummy,
@@ -1919,7 +1847,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
|| (load_inside_cost == store_inside_cost
&& load_outside_cost > store_outside_cost))
{
- dr0 = first_store;
+ dr0_info = first_store;
peel_for_unknown_alignment.inside_cost = store_inside_cost;
peel_for_unknown_alignment.outside_cost = store_outside_cost;
}
@@ -1943,19 +1871,18 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
epilogue_cost_vec.release ();
peel_for_unknown_alignment.peel_info.count = 1
- + STMT_VINFO_SAME_ALIGN_REFS
- (vinfo_for_stmt (vect_dr_stmt (dr0))).length ();
+ + STMT_VINFO_SAME_ALIGN_REFS (dr0_info->stmt).length ();
}
peel_for_unknown_alignment.peel_info.npeel = 0;
- peel_for_unknown_alignment.peel_info.dr = dr0;
+ peel_for_unknown_alignment.peel_info.dr_info = dr0_info;
best_peel = peel_for_unknown_alignment;
peel_for_known_alignment.inside_cost = INT_MAX;
peel_for_known_alignment.outside_cost = INT_MAX;
peel_for_known_alignment.peel_info.count = 0;
- peel_for_known_alignment.peel_info.dr = NULL;
+ peel_for_known_alignment.peel_info.dr_info = NULL;
if (do_peeling && one_misalignment_known)
{
@@ -1967,7 +1894,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
}
/* Compare costs of peeling for known and unknown alignment. */
- if (peel_for_known_alignment.peel_info.dr != NULL
+ if (peel_for_known_alignment.peel_info.dr_info != NULL
&& peel_for_unknown_alignment.inside_cost
>= peel_for_known_alignment.inside_cost)
{
@@ -1984,7 +1911,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
since we'd have to discard a chosen peeling except when it accidentally
aligned the unsupportable data ref. */
if (one_dr_unsupportable)
- dr0 = unsupportable_dr;
+ dr0_info = unsupportable_dr_info;
else if (do_peeling)
{
/* Calculate the penalty for no peeling, i.e. leaving everything as-is.
@@ -1994,7 +1921,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
stmt_vector_for_cost dummy;
dummy.create (2);
- vect_get_peeling_costs_all_drs (datarefs, NULL, &nopeel_inside_cost,
+ vect_get_peeling_costs_all_drs (loop_vinfo, NULL, &nopeel_inside_cost,
&nopeel_outside_cost, &dummy, &dummy,
0, false);
dummy.release ();
@@ -2015,7 +1942,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
epilogue_cost_vec.release ();
npeel = best_peel.peel_info.npeel;
- dr0 = best_peel.peel_info.dr;
+ dr0_info = best_peel.peel_info.dr_info;
/* If no peeling is not more expensive than the best peeling we
have so far, don't perform any peeling. */
@@ -2025,13 +1952,12 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
if (do_peeling)
{
- stmt = vect_dr_stmt (dr0);
- stmt_info = vinfo_for_stmt (stmt);
+ stmt_vec_info stmt_info = dr0_info->stmt;
vectype = STMT_VINFO_VECTYPE (stmt_info);
- if (known_alignment_for_access_p (dr0))
+ if (known_alignment_for_access_p (dr0_info))
{
- bool negative = tree_int_cst_compare (DR_STEP (dr0),
+ bool negative = tree_int_cst_compare (DR_STEP (dr0_info->dr),
size_zero_node) < 0;
if (!npeel)
{
@@ -2040,16 +1966,17 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
updating DR_MISALIGNMENT values. The peeling factor is the
vectorization factor minus the misalignment as an element
count. */
- mis = negative ? DR_MISALIGNMENT (dr0) : -DR_MISALIGNMENT (dr0);
- unsigned int target_align = DR_TARGET_ALIGNMENT (dr0);
+ mis = (negative
+ ? DR_MISALIGNMENT (dr0_info)
+ : -DR_MISALIGNMENT (dr0_info));
+ unsigned int target_align = DR_TARGET_ALIGNMENT (dr0_info);
npeel = ((mis & (target_align - 1))
- / vect_get_scalar_dr_size (dr0));
+ / vect_get_scalar_dr_size (dr0_info));
}
/* For interleaved data access every iteration accesses all the
members of the group, therefore we divide the number of iterations
by the group size. */
- stmt_info = vinfo_for_stmt (vect_dr_stmt (dr0));
if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
npeel /= DR_GROUP_SIZE (stmt_info);
@@ -2059,11 +1986,11 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
}
/* Ensure that all datarefs can be vectorized after the peel. */
- if (!vect_peeling_supportable (loop_vinfo, dr0, npeel))
+ if (!vect_peeling_supportable (loop_vinfo, dr0_info, npeel))
do_peeling = false;
/* Check if all datarefs are supportable and log. */
- if (do_peeling && known_alignment_for_access_p (dr0) && npeel == 0)
+ if (do_peeling && known_alignment_for_access_p (dr0_info) && npeel == 0)
{
stat = vect_verify_datarefs_alignment (loop_vinfo);
if (!stat)
@@ -2082,8 +2009,9 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
unsigned max_peel = npeel;
if (max_peel == 0)
{
- unsigned int target_align = DR_TARGET_ALIGNMENT (dr0);
- max_peel = target_align / vect_get_scalar_dr_size (dr0) - 1;
+ unsigned int target_align = DR_TARGET_ALIGNMENT (dr0_info);
+ max_peel = (target_align
+ / vect_get_scalar_dr_size (dr0_info) - 1);
}
if (max_peel > max_allowed_peel)
{
@@ -2119,25 +2047,26 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
vectorization factor times the size). Otherwise, the
misalignment of DR_i must be set to unknown. */
FOR_EACH_VEC_ELT (datarefs, i, dr)
- if (dr != dr0)
+ if (dr != dr0_info->dr)
{
/* Strided accesses perform only component accesses, alignment
is irrelevant for them. */
- stmt_info = vinfo_for_stmt (vect_dr_stmt (dr));
+ dr_vec_info *dr_info = loop_vinfo->lookup_dr (dr);
+ stmt_info = dr_info->stmt;
if (STMT_VINFO_STRIDED_P (stmt_info)
&& !STMT_VINFO_GROUPED_ACCESS (stmt_info))
continue;
- vect_update_misalignment_for_peel (dr, dr0, npeel);
+ vect_update_misalignment_for_peel (dr_info, dr0_info, npeel);
}
- LOOP_VINFO_UNALIGNED_DR (loop_vinfo) = dr0;
+ LOOP_VINFO_UNALIGNED_DR (loop_vinfo) = dr0_info;
if (npeel)
LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) = npeel;
else
LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo)
- = DR_MISALIGNMENT (dr0);
- SET_DR_MISALIGNMENT (dr0, 0);
+ = DR_MISALIGNMENT (dr0_info);
+ SET_DR_MISALIGNMENT (dr0_info, 0);
if (dump_enabled_p ())
{
dump_printf_loc (MSG_NOTE, vect_location,
@@ -2172,14 +2101,14 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
{
FOR_EACH_VEC_ELT (datarefs, i, dr)
{
- stmt = vect_dr_stmt (dr);
- stmt_info = vinfo_for_stmt (stmt);
+ dr_vec_info *dr_info = loop_vinfo->lookup_dr (dr);
+ stmt_vec_info stmt_info = dr_info->stmt;
/* For interleaving, only the alignment of the first access
matters. */
- if (aligned_access_p (dr)
+ if (aligned_access_p (dr_info)
|| (STMT_VINFO_GROUPED_ACCESS (stmt_info)
- && DR_GROUP_FIRST_ELEMENT (stmt_info) != stmt))
+ && DR_GROUP_FIRST_ELEMENT (stmt_info) != stmt_info))
continue;
if (STMT_VINFO_STRIDED_P (stmt_info))
@@ -2192,15 +2121,15 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
break;
}
- supportable_dr_alignment = vect_supportable_dr_alignment (dr, false);
+ supportable_dr_alignment
+ = vect_supportable_dr_alignment (dr_info, false);
if (!supportable_dr_alignment)
{
- gimple *stmt;
int mask;
tree vectype;
- if (known_alignment_for_access_p (dr)
+ if (known_alignment_for_access_p (dr_info)
|| LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo).length ()
>= (unsigned) PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS))
{
@@ -2208,9 +2137,8 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
break;
}
- stmt = vect_dr_stmt (dr);
- vectype = STMT_VINFO_VECTYPE (vinfo_for_stmt (stmt));
- gcc_assert (vectype);
+ vectype = STMT_VINFO_VECTYPE (stmt_info);
+ gcc_assert (vectype);
/* At present we don't support versioning for alignment
with variable VF, since there's no guarantee that the
@@ -2237,8 +2165,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
gcc_assert (!LOOP_VINFO_PTR_MASK (loop_vinfo)
|| LOOP_VINFO_PTR_MASK (loop_vinfo) == mask);
LOOP_VINFO_PTR_MASK (loop_vinfo) = mask;
- LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo).safe_push (
- vect_dr_stmt (dr));
+ LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo).safe_push (stmt_info);
}
}
@@ -2251,18 +2178,17 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
if (do_versioning)
{
- vec<gimple *> may_misalign_stmts
+ vec<stmt_vec_info> may_misalign_stmts
= LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo);
- gimple *stmt;
+ stmt_vec_info stmt_info;
/* It can now be assumed that the data references in the statements
in LOOP_VINFO_MAY_MISALIGN_STMTS will be aligned in the version
of the loop being vectorized. */
- FOR_EACH_VEC_ELT (may_misalign_stmts, i, stmt)
+ FOR_EACH_VEC_ELT (may_misalign_stmts, i, stmt_info)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
- dr = STMT_VINFO_DATA_REF (stmt_info);
- SET_DR_MISALIGNMENT (dr, 0);
+ dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
+ SET_DR_MISALIGNMENT (dr_info, 0);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"Alignment of access forced using versioning.\n");
@@ -2290,16 +2216,18 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
/* Function vect_find_same_alignment_drs.
- Update group and alignment relations according to the chosen
+ Update group and alignment relations in VINFO according to the chosen
vectorization factor. */
static void
-vect_find_same_alignment_drs (struct data_dependence_relation *ddr)
+vect_find_same_alignment_drs (vec_info *vinfo, data_dependence_relation *ddr)
{
struct data_reference *dra = DDR_A (ddr);
struct data_reference *drb = DDR_B (ddr);
- stmt_vec_info stmtinfo_a = vinfo_for_stmt (vect_dr_stmt (dra));
- stmt_vec_info stmtinfo_b = vinfo_for_stmt (vect_dr_stmt (drb));
+ dr_vec_info *dr_info_a = vinfo->lookup_dr (dra);
+ dr_vec_info *dr_info_b = vinfo->lookup_dr (drb);
+ stmt_vec_info stmtinfo_a = dr_info_a->stmt;
+ stmt_vec_info stmtinfo_b = dr_info_b->stmt;
if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
return;
@@ -2322,9 +2250,9 @@ vect_find_same_alignment_drs (struct data_dependence_relation *ddr)
if (maybe_ne (diff, 0))
{
/* Get the wider of the two alignments. */
- unsigned int align_a = (vect_calculate_target_alignment (dra)
+ unsigned int align_a = (vect_calculate_target_alignment (dr_info_a)
/ BITS_PER_UNIT);
- unsigned int align_b = (vect_calculate_target_alignment (drb)
+ unsigned int align_b = (vect_calculate_target_alignment (dr_info_b)
/ BITS_PER_UNIT);
unsigned int max_align = MAX (align_a, align_b);
@@ -2336,14 +2264,9 @@ vect_find_same_alignment_drs (struct data_dependence_relation *ddr)
STMT_VINFO_SAME_ALIGN_REFS (stmtinfo_a).safe_push (drb);
STMT_VINFO_SAME_ALIGN_REFS (stmtinfo_b).safe_push (dra);
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "accesses have the same alignment: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dra));
- dump_printf (MSG_NOTE, " and ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (drb));
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "accesses have the same alignment: %T and %T\n",
+ DR_REF (dra), DR_REF (drb));
}
@@ -2364,7 +2287,7 @@ vect_analyze_data_refs_alignment (loop_vec_info vinfo)
unsigned int i;
FOR_EACH_VEC_ELT (ddrs, i, ddr)
- vect_find_same_alignment_drs (ddr);
+ vect_find_same_alignment_drs (vinfo, ddr);
vec<data_reference_p> datarefs = vinfo->shared->datarefs;
struct data_reference *dr;
@@ -2372,9 +2295,9 @@ vect_analyze_data_refs_alignment (loop_vec_info vinfo)
vect_record_base_alignments (vinfo);
FOR_EACH_VEC_ELT (datarefs, i, dr)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (vect_dr_stmt (dr));
- if (STMT_VINFO_VECTORIZABLE (stmt_info))
- vect_compute_data_ref_alignment (dr);
+ dr_vec_info *dr_info = vinfo->lookup_dr (dr);
+ if (STMT_VINFO_VECTORIZABLE (dr_info->stmt))
+ vect_compute_data_ref_alignment (dr_info);
}
return true;
@@ -2389,18 +2312,18 @@ vect_slp_analyze_and_verify_node_alignment (slp_tree node)
/* We vectorize from the first scalar stmt in the node unless
the node is permuted in which case we start from the first
element in the group. */
- gimple *first_stmt = SLP_TREE_SCALAR_STMTS (node)[0];
- data_reference_p first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
+ stmt_vec_info first_stmt_info = SLP_TREE_SCALAR_STMTS (node)[0];
+ dr_vec_info *first_dr_info = STMT_VINFO_DR_INFO (first_stmt_info);
if (SLP_TREE_LOAD_PERMUTATION (node).exists ())
- first_stmt = DR_GROUP_FIRST_ELEMENT (vinfo_for_stmt (first_stmt));
+ first_stmt_info = DR_GROUP_FIRST_ELEMENT (first_stmt_info);
- data_reference_p dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
- vect_compute_data_ref_alignment (dr);
+ dr_vec_info *dr_info = STMT_VINFO_DR_INFO (first_stmt_info);
+ vect_compute_data_ref_alignment (dr_info);
/* For creating the data-ref pointer we need alignment of the
first element anyway. */
- if (dr != first_dr)
- vect_compute_data_ref_alignment (first_dr);
- if (! verify_data_ref_alignment (dr))
+ if (dr_info != first_dr_info)
+ vect_compute_data_ref_alignment (first_dr_info);
+ if (! verify_data_ref_alignment (dr_info))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -2429,7 +2352,7 @@ vect_slp_analyze_and_verify_instance_alignment (slp_instance instance)
return false;
node = SLP_INSTANCE_TREE (instance);
- if (STMT_VINFO_DATA_REF (vinfo_for_stmt (SLP_TREE_SCALAR_STMTS (node)[0]))
+ if (STMT_VINFO_DATA_REF (SLP_TREE_SCALAR_STMTS (node)[0])
&& ! vect_slp_analyze_and_verify_node_alignment
(SLP_INSTANCE_TREE (instance)))
return false;
@@ -2438,20 +2361,20 @@ vect_slp_analyze_and_verify_instance_alignment (slp_instance instance)
}
-/* Analyze groups of accesses: check that DR belongs to a group of
+/* Analyze groups of accesses: check that DR_INFO belongs to a group of
accesses of legal size, step, etc. Detect gaps, single element
interleaving, and other special cases. Set grouped access info.
Collect groups of strided stores for further use in SLP analysis.
Worker for vect_analyze_group_access. */
static bool
-vect_analyze_group_access_1 (struct data_reference *dr)
+vect_analyze_group_access_1 (dr_vec_info *dr_info)
{
+ data_reference *dr = dr_info->dr;
tree step = DR_STEP (dr);
tree scalar_type = TREE_TYPE (DR_REF (dr));
HOST_WIDE_INT type_size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (scalar_type));
- gimple *stmt = vect_dr_stmt (dr);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ stmt_vec_info stmt_info = dr_info->stmt;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
HOST_WIDE_INT dr_step = -1;
@@ -2473,15 +2396,10 @@ vect_analyze_group_access_1 (struct data_reference *dr)
if ((dr_step % type_size) != 0)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "Step ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, step);
- dump_printf (MSG_NOTE,
- " is not a multiple of the element size for ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr));
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Step %T is not a multiple of the element size"
+ " for %T\n",
+ step, DR_REF (dr));
return false;
}
groupsize = absu_hwi (dr_step) / type_size;
@@ -2490,7 +2408,7 @@ vect_analyze_group_access_1 (struct data_reference *dr)
groupsize = 0;
/* Not consecutive access is possible only if it is a part of interleaving. */
- if (!DR_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)))
+ if (!DR_GROUP_FIRST_ELEMENT (stmt_info))
{
/* Check if it this DR is a part of interleaving, and is a single
element of the group that is accessed in the loop. */
@@ -2501,49 +2419,42 @@ vect_analyze_group_access_1 (struct data_reference *dr)
&& (dr_step % type_size) == 0
&& groupsize > 0)
{
- DR_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) = stmt;
- DR_GROUP_SIZE (vinfo_for_stmt (stmt)) = groupsize;
+ DR_GROUP_FIRST_ELEMENT (stmt_info) = stmt_info;
+ DR_GROUP_SIZE (stmt_info) = groupsize;
DR_GROUP_GAP (stmt_info) = groupsize - 1;
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "Detected single element interleaving ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr));
- dump_printf (MSG_NOTE, " step ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, step);
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Detected single element interleaving %T"
+ " step %T\n",
+ DR_REF (dr), step);
return true;
}
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not consecutive access ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not consecutive access %G", stmt_info->stmt);
if (bb_vinfo)
- {
- /* Mark the statement as unvectorizable. */
- STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (vect_dr_stmt (dr))) = false;
- return true;
- }
+ {
+ /* Mark the statement as unvectorizable. */
+ STMT_VINFO_VECTORIZABLE (stmt_info) = false;
+ return true;
+ }
dump_printf_loc (MSG_NOTE, vect_location, "using strided accesses\n");
STMT_VINFO_STRIDED_P (stmt_info) = true;
return true;
}
- if (DR_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) == stmt)
+ if (DR_GROUP_FIRST_ELEMENT (stmt_info) == stmt_info)
{
/* First stmt in the interleaving chain. Check the chain. */
- gimple *next = DR_GROUP_NEXT_ELEMENT (vinfo_for_stmt (stmt));
+ stmt_vec_info next = DR_GROUP_NEXT_ELEMENT (stmt_info);
struct data_reference *data_ref = dr;
unsigned int count = 1;
tree prev_init = DR_INIT (data_ref);
- gimple *prev = stmt;
+ stmt_vec_info prev = stmt_info;
HOST_WIDE_INT diff, gaps = 0;
/* By construction, all group members have INTEGER_CST DR_INITs. */
@@ -2554,8 +2465,7 @@ vect_analyze_group_access_1 (struct data_reference *dr)
stmt, and the rest get their vectorized loads from the first
one. */
if (!tree_int_cst_compare (DR_INIT (data_ref),
- DR_INIT (STMT_VINFO_DATA_REF (
- vinfo_for_stmt (next)))))
+ DR_INIT (STMT_VINFO_DATA_REF (next))))
{
if (DR_IS_WRITE (data_ref))
{
@@ -2569,16 +2479,16 @@ vect_analyze_group_access_1 (struct data_reference *dr)
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"Two or more load stmts share the same dr.\n");
- /* For load use the same data-ref load. */
- DR_GROUP_SAME_DR_STMT (vinfo_for_stmt (next)) = prev;
+ /* For load use the same data-ref load. */
+ DR_GROUP_SAME_DR_STMT (next) = prev;
- prev = next;
- next = DR_GROUP_NEXT_ELEMENT (vinfo_for_stmt (next));
- continue;
+ prev = next;
+ next = DR_GROUP_NEXT_ELEMENT (next);
+ continue;
}
- prev = next;
- data_ref = STMT_VINFO_DATA_REF (vinfo_for_stmt (next));
+ prev = next;
+ data_ref = STMT_VINFO_DATA_REF (next);
/* All group members have the same STEP by construction. */
gcc_checking_assert (operand_equal_p (DR_STEP (data_ref), step, 0));
@@ -2606,12 +2516,12 @@ vect_analyze_group_access_1 (struct data_reference *dr)
/* Store the gap from the previous member of the group. If there is no
gap in the access, DR_GROUP_GAP is always 1. */
- DR_GROUP_GAP (vinfo_for_stmt (next)) = diff;
+ DR_GROUP_GAP (next) = diff;
- prev_init = DR_INIT (data_ref);
- next = DR_GROUP_NEXT_ELEMENT (vinfo_for_stmt (next));
- /* Count the number of data-refs in the chain. */
- count++;
+ prev_init = DR_INIT (data_ref);
+ next = DR_GROUP_NEXT_ELEMENT (next);
+ /* Count the number of data-refs in the chain. */
+ count++;
}
if (groupsize == 0)
@@ -2632,87 +2542,84 @@ vect_analyze_group_access_1 (struct data_reference *dr)
if (groupsize != count
&& !DR_IS_READ (dr))
{
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "interleaved store with gaps\n");
- return false;
+ groupsize = count;
+ STMT_VINFO_STRIDED_P (stmt_info) = true;
}
/* If there is a gap after the last load in the group it is the
difference between the groupsize and the last accessed
element.
When there is no gap, this difference should be 0. */
- DR_GROUP_GAP (vinfo_for_stmt (stmt)) = groupsize - last_accessed_element;
+ DR_GROUP_GAP (stmt_info) = groupsize - last_accessed_element;
- DR_GROUP_SIZE (vinfo_for_stmt (stmt)) = groupsize;
+ DR_GROUP_SIZE (stmt_info) = groupsize;
if (dump_enabled_p ())
{
dump_printf_loc (MSG_NOTE, vect_location,
"Detected interleaving ");
if (DR_IS_READ (dr))
dump_printf (MSG_NOTE, "load ");
+ else if (STMT_VINFO_STRIDED_P (stmt_info))
+ dump_printf (MSG_NOTE, "strided store ");
else
dump_printf (MSG_NOTE, "store ");
- dump_printf (MSG_NOTE, "of size %u starting with ",
- (unsigned)groupsize);
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
- if (DR_GROUP_GAP (vinfo_for_stmt (stmt)) != 0)
+ dump_printf (MSG_NOTE, "of size %u starting with %G",
+ (unsigned)groupsize, stmt_info->stmt);
+ if (DR_GROUP_GAP (stmt_info) != 0)
dump_printf_loc (MSG_NOTE, vect_location,
"There is a gap of %u elements after the group\n",
- DR_GROUP_GAP (vinfo_for_stmt (stmt)));
+ DR_GROUP_GAP (stmt_info));
}
/* SLP: create an SLP data structure for every interleaving group of
stores for further analysis in vect_analyse_slp. */
if (DR_IS_WRITE (dr) && !slp_impossible)
- {
- if (loop_vinfo)
- LOOP_VINFO_GROUPED_STORES (loop_vinfo).safe_push (stmt);
- if (bb_vinfo)
- BB_VINFO_GROUPED_STORES (bb_vinfo).safe_push (stmt);
- }
+ {
+ if (loop_vinfo)
+ LOOP_VINFO_GROUPED_STORES (loop_vinfo).safe_push (stmt_info);
+ if (bb_vinfo)
+ BB_VINFO_GROUPED_STORES (bb_vinfo).safe_push (stmt_info);
+ }
}
return true;
}
-/* Analyze groups of accesses: check that DR belongs to a group of
+/* Analyze groups of accesses: check that DR_INFO belongs to a group of
accesses of legal size, step, etc. Detect gaps, single element
interleaving, and other special cases. Set grouped access info.
Collect groups of strided stores for further use in SLP analysis. */
static bool
-vect_analyze_group_access (struct data_reference *dr)
+vect_analyze_group_access (dr_vec_info *dr_info)
{
- if (!vect_analyze_group_access_1 (dr))
+ if (!vect_analyze_group_access_1 (dr_info))
{
/* Dissolve the group if present. */
- gimple *next;
- gimple *stmt = DR_GROUP_FIRST_ELEMENT (vinfo_for_stmt (vect_dr_stmt (dr)));
- while (stmt)
+ stmt_vec_info stmt_info = DR_GROUP_FIRST_ELEMENT (dr_info->stmt);
+ while (stmt_info)
{
- stmt_vec_info vinfo = vinfo_for_stmt (stmt);
- next = DR_GROUP_NEXT_ELEMENT (vinfo);
- DR_GROUP_FIRST_ELEMENT (vinfo) = NULL;
- DR_GROUP_NEXT_ELEMENT (vinfo) = NULL;
- stmt = next;
+ stmt_vec_info next = DR_GROUP_NEXT_ELEMENT (stmt_info);
+ DR_GROUP_FIRST_ELEMENT (stmt_info) = NULL;
+ DR_GROUP_NEXT_ELEMENT (stmt_info) = NULL;
+ stmt_info = next;
}
return false;
}
return true;
}
-/* Analyze the access pattern of the data-reference DR.
+/* Analyze the access pattern of the data-reference DR_INFO.
In case of non-consecutive accesses call vect_analyze_group_access() to
analyze groups of accesses. */
static bool
-vect_analyze_data_ref_access (struct data_reference *dr)
+vect_analyze_data_ref_access (dr_vec_info *dr_info)
{
+ data_reference *dr = dr_info->dr;
tree step = DR_STEP (dr);
tree scalar_type = TREE_TYPE (DR_REF (dr));
- gimple *stmt = vect_dr_stmt (dr);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ stmt_vec_info stmt_info = dr_info->stmt;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
struct loop *loop = NULL;
@@ -2733,8 +2640,8 @@ vect_analyze_data_ref_access (struct data_reference *dr)
/* Allow loads with zero step in inner-loop vectorization. */
if (loop_vinfo && integer_zerop (step))
{
- DR_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) = NULL;
- if (!nested_in_vect_loop_p (loop, stmt))
+ DR_GROUP_FIRST_ELEMENT (stmt_info) = NULL;
+ if (!nested_in_vect_loop_p (loop, stmt_info))
return DR_IS_READ (dr);
/* Allow references with zero step for outer loops marked
with pragma omp simd only - it guarantees absence of
@@ -2748,11 +2655,11 @@ vect_analyze_data_ref_access (struct data_reference *dr)
}
}
- if (loop && nested_in_vect_loop_p (loop, stmt))
+ if (loop && nested_in_vect_loop_p (loop, stmt_info))
{
/* Interleaved accesses are not yet supported within outer-loop
vectorization for references in the inner-loop. */
- DR_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) = NULL;
+ DR_GROUP_FIRST_ELEMENT (stmt_info) = NULL;
/* For the rest of the analysis we use the outer-loop step. */
step = STMT_VINFO_DR_STEP (stmt_info);
@@ -2774,12 +2681,12 @@ vect_analyze_data_ref_access (struct data_reference *dr)
&& !compare_tree_int (TYPE_SIZE_UNIT (scalar_type), -dr_step)))
{
/* Mark that it is not interleaving. */
- DR_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) = NULL;
+ DR_GROUP_FIRST_ELEMENT (stmt_info) = NULL;
return true;
}
}
- if (loop && nested_in_vect_loop_p (loop, stmt))
+ if (loop && nested_in_vect_loop_p (loop, stmt_info))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
@@ -2792,10 +2699,10 @@ vect_analyze_data_ref_access (struct data_reference *dr)
if (TREE_CODE (step) != INTEGER_CST)
return (STMT_VINFO_STRIDED_P (stmt_info)
&& (!STMT_VINFO_GROUPED_ACCESS (stmt_info)
- || vect_analyze_group_access (dr)));
+ || vect_analyze_group_access (dr_info)));
/* Not consecutive access - check if it's a part of interleaving group. */
- return vect_analyze_group_access (dr);
+ return vect_analyze_group_access (dr_info);
}
/* Compare two data-references DRA and DRB to group them into chunks
@@ -2866,30 +2773,32 @@ strip_conversion (tree op)
return gimple_assign_rhs1 (stmt);
}
-/* Return true if vectorizable_* routines can handle statements STMT1
- and STMT2 being in a single group. */
+/* Return true if vectorizable_* routines can handle statements STMT1_INFO
+ and STMT2_INFO being in a single group. */
static bool
-can_group_stmts_p (gimple *stmt1, gimple *stmt2)
+can_group_stmts_p (stmt_vec_info stmt1_info, stmt_vec_info stmt2_info)
{
- if (gimple_assign_single_p (stmt1))
- return gimple_assign_single_p (stmt2);
+ if (gimple_assign_single_p (stmt1_info->stmt))
+ return gimple_assign_single_p (stmt2_info->stmt);
- if (is_gimple_call (stmt1) && gimple_call_internal_p (stmt1))
+ gcall *call1 = dyn_cast <gcall *> (stmt1_info->stmt);
+ if (call1 && gimple_call_internal_p (call1))
{
/* Check for two masked loads or two masked stores. */
- if (!is_gimple_call (stmt2) || !gimple_call_internal_p (stmt2))
+ gcall *call2 = dyn_cast <gcall *> (stmt2_info->stmt);
+ if (!call2 || !gimple_call_internal_p (call2))
return false;
- internal_fn ifn = gimple_call_internal_fn (stmt1);
+ internal_fn ifn = gimple_call_internal_fn (call1);
if (ifn != IFN_MASK_LOAD && ifn != IFN_MASK_STORE)
return false;
- if (ifn != gimple_call_internal_fn (stmt2))
+ if (ifn != gimple_call_internal_fn (call2))
return false;
/* Check that the masks are the same. Cope with casts of masks,
like those created by build_mask_conversion. */
- tree mask1 = gimple_call_arg (stmt1, 2);
- tree mask2 = gimple_call_arg (stmt2, 2);
+ tree mask1 = gimple_call_arg (call1, 2);
+ tree mask2 = gimple_call_arg (call2, 2);
if (!operand_equal_p (mask1, mask2, 0))
{
mask1 = strip_conversion (mask1);
@@ -2938,7 +2847,8 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
for (i = 0; i < datarefs_copy.length () - 1;)
{
data_reference_p dra = datarefs_copy[i];
- stmt_vec_info stmtinfo_a = vinfo_for_stmt (vect_dr_stmt (dra));
+ dr_vec_info *dr_info_a = vinfo->lookup_dr (dra);
+ stmt_vec_info stmtinfo_a = dr_info_a->stmt;
stmt_vec_info lastinfo = NULL;
if (!STMT_VINFO_VECTORIZABLE (stmtinfo_a)
|| STMT_VINFO_GATHER_SCATTER_P (stmtinfo_a))
@@ -2949,7 +2859,8 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
for (i = i + 1; i < datarefs_copy.length (); ++i)
{
data_reference_p drb = datarefs_copy[i];
- stmt_vec_info stmtinfo_b = vinfo_for_stmt (vect_dr_stmt (drb));
+ dr_vec_info *dr_info_b = vinfo->lookup_dr (drb);
+ stmt_vec_info stmtinfo_b = dr_info_b->stmt;
if (!STMT_VINFO_VECTORIZABLE (stmtinfo_b)
|| STMT_VINFO_GATHER_SCATTER_P (stmtinfo_b))
break;
@@ -2973,7 +2884,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
|| data_ref_compare_tree (DR_BASE_ADDRESS (dra),
DR_BASE_ADDRESS (drb)) != 0
|| data_ref_compare_tree (DR_OFFSET (dra), DR_OFFSET (drb)) != 0
- || !can_group_stmts_p (vect_dr_stmt (dra), vect_dr_stmt (drb)))
+ || !can_group_stmts_p (stmtinfo_a, stmtinfo_b))
break;
/* Check that the data-refs have the same constant size. */
@@ -3046,51 +2957,47 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
}
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "Detected interleaving ");
- if (DR_IS_READ (dra))
- dump_printf (MSG_NOTE, "load ");
- else
- dump_printf (MSG_NOTE, "store ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dra));
- dump_printf (MSG_NOTE, " and ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (drb));
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ DR_IS_READ (dra)
+ ? "Detected interleaving load %T and %T\n"
+ : "Detected interleaving store %T and %T\n",
+ DR_REF (dra), DR_REF (drb));
/* Link the found element into the group list. */
if (!DR_GROUP_FIRST_ELEMENT (stmtinfo_a))
{
- DR_GROUP_FIRST_ELEMENT (stmtinfo_a) = vect_dr_stmt (dra);
+ DR_GROUP_FIRST_ELEMENT (stmtinfo_a) = stmtinfo_a;
lastinfo = stmtinfo_a;
}
- DR_GROUP_FIRST_ELEMENT (stmtinfo_b) = vect_dr_stmt (dra);
- DR_GROUP_NEXT_ELEMENT (lastinfo) = vect_dr_stmt (drb);
+ DR_GROUP_FIRST_ELEMENT (stmtinfo_b) = stmtinfo_a;
+ DR_GROUP_NEXT_ELEMENT (lastinfo) = stmtinfo_b;
lastinfo = stmtinfo_b;
}
}
FOR_EACH_VEC_ELT (datarefs_copy, i, dr)
- if (STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (vect_dr_stmt (dr)))
- && !vect_analyze_data_ref_access (dr))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: complicated access pattern.\n");
-
- if (is_a <bb_vec_info> (vinfo))
- {
- /* Mark the statement as not vectorizable. */
- STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (vect_dr_stmt (dr))) = false;
- continue;
- }
- else
- {
- datarefs_copy.release ();
- return false;
- }
- }
+ {
+ dr_vec_info *dr_info = vinfo->lookup_dr (dr);
+ if (STMT_VINFO_VECTORIZABLE (dr_info->stmt)
+ && !vect_analyze_data_ref_access (dr_info))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: complicated access pattern.\n");
+
+ if (is_a <bb_vec_info> (vinfo))
+ {
+ /* Mark the statement as not vectorizable. */
+ STMT_VINFO_VECTORIZABLE (dr_info->stmt) = false;
+ continue;
+ }
+ else
+ {
+ datarefs_copy.release ();
+ return false;
+ }
+ }
+ }
datarefs_copy.release ();
return true;
@@ -3099,7 +3006,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
/* Function vect_vfa_segment_size.
Input:
- DR: The data reference.
+ DR_INFO: The data reference.
LENGTH_FACTOR: segment length to consider.
Return a value suitable for the dr_with_seg_len::seg_len field.
@@ -3108,32 +3015,32 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
the size of the access; in effect it only describes the first byte. */
static tree
-vect_vfa_segment_size (struct data_reference *dr, tree length_factor)
+vect_vfa_segment_size (dr_vec_info *dr_info, tree length_factor)
{
length_factor = size_binop (MINUS_EXPR,
fold_convert (sizetype, length_factor),
size_one_node);
- return size_binop (MULT_EXPR, fold_convert (sizetype, DR_STEP (dr)),
+ return size_binop (MULT_EXPR, fold_convert (sizetype, DR_STEP (dr_info->dr)),
length_factor);
}
-/* Return a value that, when added to abs (vect_vfa_segment_size (dr)),
+/* Return a value that, when added to abs (vect_vfa_segment_size (DR_INFO)),
gives the worst-case number of bytes covered by the segment. */
static unsigned HOST_WIDE_INT
-vect_vfa_access_size (data_reference *dr)
+vect_vfa_access_size (dr_vec_info *dr_info)
{
- stmt_vec_info stmt_vinfo = vinfo_for_stmt (vect_dr_stmt (dr));
- tree ref_type = TREE_TYPE (DR_REF (dr));
+ stmt_vec_info stmt_vinfo = dr_info->stmt;
+ tree ref_type = TREE_TYPE (DR_REF (dr_info->dr));
unsigned HOST_WIDE_INT ref_size = tree_to_uhwi (TYPE_SIZE_UNIT (ref_type));
unsigned HOST_WIDE_INT access_size = ref_size;
if (DR_GROUP_FIRST_ELEMENT (stmt_vinfo))
{
- gcc_assert (DR_GROUP_FIRST_ELEMENT (stmt_vinfo) == vect_dr_stmt (dr));
+ gcc_assert (DR_GROUP_FIRST_ELEMENT (stmt_vinfo) == stmt_vinfo);
access_size *= DR_GROUP_SIZE (stmt_vinfo) - DR_GROUP_GAP (stmt_vinfo);
}
if (STMT_VINFO_VEC_STMT (stmt_vinfo)
- && (vect_supportable_dr_alignment (dr, false)
+ && (vect_supportable_dr_alignment (dr_info, false)
== dr_explicit_realign_optimized))
{
/* We might access a full vector's worth. */
@@ -3143,12 +3050,13 @@ vect_vfa_access_size (data_reference *dr)
return access_size;
}
-/* Get the minimum alignment for all the scalar accesses that DR describes. */
+/* Get the minimum alignment for all the scalar accesses that DR_INFO
+ describes. */
static unsigned int
-vect_vfa_align (const data_reference *dr)
+vect_vfa_align (dr_vec_info *dr_info)
{
- return TYPE_ALIGN_UNIT (TREE_TYPE (DR_REF (dr)));
+ return TYPE_ALIGN_UNIT (TREE_TYPE (DR_REF (dr_info->dr)));
}
/* Function vect_no_alias_p.
@@ -3161,27 +3069,27 @@ vect_vfa_align (const data_reference *dr)
of dr_with_seg_len::{seg_len,access_size} for A and B. */
static int
-vect_compile_time_alias (struct data_reference *a, struct data_reference *b,
+vect_compile_time_alias (dr_vec_info *a, dr_vec_info *b,
tree segment_length_a, tree segment_length_b,
unsigned HOST_WIDE_INT access_size_a,
unsigned HOST_WIDE_INT access_size_b)
{
- poly_offset_int offset_a = wi::to_poly_offset (DR_INIT (a));
- poly_offset_int offset_b = wi::to_poly_offset (DR_INIT (b));
+ poly_offset_int offset_a = wi::to_poly_offset (DR_INIT (a->dr));
+ poly_offset_int offset_b = wi::to_poly_offset (DR_INIT (b->dr));
poly_uint64 const_length_a;
poly_uint64 const_length_b;
/* For negative step, we need to adjust address range by TYPE_SIZE_UNIT
bytes, e.g., int a[3] -> a[1] range is [a+4, a+16) instead of
[a, a+12) */
- if (tree_int_cst_compare (DR_STEP (a), size_zero_node) < 0)
+ if (tree_int_cst_compare (DR_STEP (a->dr), size_zero_node) < 0)
{
const_length_a = (-wi::to_poly_wide (segment_length_a)).force_uhwi ();
offset_a = (offset_a + access_size_a) - const_length_a;
}
else
const_length_a = tree_to_poly_uint64 (segment_length_a);
- if (tree_int_cst_compare (DR_STEP (b), size_zero_node) < 0)
+ if (tree_int_cst_compare (DR_STEP (b->dr), size_zero_node) < 0)
{
const_length_b = (-wi::to_poly_wide (segment_length_b)).force_uhwi ();
offset_b = (offset_b + access_size_b) - const_length_b;
@@ -3229,14 +3137,9 @@ dependence_distance_ge_vf (data_dependence_relation *ddr,
}
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "dependence distance between ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (DDR_A (ddr)));
- dump_printf (MSG_NOTE, " and ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (DDR_B (ddr)));
- dump_printf (MSG_NOTE, " is >= VF\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "dependence distance between %T and %T is >= VF\n",
+ DR_REF (DDR_A (ddr)), DR_REF (DDR_B (ddr)));
return true;
}
@@ -3246,9 +3149,9 @@ dependence_distance_ge_vf (data_dependence_relation *ddr,
static void
dump_lower_bound (dump_flags_t dump_kind, const vec_lower_bound &lower_bound)
{
- dump_printf (dump_kind, "%s (", lower_bound.unsigned_p ? "unsigned" : "abs");
- dump_generic_expr (dump_kind, TDF_SLIM, lower_bound.expr);
- dump_printf (dump_kind, ") >= ");
+ dump_printf (dump_kind, "%s (%T) >= ",
+ lower_bound.unsigned_p ? "unsigned" : "abs",
+ lower_bound.expr);
dump_dec (dump_kind, lower_bound.min_value);
}
@@ -3291,30 +3194,34 @@ vect_check_lower_bound (loop_vec_info loop_vinfo, tree expr, bool unsigned_p,
LOOP_VINFO_LOWER_BOUNDS (loop_vinfo).safe_push (lower_bound);
}
-/* Return true if it's unlikely that the step of the vectorized form of DR
+/* Return true if it's unlikely that the step of the vectorized form of DR_INFO
will span fewer than GAP bytes. */
static bool
-vect_small_gap_p (loop_vec_info loop_vinfo, data_reference *dr, poly_int64 gap)
+vect_small_gap_p (loop_vec_info loop_vinfo, dr_vec_info *dr_info,
+ poly_int64 gap)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (vect_dr_stmt (dr));
+ stmt_vec_info stmt_info = dr_info->stmt;
HOST_WIDE_INT count
= estimated_poly_value (LOOP_VINFO_VECT_FACTOR (loop_vinfo));
if (DR_GROUP_FIRST_ELEMENT (stmt_info))
- count *= DR_GROUP_SIZE (vinfo_for_stmt (DR_GROUP_FIRST_ELEMENT (stmt_info)));
- return estimated_poly_value (gap) <= count * vect_get_scalar_dr_size (dr);
+ count *= DR_GROUP_SIZE (DR_GROUP_FIRST_ELEMENT (stmt_info));
+ return (estimated_poly_value (gap)
+ <= count * vect_get_scalar_dr_size (dr_info));
}
-/* Return true if we know that there is no alias between DR_A and DR_B
- when abs (DR_STEP (DR_A)) >= N for some N. When returning true, set
- *LOWER_BOUND_OUT to this N. */
+/* Return true if we know that there is no alias between DR_INFO_A and
+ DR_INFO_B when abs (DR_STEP (DR_INFO_A->dr)) >= N for some N.
+ When returning true, set *LOWER_BOUND_OUT to this N. */
static bool
-vectorizable_with_step_bound_p (data_reference *dr_a, data_reference *dr_b,
+vectorizable_with_step_bound_p (dr_vec_info *dr_info_a, dr_vec_info *dr_info_b,
poly_uint64 *lower_bound_out)
{
/* Check that there is a constant gap of known sign between DR_A
and DR_B. */
+ data_reference *dr_a = dr_info_a->dr;
+ data_reference *dr_b = dr_info_b->dr;
poly_int64 init_a, init_b;
if (!operand_equal_p (DR_BASE_ADDRESS (dr_a), DR_BASE_ADDRESS (dr_b), 0)
|| !operand_equal_p (DR_OFFSET (dr_a), DR_OFFSET (dr_b), 0)
@@ -3328,19 +3235,19 @@ vectorizable_with_step_bound_p (data_reference *dr_a, data_reference *dr_b,
if (maybe_lt (init_b, init_a))
{
std::swap (init_a, init_b);
+ std::swap (dr_info_a, dr_info_b);
std::swap (dr_a, dr_b);
}
/* If the two accesses could be dependent within a scalar iteration,
make sure that we'd retain their order. */
- if (maybe_gt (init_a + vect_get_scalar_dr_size (dr_a), init_b)
- && !vect_preserves_scalar_order_p (vect_dr_stmt (dr_a),
- vect_dr_stmt (dr_b)))
+ if (maybe_gt (init_a + vect_get_scalar_dr_size (dr_info_a), init_b)
+ && !vect_preserves_scalar_order_p (dr_info_a, dr_info_b))
return false;
/* There is no alias if abs (DR_STEP) is greater than or equal to
the bytes spanned by the combination of the two accesses. */
- *lower_bound_out = init_b + vect_get_scalar_dr_size (dr_b) - init_a;
+ *lower_bound_out = init_b + vect_get_scalar_dr_size (dr_info_b) - init_a;
return true;
}
@@ -3398,12 +3305,9 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
{
int comp_res;
poly_uint64 lower_bound;
- struct data_reference *dr_a, *dr_b;
- gimple *dr_group_first_a, *dr_group_first_b;
tree segment_length_a, segment_length_b;
unsigned HOST_WIDE_INT access_size_a, access_size_b;
unsigned int align_a, align_b;
- gimple *stmt_a, *stmt_b;
/* Ignore the alias if the VF we chose ended up being no greater
than the dependence distance. */
@@ -3416,39 +3320,33 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
if (!compared_objects.add (new_pair))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "checking that ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, new_pair.first);
- dump_printf (MSG_NOTE, " and ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, new_pair.second);
- dump_printf (MSG_NOTE, " have different addresses\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "checking that %T and %T"
+ " have different addresses\n",
+ new_pair.first, new_pair.second);
LOOP_VINFO_CHECK_UNEQUAL_ADDRS (loop_vinfo).safe_push (new_pair);
}
continue;
}
- dr_a = DDR_A (ddr);
- stmt_a = vect_dr_stmt (DDR_A (ddr));
+ dr_vec_info *dr_info_a = loop_vinfo->lookup_dr (DDR_A (ddr));
+ stmt_vec_info stmt_info_a = dr_info_a->stmt;
- dr_b = DDR_B (ddr);
- stmt_b = vect_dr_stmt (DDR_B (ddr));
+ dr_vec_info *dr_info_b = loop_vinfo->lookup_dr (DDR_B (ddr));
+ stmt_vec_info stmt_info_b = dr_info_b->stmt;
/* Skip the pair if inter-iteration dependencies are irrelevant
and intra-iteration dependencies are guaranteed to be honored. */
if (ignore_step_p
- && (vect_preserves_scalar_order_p (stmt_a, stmt_b)
- || vectorizable_with_step_bound_p (dr_a, dr_b, &lower_bound)))
+ && (vect_preserves_scalar_order_p (dr_info_a, dr_info_b)
+ || vectorizable_with_step_bound_p (dr_info_a, dr_info_b,
+ &lower_bound)))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "no need for alias check between ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a));
- dump_printf (MSG_NOTE, " and ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b));
- dump_printf (MSG_NOTE, " when VF is 1\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "no need for alias check between "
+ "%T and %T when VF is 1\n",
+ DR_REF (dr_info_a->dr), DR_REF (dr_info_b->dr));
continue;
}
@@ -3457,21 +3355,20 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
(It might not be, for example, if the minimum step is much larger
than the number of bytes handled by one vector iteration.) */
if (!ignore_step_p
- && TREE_CODE (DR_STEP (dr_a)) != INTEGER_CST
- && vectorizable_with_step_bound_p (dr_a, dr_b, &lower_bound)
- && (vect_small_gap_p (loop_vinfo, dr_a, lower_bound)
- || vect_small_gap_p (loop_vinfo, dr_b, lower_bound)))
+ && TREE_CODE (DR_STEP (dr_info_a->dr)) != INTEGER_CST
+ && vectorizable_with_step_bound_p (dr_info_a, dr_info_b,
+ &lower_bound)
+ && (vect_small_gap_p (loop_vinfo, dr_info_a, lower_bound)
+ || vect_small_gap_p (loop_vinfo, dr_info_b, lower_bound)))
{
- bool unsigned_p = dr_known_forward_stride_p (dr_a);
+ bool unsigned_p = dr_known_forward_stride_p (dr_info_a->dr);
if (dump_enabled_p ())
{
- dump_printf_loc (MSG_NOTE, vect_location, "no alias between ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a));
- dump_printf (MSG_NOTE, " and ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b));
- dump_printf (MSG_NOTE, " when the step ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_STEP (dr_a));
- dump_printf (MSG_NOTE, " is outside ");
+ dump_printf_loc (MSG_NOTE, vect_location, "no alias between "
+ "%T and %T when the step %T is outside ",
+ DR_REF (dr_info_a->dr),
+ DR_REF (dr_info_b->dr),
+ DR_STEP (dr_info_a->dr));
if (unsigned_p)
dump_printf (MSG_NOTE, "[0");
else
@@ -3483,23 +3380,23 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
dump_dec (MSG_NOTE, lower_bound);
dump_printf (MSG_NOTE, ")\n");
}
- vect_check_lower_bound (loop_vinfo, DR_STEP (dr_a), unsigned_p,
- lower_bound);
+ vect_check_lower_bound (loop_vinfo, DR_STEP (dr_info_a->dr),
+ unsigned_p, lower_bound);
continue;
}
- dr_group_first_a = DR_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt_a));
+ stmt_vec_info dr_group_first_a = DR_GROUP_FIRST_ELEMENT (stmt_info_a);
if (dr_group_first_a)
{
- stmt_a = dr_group_first_a;
- dr_a = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt_a));
+ stmt_info_a = dr_group_first_a;
+ dr_info_a = STMT_VINFO_DR_INFO (stmt_info_a);
}
- dr_group_first_b = DR_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt_b));
+ stmt_vec_info dr_group_first_b = DR_GROUP_FIRST_ELEMENT (stmt_info_b);
if (dr_group_first_b)
{
- stmt_b = dr_group_first_b;
- dr_b = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt_b));
+ stmt_info_b = dr_group_first_b;
+ dr_info_b = STMT_VINFO_DR_INFO (stmt_info_b);
}
if (ignore_step_p)
@@ -3509,32 +3406,33 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
}
else
{
- if (!operand_equal_p (DR_STEP (dr_a), DR_STEP (dr_b), 0))
+ if (!operand_equal_p (DR_STEP (dr_info_a->dr),
+ DR_STEP (dr_info_b->dr), 0))
length_factor = scalar_loop_iters;
else
length_factor = size_int (vect_factor);
- segment_length_a = vect_vfa_segment_size (dr_a, length_factor);
- segment_length_b = vect_vfa_segment_size (dr_b, length_factor);
+ segment_length_a = vect_vfa_segment_size (dr_info_a, length_factor);
+ segment_length_b = vect_vfa_segment_size (dr_info_b, length_factor);
}
- access_size_a = vect_vfa_access_size (dr_a);
- access_size_b = vect_vfa_access_size (dr_b);
- align_a = vect_vfa_align (dr_a);
- align_b = vect_vfa_align (dr_b);
+ access_size_a = vect_vfa_access_size (dr_info_a);
+ access_size_b = vect_vfa_access_size (dr_info_b);
+ align_a = vect_vfa_align (dr_info_a);
+ align_b = vect_vfa_align (dr_info_b);
- comp_res = data_ref_compare_tree (DR_BASE_ADDRESS (dr_a),
- DR_BASE_ADDRESS (dr_b));
+ comp_res = data_ref_compare_tree (DR_BASE_ADDRESS (dr_info_a->dr),
+ DR_BASE_ADDRESS (dr_info_b->dr));
if (comp_res == 0)
- comp_res = data_ref_compare_tree (DR_OFFSET (dr_a),
- DR_OFFSET (dr_b));
+ comp_res = data_ref_compare_tree (DR_OFFSET (dr_info_a->dr),
+ DR_OFFSET (dr_info_b->dr));
/* See whether the alias is known at compilation time. */
if (comp_res == 0
- && TREE_CODE (DR_STEP (dr_a)) == INTEGER_CST
- && TREE_CODE (DR_STEP (dr_b)) == INTEGER_CST
+ && TREE_CODE (DR_STEP (dr_info_a->dr)) == INTEGER_CST
+ && TREE_CODE (DR_STEP (dr_info_b->dr)) == INTEGER_CST
&& poly_int_tree_p (segment_length_a)
&& poly_int_tree_p (segment_length_b))
{
- int res = vect_compile_time_alias (dr_a, dr_b,
+ int res = vect_compile_time_alias (dr_info_a, dr_info_b,
segment_length_a,
segment_length_b,
access_size_a,
@@ -3542,10 +3440,8 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
if (res >= 0 && dump_enabled_p ())
{
dump_printf_loc (MSG_NOTE, vect_location,
- "can tell at compile time that ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a));
- dump_printf (MSG_NOTE, " and ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b));
+ "can tell at compile time that %T and %T",
+ DR_REF (dr_info_a->dr), DR_REF (dr_info_b->dr));
if (res == 0)
dump_printf (MSG_NOTE, " do not alias\n");
else
@@ -3565,8 +3461,10 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
}
dr_with_seg_len_pair_t dr_with_seg_len_pair
- (dr_with_seg_len (dr_a, segment_length_a, access_size_a, align_a),
- dr_with_seg_len (dr_b, segment_length_b, access_size_b, align_b));
+ (dr_with_seg_len (dr_info_a->dr, segment_length_a,
+ access_size_a, align_a),
+ dr_with_seg_len (dr_info_b->dr, segment_length_b,
+ access_size_b, align_b));
/* Canonicalize pairs by sorting the two DR members. */
if (comp_res > 0)
@@ -3644,13 +3542,14 @@ vect_gather_scatter_fn_p (bool read_p, bool masked_p, tree vectype,
return true;
}
-/* CALL is a call to an internal gather load or scatter store function.
+/* STMT_INFO is a call to an internal gather load or scatter store function.
Describe the operation in INFO. */
static void
-vect_describe_gather_scatter_call (gcall *call, gather_scatter_info *info)
+vect_describe_gather_scatter_call (stmt_vec_info stmt_info,
+ gather_scatter_info *info)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (call);
+ gcall *call = as_a <gcall *> (stmt_info->stmt);
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
@@ -3665,17 +3564,16 @@ vect_describe_gather_scatter_call (gcall *call, gather_scatter_info *info)
info->memory_type = TREE_TYPE (DR_REF (dr));
}
-/* Return true if a non-affine read or write in STMT is suitable for a
+/* Return true if a non-affine read or write in STMT_INFO is suitable for a
gather load or scatter store. Describe the operation in *INFO if so. */
bool
-vect_check_gather_scatter (gimple *stmt, loop_vec_info loop_vinfo,
+vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo,
gather_scatter_info *info)
{
HOST_WIDE_INT scale = 1;
poly_int64 pbitpos, pbitsize;
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
tree offtype = NULL_TREE;
tree decl = NULL_TREE, base, off;
@@ -3689,13 +3587,13 @@ vect_check_gather_scatter (gimple *stmt, loop_vec_info loop_vinfo,
/* See whether this is already a call to a gather/scatter internal function.
If not, see whether it's a masked load or store. */
- gcall *call = dyn_cast <gcall *> (stmt);
+ gcall *call = dyn_cast <gcall *> (stmt_info->stmt);
if (call && gimple_call_internal_p (call))
{
- ifn = gimple_call_internal_fn (stmt);
+ ifn = gimple_call_internal_fn (call);
if (internal_gather_scatter_fn_p (ifn))
{
- vect_describe_gather_scatter_call (call, info);
+ vect_describe_gather_scatter_call (stmt_info, info);
return true;
}
masked_p = (ifn == IFN_MASK_LOAD || ifn == IFN_MASK_STORE);
@@ -3961,23 +3859,17 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
if (gimple_has_volatile_ops (stmt))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: volatile type ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: volatile type %G", stmt);
return false;
}
if (stmt_can_throw_internal (stmt))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: statement can throw an "
- "exception ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: statement can throw an exception %G",
+ stmt);
return false;
}
@@ -3991,12 +3883,9 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
if (refs.length () > 1)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: more than one data ref "
- "in stmt: ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: more than one data ref "
+ "in stmt: %G", stmt);
return false;
}
@@ -4006,11 +3895,8 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
&& gimple_call_internal_fn (call) != IFN_MASK_STORE))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: dr in a call ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: dr in a call %G", stmt);
return false;
}
@@ -4019,12 +3905,9 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
&& DECL_BIT_FIELD (TREE_OPERAND (DR_REF (dr), 1)))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: statement is bitfield "
- "access ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: statement is bitfield "
+ "access %G", stmt);
return false;
}
@@ -4140,14 +4023,14 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf)
vec<data_reference_p> datarefs = vinfo->shared->datarefs;
FOR_EACH_VEC_ELT (datarefs, i, dr)
{
- gimple *stmt;
- stmt_vec_info stmt_info;
enum { SG_NONE, GATHER, SCATTER } gatherscatter = SG_NONE;
poly_uint64 vf;
gcc_assert (DR_REF (dr));
- stmt = vect_dr_stmt (dr);
- stmt_info = vinfo_for_stmt (stmt);
+ stmt_vec_info stmt_info = vinfo->lookup_stmt (DR_STMT (dr));
+ gcc_assert (!stmt_info->dr_aux.dr);
+ stmt_info->dr_aux.dr = dr;
+ stmt_info->dr_aux.stmt = stmt_info;
/* Check that analysis of the data-ref succeeded. */
if (!DR_BASE_ADDRESS (dr) || !DR_OFFSET (dr) || !DR_INIT (dr)
@@ -4167,7 +4050,7 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf)
/* If target supports vector gather loads or scatter stores,
see if they can't be used. */
if (is_a <loop_vec_info> (vinfo)
- && !nested_in_vect_loop_p (loop, stmt))
+ && !nested_in_vect_loop_p (loop, stmt_info))
{
if (maybe_gather || maybe_scatter)
{
@@ -4181,12 +4064,9 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf)
if (gatherscatter == SG_NONE)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: data ref analysis "
- "failed ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: data ref analysis "
+ "failed %G", stmt_info->stmt);
if (is_a <bb_vec_info> (vinfo))
{
/* In BB vectorization the ref can still participate
@@ -4201,15 +4081,12 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf)
/* See if this was detected as SIMD lane access. */
if (dr->aux == (void *)-1)
{
- if (nested_in_vect_loop_p (loop, stmt))
+ if (nested_in_vect_loop_p (loop, stmt_info))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: data ref analysis "
- "failed ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: data ref analysis "
+ "failed %G", stmt_info->stmt);
return false;
}
STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) = true;
@@ -4219,12 +4096,9 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf)
if (base && VAR_P (base) && DECL_NONALIASED (base))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: base object not addressable "
- "for stmt: ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: base object not addressable "
+ "for stmt: %G", stmt_info->stmt);
if (is_a <bb_vec_info> (vinfo))
{
/* In BB vectorization the ref can still participate
@@ -4239,15 +4113,12 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf)
&& DR_STEP (dr)
&& TREE_CODE (DR_STEP (dr)) != INTEGER_CST)
{
- if (nested_in_vect_loop_p (loop, stmt))
+ if (nested_in_vect_loop_p (loop, stmt_info))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: not suitable for strided "
- "load ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: not suitable for strided "
+ "load %G", stmt_info->stmt);
return false;
}
STMT_VINFO_STRIDED_P (stmt_info) = true;
@@ -4261,7 +4132,7 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf)
inner-most enclosing loop). We do that by building a reference to the
first location accessed by the inner-loop, and analyze it relative to
the outer-loop. */
- if (loop && nested_in_vect_loop_p (loop, stmt))
+ if (loop && nested_in_vect_loop_p (loop, stmt_info))
{
/* Build a reference to the first location accessed by the
inner loop: *(BASE + INIT + OFFSET). By construction,
@@ -4276,12 +4147,8 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf)
tree init_ref = build_fold_indirect_ref (init_addr);
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "analyze in outer loop: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, init_ref);
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "analyze in outer loop: %T\n", init_ref);
if (!dr_analyze_innermost (&STMT_VINFO_DR_WRT_VEC_LOOP (stmt_info),
init_ref, loop))
@@ -4289,35 +4156,25 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf)
return false;
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "\touter base_address: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM,
- STMT_VINFO_DR_BASE_ADDRESS (stmt_info));
- dump_printf (MSG_NOTE, "\n\touter offset from base address: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM,
- STMT_VINFO_DR_OFFSET (stmt_info));
- dump_printf (MSG_NOTE,
- "\n\touter constant offset from base address: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM,
- STMT_VINFO_DR_INIT (stmt_info));
- dump_printf (MSG_NOTE, "\n\touter step: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM,
- STMT_VINFO_DR_STEP (stmt_info));
- dump_printf (MSG_NOTE, "\n\touter base alignment: %d\n",
- STMT_VINFO_DR_BASE_ALIGNMENT (stmt_info));
- dump_printf (MSG_NOTE, "\n\touter base misalignment: %d\n",
- STMT_VINFO_DR_BASE_MISALIGNMENT (stmt_info));
- dump_printf (MSG_NOTE, "\n\touter offset alignment: %d\n",
- STMT_VINFO_DR_OFFSET_ALIGNMENT (stmt_info));
- dump_printf (MSG_NOTE, "\n\touter step alignment: %d\n",
- STMT_VINFO_DR_STEP_ALIGNMENT (stmt_info));
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "\touter base_address: %T\n"
+ "\touter offset from base address: %T\n"
+ "\touter constant offset from base address: %T\n"
+ "\touter step: %T\n"
+ "\touter base alignment: %d\n\n"
+ "\touter base misalignment: %d\n"
+ "\touter offset alignment: %d\n"
+ "\touter step alignment: %d\n",
+ STMT_VINFO_DR_BASE_ADDRESS (stmt_info),
+ STMT_VINFO_DR_OFFSET (stmt_info),
+ STMT_VINFO_DR_INIT (stmt_info),
+ STMT_VINFO_DR_STEP (stmt_info),
+ STMT_VINFO_DR_BASE_ALIGNMENT (stmt_info),
+ STMT_VINFO_DR_BASE_MISALIGNMENT (stmt_info),
+ STMT_VINFO_DR_OFFSET_ALIGNMENT (stmt_info),
+ STMT_VINFO_DR_STEP_ALIGNMENT (stmt_info));
}
- gcc_assert (!STMT_VINFO_DATA_REF (stmt_info));
- STMT_VINFO_DATA_REF (stmt_info) = dr;
-
/* Set vectype for STMT. */
scalar_type = TREE_TYPE (DR_REF (dr));
STMT_VINFO_VECTYPE (stmt_info)
@@ -4327,8 +4184,8 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf)
if (dump_enabled_p ())
{
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: no vectype for stmt: ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
+ "not vectorized: no vectype for stmt: %G",
+ stmt_info->stmt);
dump_printf (MSG_MISSED_OPTIMIZATION, " scalar_type: ");
dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_DETAILS,
scalar_type);
@@ -4347,14 +4204,9 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf)
else
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "got vectype for stmt: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
- dump_generic_expr (MSG_NOTE, TDF_SLIM,
- STMT_VINFO_VECTYPE (stmt_info));
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "got vectype for stmt: %G%T\n",
+ stmt_info->stmt, STMT_VINFO_VECTYPE (stmt_info));
}
/* Adjust the minimal vectorization factor according to the
@@ -4365,20 +4217,19 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf)
if (gatherscatter != SG_NONE)
{
gather_scatter_info gs_info;
- if (!vect_check_gather_scatter (stmt, as_a <loop_vec_info> (vinfo),
+ if (!vect_check_gather_scatter (stmt_info,
+ as_a <loop_vec_info> (vinfo),
&gs_info)
|| !get_vectype_for_scalar_type (TREE_TYPE (gs_info.offset)))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- (gatherscatter == GATHER) ?
- "not vectorized: not suitable for gather "
- "load " :
- "not vectorized: not suitable for scatter "
- "store ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ (gatherscatter == GATHER) ?
+ "not vectorized: not suitable for gather "
+ "load %G" :
+ "not vectorized: not suitable for scatter "
+ "store %G",
+ stmt_info->stmt);
return false;
}
STMT_VINFO_GATHER_SCATTER_P (stmt_info) = gatherscatter;
@@ -4471,18 +4322,18 @@ vect_get_new_ssa_name (tree type, enum vect_var_kind var_kind, const char *name)
return new_vect_var;
}
-/* Duplicate ptr info and set alignment/misaligment on NAME from DR. */
+/* Duplicate ptr info and set alignment/misaligment on NAME from DR_INFO. */
static void
-vect_duplicate_ssa_name_ptr_info (tree name, data_reference *dr)
+vect_duplicate_ssa_name_ptr_info (tree name, dr_vec_info *dr_info)
{
- duplicate_ssa_name_ptr_info (name, DR_PTR_INFO (dr));
- int misalign = DR_MISALIGNMENT (dr);
+ duplicate_ssa_name_ptr_info (name, DR_PTR_INFO (dr_info->dr));
+ int misalign = DR_MISALIGNMENT (dr_info);
if (misalign == DR_MISALIGNMENT_UNKNOWN)
mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (name));
else
set_ptr_info_alignment (SSA_NAME_PTR_INFO (name),
- DR_TARGET_ALIGNMENT (dr), misalign);
+ DR_TARGET_ALIGNMENT (dr_info), misalign);
}
/* Function vect_create_addr_base_for_vector_ref.
@@ -4491,7 +4342,7 @@ vect_duplicate_ssa_name_ptr_info (tree name, data_reference *dr)
that will be accessed for a data reference.
Input:
- STMT: The statement containing the data reference.
+ STMT_INFO: The statement containing the data reference.
NEW_STMT_LIST: Must be initialized to NULL_TREE or a statement list.
OFFSET: Optional. If supplied, it is be added to the initial address.
LOOP: Specify relative to which loop-nest should the address be computed.
@@ -4520,13 +4371,13 @@ vect_duplicate_ssa_name_ptr_info (tree name, data_reference *dr)
FORNOW: We are only handling array accesses with step 1. */
tree
-vect_create_addr_base_for_vector_ref (gimple *stmt,
+vect_create_addr_base_for_vector_ref (stmt_vec_info stmt_info,
gimple_seq *new_stmt_list,
tree offset,
tree byte_offset)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
- struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
+ dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
+ struct data_reference *dr = dr_info->dr;
const char *base_name;
tree addr_base;
tree dest;
@@ -4534,7 +4385,7 @@ vect_create_addr_base_for_vector_ref (gimple *stmt,
tree vect_ptr_type;
tree step = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr)));
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- innermost_loop_behavior *drb = vect_dr_behavior (dr);
+ innermost_loop_behavior *drb = vect_dr_behavior (dr_info);
tree data_ref_base = unshare_expr (drb->base_address);
tree base_offset = unshare_expr (drb->offset);
@@ -4587,17 +4438,13 @@ vect_create_addr_base_for_vector_ref (gimple *stmt,
&& TREE_CODE (addr_base) == SSA_NAME
&& !SSA_NAME_PTR_INFO (addr_base))
{
- vect_duplicate_ssa_name_ptr_info (addr_base, dr);
+ vect_duplicate_ssa_name_ptr_info (addr_base, dr_info);
if (offset || byte_offset)
mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (addr_base));
}
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "created ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, addr_base);
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "created %T\n", addr_base);
return addr_base;
}
@@ -4606,26 +4453,26 @@ vect_create_addr_base_for_vector_ref (gimple *stmt,
/* Function vect_create_data_ref_ptr.
Create a new pointer-to-AGGR_TYPE variable (ap), that points to the first
- location accessed in the loop by STMT, along with the def-use update
+ location accessed in the loop by STMT_INFO, along with the def-use update
chain to appropriately advance the pointer through the loop iterations.
Also set aliasing information for the pointer. This pointer is used by
the callers to this function to create a memory reference expression for
vector load/store access.
Input:
- 1. STMT: a stmt that references memory. Expected to be of the form
+ 1. STMT_INFO: a stmt that references memory. Expected to be of the form
GIMPLE_ASSIGN <name, data-ref> or
GIMPLE_ASSIGN <data-ref, name>.
2. AGGR_TYPE: the type of the reference, which should be either a vector
or an array.
3. AT_LOOP: the loop where the vector memref is to be created.
4. OFFSET (optional): an offset to be added to the initial address accessed
- by the data-ref in STMT.
+ by the data-ref in STMT_INFO.
5. BSI: location where the new stmts are to be placed if there is no loop
6. ONLY_INIT: indicate if ap is to be updated in the loop, or remain
pointing to the initial address.
7. BYTE_OFFSET (optional, defaults to NULL): a byte offset to be added
- to the initial address accessed by the data-ref in STMT. This is
+ to the initial address accessed by the data-ref in STMT_INFO. This is
similar to OFFSET, but OFFSET is counted in elements, while BYTE_OFFSET
in bytes.
8. IV_STEP (optional, defaults to NULL): the amount that should be added
@@ -4655,20 +4502,16 @@ vect_create_addr_base_for_vector_ref (gimple *stmt,
Return the increment stmt that updates the pointer in PTR_INCR.
- 3. Set INV_P to true if the access pattern of the data reference in the
- vectorized loop is invariant. Set it to false otherwise.
-
- 4. Return the pointer. */
+ 3. Return the pointer. */
tree
-vect_create_data_ref_ptr (gimple *stmt, tree aggr_type, struct loop *at_loop,
- tree offset, tree *initial_address,
- gimple_stmt_iterator *gsi, gimple **ptr_incr,
- bool only_init, bool *inv_p, tree byte_offset,
- tree iv_step)
+vect_create_data_ref_ptr (stmt_vec_info stmt_info, tree aggr_type,
+ struct loop *at_loop, tree offset,
+ tree *initial_address, gimple_stmt_iterator *gsi,
+ gimple **ptr_incr, bool only_init,
+ tree byte_offset, tree iv_step)
{
const char *base_name;
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
struct loop *loop = NULL;
bool nested_in_vect_loop = false;
@@ -4680,13 +4523,13 @@ vect_create_data_ref_ptr (gimple *stmt, tree aggr_type, struct loop *at_loop,
edge pe = NULL;
basic_block new_bb;
tree aggr_ptr_init;
- struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
+ dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
+ struct data_reference *dr = dr_info->dr;
tree aptr;
gimple_stmt_iterator incr_gsi;
bool insert_after;
tree indx_before_incr, indx_after_incr;
gimple *incr;
- tree step;
bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
gcc_assert (iv_step != NULL_TREE
@@ -4696,8 +4539,8 @@ vect_create_data_ref_ptr (gimple *stmt, tree aggr_type, struct loop *at_loop,
if (loop_vinfo)
{
loop = LOOP_VINFO_LOOP (loop_vinfo);
- nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt);
- containing_loop = (gimple_bb (stmt))->loop_father;
+ nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt_info);
+ containing_loop = (gimple_bb (stmt_info->stmt))->loop_father;
pe = loop_preheader_edge (loop);
}
else
@@ -4707,14 +4550,6 @@ vect_create_data_ref_ptr (gimple *stmt, tree aggr_type, struct loop *at_loop,
*ptr_incr = NULL;
}
- /* Check the step (evolution) of the load in LOOP, and record
- whether it's invariant. */
- step = vect_dr_behavior (dr)->step;
- if (integer_zerop (step))
- *inv_p = true;
- else
- *inv_p = false;
-
/* Create an expression for the first address accessed by this load
in LOOP. */
base_name = get_name (DR_BASE_ADDRESS (dr));
@@ -4723,9 +4558,9 @@ vect_create_data_ref_ptr (gimple *stmt, tree aggr_type, struct loop *at_loop,
{
tree dr_base_type = TREE_TYPE (DR_BASE_OBJECT (dr));
dump_printf_loc (MSG_NOTE, vect_location,
- "create %s-pointer variable to type: ",
- get_tree_code_name (TREE_CODE (aggr_type)));
- dump_generic_expr (MSG_NOTE, TDF_SLIM, aggr_type);
+ "create %s-pointer variable to type: %T",
+ get_tree_code_name (TREE_CODE (aggr_type)),
+ aggr_type);
if (TREE_CODE (dr_base_type) == ARRAY_TYPE)
dump_printf (MSG_NOTE, " vectorizing an array ref: ");
else if (TREE_CODE (dr_base_type) == VECTOR_TYPE)
@@ -4734,8 +4569,7 @@ vect_create_data_ref_ptr (gimple *stmt, tree aggr_type, struct loop *at_loop,
dump_printf (MSG_NOTE, " vectorizing a record based array ref: ");
else
dump_printf (MSG_NOTE, " vectorizing a pointer ref: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_BASE_OBJECT (dr));
- dump_printf (MSG_NOTE, "\n");
+ dump_printf (MSG_NOTE, "%T\n", DR_BASE_OBJECT (dr));
}
/* (1) Create the new aggregate-pointer variable.
@@ -4750,10 +4584,9 @@ vect_create_data_ref_ptr (gimple *stmt, tree aggr_type, struct loop *at_loop,
/* Likewise for any of the data references in the stmt group. */
else if (DR_GROUP_SIZE (stmt_info) > 1)
{
- gimple *orig_stmt = DR_GROUP_FIRST_ELEMENT (stmt_info);
+ stmt_vec_info sinfo = DR_GROUP_FIRST_ELEMENT (stmt_info);
do
{
- stmt_vec_info sinfo = vinfo_for_stmt (orig_stmt);
struct data_reference *sdr = STMT_VINFO_DATA_REF (sinfo);
if (!alias_sets_conflict_p (get_alias_set (aggr_type),
get_alias_set (DR_REF (sdr))))
@@ -4761,9 +4594,9 @@ vect_create_data_ref_ptr (gimple *stmt, tree aggr_type, struct loop *at_loop,
need_ref_all = true;
break;
}
- orig_stmt = DR_GROUP_NEXT_ELEMENT (sinfo);
+ sinfo = DR_GROUP_NEXT_ELEMENT (sinfo);
}
- while (orig_stmt);
+ while (sinfo);
}
aggr_ptr_type = build_pointer_type_for_mode (aggr_type, ptr_mode,
need_ref_all);
@@ -4806,7 +4639,7 @@ vect_create_data_ref_ptr (gimple *stmt, tree aggr_type, struct loop *at_loop,
/* Create: (&(base[init_val+offset]+byte_offset) in the loop preheader. */
- new_temp = vect_create_addr_base_for_vector_ref (stmt, &new_stmt_list,
+ new_temp = vect_create_addr_base_for_vector_ref (stmt_info, &new_stmt_list,
offset, byte_offset);
if (new_stmt_list)
{
@@ -4831,15 +4664,17 @@ vect_create_data_ref_ptr (gimple *stmt, tree aggr_type, struct loop *at_loop,
aptr = aggr_ptr_init;
else
{
+ /* Accesses to invariant addresses should be handled specially
+ by the caller. */
+ tree step = vect_dr_behavior (dr_info)->step;
+ gcc_assert (!integer_zerop (step));
+
if (iv_step == NULL_TREE)
{
- /* The step of the aggregate pointer is the type size. */
+ /* The step of the aggregate pointer is the type size,
+ negated for downward accesses. */
iv_step = TYPE_SIZE_UNIT (aggr_type);
- /* One exception to the above is when the scalar step of the load in
- LOOP is zero. In this case the step here is also zero. */
- if (*inv_p)
- iv_step = size_zero_node;
- else if (tree_int_cst_sgn (step) == -1)
+ if (tree_int_cst_sgn (step) == -1)
iv_step = fold_build1 (NEGATE_EXPR, TREE_TYPE (iv_step), iv_step);
}
@@ -4850,13 +4685,13 @@ vect_create_data_ref_ptr (gimple *stmt, tree aggr_type, struct loop *at_loop,
aggr_ptr, loop, &incr_gsi, insert_after,
&indx_before_incr, &indx_after_incr);
incr = gsi_stmt (incr_gsi);
- set_vinfo_for_stmt (incr, new_stmt_vec_info (incr, loop_vinfo));
+ loop_vinfo->add_stmt (incr);
/* Copy the points-to information if it exists. */
if (DR_PTR_INFO (dr))
{
- vect_duplicate_ssa_name_ptr_info (indx_before_incr, dr);
- vect_duplicate_ssa_name_ptr_info (indx_after_incr, dr);
+ vect_duplicate_ssa_name_ptr_info (indx_before_incr, dr_info);
+ vect_duplicate_ssa_name_ptr_info (indx_after_incr, dr_info);
}
if (ptr_incr)
*ptr_incr = incr;
@@ -4880,13 +4715,13 @@ vect_create_data_ref_ptr (gimple *stmt, tree aggr_type, struct loop *at_loop,
containing_loop, &incr_gsi, insert_after, &indx_before_incr,
&indx_after_incr);
incr = gsi_stmt (incr_gsi);
- set_vinfo_for_stmt (incr, new_stmt_vec_info (incr, loop_vinfo));
+ loop_vinfo->add_stmt (incr);
/* Copy the points-to information if it exists. */
if (DR_PTR_INFO (dr))
{
- vect_duplicate_ssa_name_ptr_info (indx_before_incr, dr);
- vect_duplicate_ssa_name_ptr_info (indx_after_incr, dr);
+ vect_duplicate_ssa_name_ptr_info (indx_before_incr, dr_info);
+ vect_duplicate_ssa_name_ptr_info (indx_after_incr, dr_info);
}
if (ptr_incr)
*ptr_incr = incr;
@@ -4924,7 +4759,7 @@ vect_create_data_ref_ptr (gimple *stmt, tree aggr_type, struct loop *at_loop,
the loop. The increment amount across iterations is expected
to be vector_size.
BSI - location where the new update stmt is to be placed.
- STMT - the original scalar memory-access stmt that is being vectorized.
+ STMT_INFO - the original scalar memory-access stmt that is being vectorized.
BUMP - optional. The offset by which to bump the pointer. If not given,
the offset is assumed to be vector_size.
@@ -4934,9 +4769,8 @@ vect_create_data_ref_ptr (gimple *stmt, tree aggr_type, struct loop *at_loop,
tree
bump_vector_ptr (tree dataref_ptr, gimple *ptr_incr, gimple_stmt_iterator *gsi,
- gimple *stmt, tree bump)
+ stmt_vec_info stmt_info, tree bump)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
tree update = TYPE_SIZE_UNIT (vectype);
@@ -4954,7 +4788,7 @@ bump_vector_ptr (tree dataref_ptr, gimple *ptr_incr, gimple_stmt_iterator *gsi,
new_dataref_ptr = make_ssa_name (TREE_TYPE (dataref_ptr));
incr_stmt = gimple_build_assign (new_dataref_ptr, POINTER_PLUS_EXPR,
dataref_ptr, update);
- vect_finish_stmt_generation (stmt, incr_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, incr_stmt, gsi);
/* Copy the points-to information if it exists. */
if (DR_PTR_INFO (dr))
@@ -5149,7 +4983,7 @@ vect_grouped_store_supported (tree vectype, unsigned HOST_WIDE_INT count)
if (dump_enabled_p ())
dump_printf (MSG_MISSED_OPTIMIZATION,
- "permutaion op not supported by target.\n");
+ "permutation op not supported by target.\n");
return false;
}
@@ -5236,13 +5070,13 @@ vect_store_lanes_supported (tree vectype, unsigned HOST_WIDE_INT count,
void
vect_permute_store_chain (vec<tree> dr_chain,
unsigned int length,
- gimple *stmt,
+ stmt_vec_info stmt_info,
gimple_stmt_iterator *gsi,
vec<tree> *result_chain)
{
tree vect1, vect2, high, low;
gimple *perm_stmt;
- tree vectype = STMT_VINFO_VECTYPE (vinfo_for_stmt (stmt));
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
tree perm_mask_low, perm_mask_high;
tree data_ref;
tree perm3_mask_low, perm3_mask_high;
@@ -5301,7 +5135,7 @@ vect_permute_store_chain (vec<tree> dr_chain,
data_ref = make_temp_ssa_name (vectype, NULL, "vect_shuffle3_low");
perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR, vect1,
vect2, perm3_mask_low);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, perm_stmt, gsi);
vect1 = data_ref;
vect2 = dr_chain[2];
@@ -5312,7 +5146,7 @@ vect_permute_store_chain (vec<tree> dr_chain,
data_ref = make_temp_ssa_name (vectype, NULL, "vect_shuffle3_high");
perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR, vect1,
vect2, perm3_mask_high);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, perm_stmt, gsi);
(*result_chain)[j] = data_ref;
}
}
@@ -5351,7 +5185,7 @@ vect_permute_store_chain (vec<tree> dr_chain,
high = make_temp_ssa_name (vectype, NULL, "vect_inter_high");
perm_stmt = gimple_build_assign (high, VEC_PERM_EXPR, vect1,
vect2, perm_mask_high);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, perm_stmt, gsi);
(*result_chain)[2*j] = high;
/* Create interleaving stmt:
@@ -5361,7 +5195,7 @@ vect_permute_store_chain (vec<tree> dr_chain,
low = make_temp_ssa_name (vectype, NULL, "vect_inter_low");
perm_stmt = gimple_build_assign (low, VEC_PERM_EXPR, vect1,
vect2, perm_mask_low);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, perm_stmt, gsi);
(*result_chain)[2*j+1] = low;
}
memcpy (dr_chain.address (), result_chain->address (),
@@ -5386,12 +5220,12 @@ vect_permute_store_chain (vec<tree> dr_chain,
dr_explicit_realign_optimized.
The code above sets up a new (vector) pointer, pointing to the first
- location accessed by STMT, and a "floor-aligned" load using that pointer.
- It also generates code to compute the "realignment-token" (if the relevant
- target hook was defined), and creates a phi-node at the loop-header bb
- whose arguments are the result of the prolog-load (created by this
- function) and the result of a load that takes place in the loop (to be
- created by the caller to this function).
+ location accessed by STMT_INFO, and a "floor-aligned" load using that
+ pointer. It also generates code to compute the "realignment-token"
+ (if the relevant target hook was defined), and creates a phi-node at the
+ loop-header bb whose arguments are the result of the prolog-load (created
+ by this function) and the result of a load that takes place in the loop
+ (to be created by the caller to this function).
For the case of dr_explicit_realign_optimized:
The caller to this function uses the phi-result (msq) to create the
@@ -5410,8 +5244,8 @@ vect_permute_store_chain (vec<tree> dr_chain,
result = realign_load (msq, lsq, realignment_token);
Input:
- STMT - (scalar) load stmt to be vectorized. This load accesses
- a memory location that may be unaligned.
+ STMT_INFO - (scalar) load stmt to be vectorized. This load accesses
+ a memory location that may be unaligned.
BSI - place where new code is to be inserted.
ALIGNMENT_SUPPORT_SCHEME - which of the two misalignment handling schemes
is used.
@@ -5422,19 +5256,19 @@ vect_permute_store_chain (vec<tree> dr_chain,
Return value - the result of the loop-header phi node. */
tree
-vect_setup_realignment (gimple *stmt, gimple_stmt_iterator *gsi,
+vect_setup_realignment (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
tree *realignment_token,
enum dr_alignment_support alignment_support_scheme,
tree init_addr,
struct loop **at_loop)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
+ dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
+ struct data_reference *dr = dr_info->dr;
struct loop *loop = NULL;
edge pe = NULL;
- tree scalar_dest = gimple_assign_lhs (stmt);
+ tree scalar_dest = gimple_assign_lhs (stmt_info->stmt);
tree vec_dest;
gimple *inc;
tree ptr;
@@ -5445,16 +5279,15 @@ vect_setup_realignment (gimple *stmt, gimple_stmt_iterator *gsi,
gphi *phi_stmt;
tree msq = NULL_TREE;
gimple_seq stmts = NULL;
- bool inv_p;
bool compute_in_loop = false;
bool nested_in_vect_loop = false;
- struct loop *containing_loop = (gimple_bb (stmt))->loop_father;
+ struct loop *containing_loop = (gimple_bb (stmt_info->stmt))->loop_father;
struct loop *loop_for_initial_load = NULL;
if (loop_vinfo)
{
loop = LOOP_VINFO_LOOP (loop_vinfo);
- nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt);
+ nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt_info);
}
gcc_assert (alignment_support_scheme == dr_explicit_realign
@@ -5537,14 +5370,14 @@ vect_setup_realignment (gimple *stmt, gimple_stmt_iterator *gsi,
gcc_assert (!compute_in_loop);
vec_dest = vect_create_destination_var (scalar_dest, vectype);
- ptr = vect_create_data_ref_ptr (stmt, vectype, loop_for_initial_load,
- NULL_TREE, &init_addr, NULL, &inc,
- true, &inv_p);
+ ptr = vect_create_data_ref_ptr (stmt_info, vectype,
+ loop_for_initial_load, NULL_TREE,
+ &init_addr, NULL, &inc, true);
if (TREE_CODE (ptr) == SSA_NAME)
new_temp = copy_ssa_name (ptr);
else
new_temp = make_ssa_name (TREE_TYPE (ptr));
- unsigned int align = DR_TARGET_ALIGNMENT (dr);
+ unsigned int align = DR_TARGET_ALIGNMENT (dr_info);
new_stmt = gimple_build_assign
(new_temp, BIT_AND_EXPR, ptr,
build_int_cst (TREE_TYPE (ptr), -(HOST_WIDE_INT) align));
@@ -5581,7 +5414,7 @@ vect_setup_realignment (gimple *stmt, gimple_stmt_iterator *gsi,
if (!init_addr)
{
/* Generate the INIT_ADDR computation outside LOOP. */
- init_addr = vect_create_addr_base_for_vector_ref (stmt, &stmts,
+ init_addr = vect_create_addr_base_for_vector_ref (stmt_info, &stmts,
NULL_TREE);
if (loop)
{
@@ -5857,7 +5690,7 @@ vect_load_lanes_supported (tree vectype, unsigned HOST_WIDE_INT count,
static void
vect_permute_load_chain (vec<tree> dr_chain,
unsigned int length,
- gimple *stmt,
+ stmt_vec_info stmt_info,
gimple_stmt_iterator *gsi,
vec<tree> *result_chain)
{
@@ -5865,7 +5698,7 @@ vect_permute_load_chain (vec<tree> dr_chain,
tree perm_mask_even, perm_mask_odd;
tree perm3_mask_low, perm3_mask_high;
gimple *perm_stmt;
- tree vectype = STMT_VINFO_VECTYPE (vinfo_for_stmt (stmt));
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
unsigned int i, j, log_length = exact_log2 (length);
result_chain->quick_grow (length);
@@ -5908,7 +5741,7 @@ vect_permute_load_chain (vec<tree> dr_chain,
data_ref = make_temp_ssa_name (vectype, NULL, "vect_shuffle3_low");
perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR, first_vect,
second_vect, perm3_mask_low);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, perm_stmt, gsi);
/* Create interleaving stmt (high part of):
high = VEC_PERM_EXPR <first_vect, second_vect2, {k, 3 + k, 6 + k,
@@ -5918,7 +5751,7 @@ vect_permute_load_chain (vec<tree> dr_chain,
data_ref = make_temp_ssa_name (vectype, NULL, "vect_shuffle3_high");
perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR, first_vect,
second_vect, perm3_mask_high);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, perm_stmt, gsi);
(*result_chain)[k] = data_ref;
}
}
@@ -5953,7 +5786,7 @@ vect_permute_load_chain (vec<tree> dr_chain,
perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR,
first_vect, second_vect,
perm_mask_even);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, perm_stmt, gsi);
(*result_chain)[j/2] = data_ref;
/* data_ref = permute_odd (first_data_ref, second_data_ref); */
@@ -5961,7 +5794,7 @@ vect_permute_load_chain (vec<tree> dr_chain,
perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR,
first_vect, second_vect,
perm_mask_odd);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, perm_stmt, gsi);
(*result_chain)[j/2+length/2] = data_ref;
}
memcpy (dr_chain.address (), result_chain->address (),
@@ -6060,7 +5893,7 @@ vect_permute_load_chain (vec<tree> dr_chain,
static bool
vect_shift_permute_load_chain (vec<tree> dr_chain,
unsigned int length,
- gimple *stmt,
+ stmt_vec_info stmt_info,
gimple_stmt_iterator *gsi,
vec<tree> *result_chain)
{
@@ -6069,9 +5902,8 @@ vect_shift_permute_load_chain (vec<tree> dr_chain,
tree select_mask, shift1_mask, shift2_mask, shift3_mask, shift4_mask;
gimple *perm_stmt;
- tree vectype = STMT_VINFO_VECTYPE (vinfo_for_stmt (stmt));
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
unsigned int i;
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
unsigned HOST_WIDE_INT nelt, vf;
@@ -6161,26 +5993,26 @@ vect_shift_permute_load_chain (vec<tree> dr_chain,
perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR,
first_vect, first_vect,
perm2_mask1);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, perm_stmt, gsi);
vect[0] = data_ref;
data_ref = make_temp_ssa_name (vectype, NULL, "vect_shuffle2");
perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR,
second_vect, second_vect,
perm2_mask2);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, perm_stmt, gsi);
vect[1] = data_ref;
data_ref = make_temp_ssa_name (vectype, NULL, "vect_shift");
perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR,
vect[0], vect[1], shift1_mask);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, perm_stmt, gsi);
(*result_chain)[j/2 + length/2] = data_ref;
data_ref = make_temp_ssa_name (vectype, NULL, "vect_select");
perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR,
vect[0], vect[1], select_mask);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, perm_stmt, gsi);
(*result_chain)[j/2] = data_ref;
}
memcpy (dr_chain.address (), result_chain->address (),
@@ -6277,7 +6109,7 @@ vect_shift_permute_load_chain (vec<tree> dr_chain,
perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR,
dr_chain[k], dr_chain[k],
perm3_mask);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, perm_stmt, gsi);
vect[k] = data_ref;
}
@@ -6287,7 +6119,7 @@ vect_shift_permute_load_chain (vec<tree> dr_chain,
perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR,
vect[k % 3], vect[(k + 1) % 3],
shift1_mask);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, perm_stmt, gsi);
vect_shift[k] = data_ref;
}
@@ -6298,7 +6130,7 @@ vect_shift_permute_load_chain (vec<tree> dr_chain,
vect_shift[(4 - k) % 3],
vect_shift[(3 - k) % 3],
shift2_mask);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, perm_stmt, gsi);
vect[k] = data_ref;
}
@@ -6307,13 +6139,13 @@ vect_shift_permute_load_chain (vec<tree> dr_chain,
data_ref = make_temp_ssa_name (vectype, NULL, "vect_shift3");
perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR, vect[0],
vect[0], shift3_mask);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, perm_stmt, gsi);
(*result_chain)[nelt % 3] = data_ref;
data_ref = make_temp_ssa_name (vectype, NULL, "vect_shift4");
perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR, vect[1],
vect[1], shift4_mask);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, perm_stmt, gsi);
(*result_chain)[0] = data_ref;
return true;
}
@@ -6328,8 +6160,8 @@ vect_shift_permute_load_chain (vec<tree> dr_chain,
*/
void
-vect_transform_grouped_load (gimple *stmt, vec<tree> dr_chain, int size,
- gimple_stmt_iterator *gsi)
+vect_transform_grouped_load (stmt_vec_info stmt_info, vec<tree> dr_chain,
+ int size, gimple_stmt_iterator *gsi)
{
machine_mode mode;
vec<tree> result_chain = vNULL;
@@ -6342,36 +6174,37 @@ vect_transform_grouped_load (gimple *stmt, vec<tree> dr_chain, int size,
/* If reassociation width for vector type is 2 or greater target machine can
execute 2 or more vector instructions in parallel. Otherwise try to
get chain for loads group using vect_shift_permute_load_chain. */
- mode = TYPE_MODE (STMT_VINFO_VECTYPE (vinfo_for_stmt (stmt)));
+ mode = TYPE_MODE (STMT_VINFO_VECTYPE (stmt_info));
if (targetm.sched.reassociation_width (VEC_PERM_EXPR, mode) > 1
|| pow2p_hwi (size)
- || !vect_shift_permute_load_chain (dr_chain, size, stmt,
+ || !vect_shift_permute_load_chain (dr_chain, size, stmt_info,
gsi, &result_chain))
- vect_permute_load_chain (dr_chain, size, stmt, gsi, &result_chain);
- vect_record_grouped_load_vectors (stmt, result_chain);
+ vect_permute_load_chain (dr_chain, size, stmt_info, gsi, &result_chain);
+ vect_record_grouped_load_vectors (stmt_info, result_chain);
result_chain.release ();
}
/* RESULT_CHAIN contains the output of a group of grouped loads that were
- generated as part of the vectorization of STMT. Assign the statement
+ generated as part of the vectorization of STMT_INFO. Assign the statement
for each vector to the associated scalar statement. */
void
-vect_record_grouped_load_vectors (gimple *stmt, vec<tree> result_chain)
+vect_record_grouped_load_vectors (stmt_vec_info stmt_info,
+ vec<tree> result_chain)
{
- gimple *first_stmt = DR_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt));
- gimple *next_stmt, *new_stmt;
+ vec_info *vinfo = stmt_info->vinfo;
+ stmt_vec_info first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
unsigned int i, gap_count;
tree tmp_data_ref;
/* Put a permuted data-ref in the VECTORIZED_STMT field.
Since we scan the chain starting from it's first node, their order
corresponds the order of data-refs in RESULT_CHAIN. */
- next_stmt = first_stmt;
+ stmt_vec_info next_stmt_info = first_stmt_info;
gap_count = 1;
FOR_EACH_VEC_ELT (result_chain, i, tmp_data_ref)
{
- if (!next_stmt)
+ if (!next_stmt_info)
break;
/* Skip the gaps. Loads created for the gaps will be removed by dead
@@ -6380,47 +6213,45 @@ vect_record_grouped_load_vectors (gimple *stmt, vec<tree> result_chain)
DR_GROUP_GAP is the number of steps in elements from the previous
access (if there is no gap DR_GROUP_GAP is 1). We skip loads that
correspond to the gaps. */
- if (next_stmt != first_stmt
- && gap_count < DR_GROUP_GAP (vinfo_for_stmt (next_stmt)))
+ if (next_stmt_info != first_stmt_info
+ && gap_count < DR_GROUP_GAP (next_stmt_info))
{
gap_count++;
continue;
}
- while (next_stmt)
+ while (next_stmt_info)
{
- new_stmt = SSA_NAME_DEF_STMT (tmp_data_ref);
+ stmt_vec_info new_stmt_info = vinfo->lookup_def (tmp_data_ref);
/* We assume that if VEC_STMT is not NULL, this is a case of multiple
copies, and we put the new vector statement in the first available
RELATED_STMT. */
- if (!STMT_VINFO_VEC_STMT (vinfo_for_stmt (next_stmt)))
- STMT_VINFO_VEC_STMT (vinfo_for_stmt (next_stmt)) = new_stmt;
+ if (!STMT_VINFO_VEC_STMT (next_stmt_info))
+ STMT_VINFO_VEC_STMT (next_stmt_info) = new_stmt_info;
else
{
- if (!DR_GROUP_SAME_DR_STMT (vinfo_for_stmt (next_stmt)))
+ if (!DR_GROUP_SAME_DR_STMT (next_stmt_info))
{
- gimple *prev_stmt =
- STMT_VINFO_VEC_STMT (vinfo_for_stmt (next_stmt));
- gimple *rel_stmt =
- STMT_VINFO_RELATED_STMT (vinfo_for_stmt (prev_stmt));
- while (rel_stmt)
+ stmt_vec_info prev_stmt_info
+ = STMT_VINFO_VEC_STMT (next_stmt_info);
+ stmt_vec_info rel_stmt_info
+ = STMT_VINFO_RELATED_STMT (prev_stmt_info);
+ while (rel_stmt_info)
{
- prev_stmt = rel_stmt;
- rel_stmt =
- STMT_VINFO_RELATED_STMT (vinfo_for_stmt (rel_stmt));
+ prev_stmt_info = rel_stmt_info;
+ rel_stmt_info = STMT_VINFO_RELATED_STMT (rel_stmt_info);
}
- STMT_VINFO_RELATED_STMT (vinfo_for_stmt (prev_stmt)) =
- new_stmt;
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
}
}
- next_stmt = DR_GROUP_NEXT_ELEMENT (vinfo_for_stmt (next_stmt));
+ next_stmt_info = DR_GROUP_NEXT_ELEMENT (next_stmt_info);
gap_count = 1;
- /* If NEXT_STMT accesses the same DR as the previous statement,
+ /* If NEXT_STMT_INFO accesses the same DR as the previous statement,
put the same TMP_DATA_REF as its vectorized statement; otherwise
get the next data-ref from RESULT_CHAIN. */
- if (!next_stmt || !DR_GROUP_SAME_DR_STMT (vinfo_for_stmt (next_stmt)))
+ if (!next_stmt_info || !DR_GROUP_SAME_DR_STMT (next_stmt_info))
break;
}
}
@@ -6448,39 +6279,39 @@ vect_can_force_dr_alignment_p (const_tree decl, unsigned int alignment)
}
-/* Return whether the data reference DR is supported with respect to its
+/* Return whether the data reference DR_INFO is supported with respect to its
alignment.
If CHECK_ALIGNED_ACCESSES is TRUE, check if the access is supported even
it is aligned, i.e., check if it is possible to vectorize it with different
alignment. */
enum dr_alignment_support
-vect_supportable_dr_alignment (struct data_reference *dr,
+vect_supportable_dr_alignment (dr_vec_info *dr_info,
bool check_aligned_accesses)
{
- gimple *stmt = vect_dr_stmt (dr);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ data_reference *dr = dr_info->dr;
+ stmt_vec_info stmt_info = dr_info->stmt;
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
machine_mode mode = TYPE_MODE (vectype);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
struct loop *vect_loop = NULL;
bool nested_in_vect_loop = false;
- if (aligned_access_p (dr) && !check_aligned_accesses)
+ if (aligned_access_p (dr_info) && !check_aligned_accesses)
return dr_aligned;
/* For now assume all conditional loads/stores support unaligned
access without any special code. */
- if (is_gimple_call (stmt)
- && gimple_call_internal_p (stmt)
- && (gimple_call_internal_fn (stmt) == IFN_MASK_LOAD
- || gimple_call_internal_fn (stmt) == IFN_MASK_STORE))
- return dr_unaligned_supported;
+ if (gcall *stmt = dyn_cast <gcall *> (stmt_info->stmt))
+ if (gimple_call_internal_p (stmt)
+ && (gimple_call_internal_fn (stmt) == IFN_MASK_LOAD
+ || gimple_call_internal_fn (stmt) == IFN_MASK_STORE))
+ return dr_unaligned_supported;
if (loop_vinfo)
{
vect_loop = LOOP_VINFO_LOOP (loop_vinfo);
- nested_in_vect_loop = nested_in_vect_loop_p (vect_loop, stmt);
+ nested_in_vect_loop = nested_in_vect_loop_p (vect_loop, stmt_info);
}
/* Possibly unaligned access. */
@@ -6562,8 +6393,8 @@ vect_supportable_dr_alignment (struct data_reference *dr,
if (loop_vinfo
&& STMT_SLP_TYPE (stmt_info)
&& !multiple_p (LOOP_VINFO_VECT_FACTOR (loop_vinfo)
- * DR_GROUP_SIZE (vinfo_for_stmt
- (DR_GROUP_FIRST_ELEMENT (stmt_info))),
+ * (DR_GROUP_SIZE
+ (DR_GROUP_FIRST_ELEMENT (stmt_info))),
TYPE_VECTOR_SUBPARTS (vectype)))
;
else if (!loop_vinfo
@@ -6574,11 +6405,11 @@ vect_supportable_dr_alignment (struct data_reference *dr,
else
return dr_explicit_realign_optimized;
}
- if (!known_alignment_for_access_p (dr))
+ if (!known_alignment_for_access_p (dr_info))
is_packed = not_size_aligned (DR_REF (dr));
if (targetm.vectorize.support_vector_misalignment
- (mode, type, DR_MISALIGNMENT (dr), is_packed))
+ (mode, type, DR_MISALIGNMENT (dr_info), is_packed))
/* Can't software pipeline the loads, but can at least do them. */
return dr_unaligned_supported;
}
@@ -6587,11 +6418,11 @@ vect_supportable_dr_alignment (struct data_reference *dr,
bool is_packed = false;
tree type = (TREE_TYPE (DR_REF (dr)));
- if (!known_alignment_for_access_p (dr))
+ if (!known_alignment_for_access_p (dr_info))
is_packed = not_size_aligned (DR_REF (dr));
if (targetm.vectorize.support_vector_misalignment
- (mode, type, DR_MISALIGNMENT (dr), is_packed))
+ (mode, type, DR_MISALIGNMENT (dr_info), is_packed))
return dr_unaligned_supported;
}
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index 909f790..1c9701d 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -120,7 +120,7 @@ typedef tree (*elem_op_func) (gimple_stmt_iterator *,
tree, tree, tree, tree, tree, enum tree_code,
tree);
-static inline tree
+tree
tree_vec_extract (gimple_stmt_iterator *gsi, tree type,
tree t, tree bitsize, tree bitpos)
{
diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c
index 01d1850..a93c6ee 100644
--- a/gcc/tree-vect-loop-manip.c
+++ b/gcc/tree-vect-loop-manip.c
@@ -935,14 +935,16 @@ vect_set_loop_condition (struct loop *loop, loop_vec_info loop_vinfo,
loop_cond_gsi);
/* Remove old loop exit test. */
- gsi_remove (&loop_cond_gsi, true);
- free_stmt_vec_info (orig_cond);
+ stmt_vec_info orig_cond_info;
+ if (loop_vinfo
+ && (orig_cond_info = loop_vinfo->lookup_stmt (orig_cond)))
+ loop_vinfo->remove_stmt (orig_cond_info);
+ else
+ gsi_remove (&loop_cond_gsi, true);
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "New loop exit condition: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, cond_stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "New loop exit condition: %G",
+ cond_stmt);
}
/* Helper routine of slpeel_tree_duplicate_loop_to_edge_cfg.
@@ -1335,16 +1337,16 @@ find_loop_location (struct loop *loop)
return dump_user_location_t ();
}
-/* Return true if PHI defines an IV of the loop to be vectorized. */
+/* Return true if the phi described by STMT_INFO defines an IV of the
+ loop to be vectorized. */
static bool
-iv_phi_p (gphi *phi)
+iv_phi_p (stmt_vec_info stmt_info)
{
+ gphi *phi = as_a <gphi *> (stmt_info->stmt);
if (virtual_operand_p (PHI_RESULT (phi)))
return false;
- stmt_vec_info stmt_info = vinfo_for_stmt (phi);
- gcc_assert (stmt_info != NULL);
if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def
|| STMT_VINFO_DEF_TYPE (stmt_info) == vect_double_reduction_def)
return false;
@@ -1377,17 +1379,16 @@ vect_can_advance_ivs_p (loop_vec_info loop_vinfo)
tree evolution_part;
gphi *phi = gsi.phi ();
+ stmt_vec_info phi_info = loop_vinfo->lookup_stmt (phi);
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "Analyze phi: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, phi, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "Analyze phi: %G",
+ phi_info->stmt);
/* Skip virtual phi's. The data dependences that are associated with
virtual defs/uses (i.e., memory accesses) are analyzed elsewhere.
Skip reduction phis. */
- if (!iv_phi_p (phi))
+ if (!iv_phi_p (phi_info))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
@@ -1397,8 +1398,7 @@ vect_can_advance_ivs_p (loop_vec_info loop_vinfo)
/* Analyze the evolution function. */
- evolution_part
- = STMT_VINFO_LOOP_PHI_EVOLUTION_PART (vinfo_for_stmt (phi));
+ evolution_part = STMT_VINFO_LOOP_PHI_EVOLUTION_PART (phi_info);
if (evolution_part == NULL_TREE)
{
if (dump_enabled_p ())
@@ -1500,15 +1500,13 @@ vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo,
gphi *phi = gsi.phi ();
gphi *phi1 = gsi1.phi ();
+ stmt_vec_info phi_info = loop_vinfo->lookup_stmt (phi);
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "vect_update_ivs_after_vectorizer: phi: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, phi, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "vect_update_ivs_after_vectorizer: phi: %G", phi);
/* Skip reduction and virtual phis. */
- if (!iv_phi_p (phi))
+ if (!iv_phi_p (phi_info))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
@@ -1517,7 +1515,7 @@ vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo,
}
type = TREE_TYPE (gimple_phi_result (phi));
- step_expr = STMT_VINFO_LOOP_PHI_EVOLUTION_PART (vinfo_for_stmt (phi));
+ step_expr = STMT_VINFO_LOOP_PHI_EVOLUTION_PART (phi_info);
step_expr = unshare_expr (step_expr);
/* FORNOW: We do not support IVs whose evolution function is a polynomial
@@ -1559,19 +1557,19 @@ vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo,
static tree
get_misalign_in_elems (gimple **seq, loop_vec_info loop_vinfo)
{
- struct data_reference *dr = LOOP_VINFO_UNALIGNED_DR (loop_vinfo);
- gimple *dr_stmt = vect_dr_stmt (dr);
- stmt_vec_info stmt_info = vinfo_for_stmt (dr_stmt);
+ dr_vec_info *dr_info = LOOP_VINFO_UNALIGNED_DR (loop_vinfo);
+ stmt_vec_info stmt_info = dr_info->stmt;
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
- unsigned int target_align = DR_TARGET_ALIGNMENT (dr);
+ unsigned int target_align = DR_TARGET_ALIGNMENT (dr_info);
gcc_assert (target_align != 0);
- bool negative = tree_int_cst_compare (DR_STEP (dr), size_zero_node) < 0;
+ bool negative = tree_int_cst_compare (DR_STEP (dr_info->dr),
+ size_zero_node) < 0;
tree offset = (negative
? size_int (-TYPE_VECTOR_SUBPARTS (vectype) + 1)
: size_zero_node);
- tree start_addr = vect_create_addr_base_for_vector_ref (dr_stmt, seq,
+ tree start_addr = vect_create_addr_base_for_vector_ref (stmt_info, seq,
offset);
tree type = unsigned_type_for (TREE_TYPE (start_addr));
tree target_align_minus_1 = build_int_cst (type, target_align - 1);
@@ -1626,15 +1624,14 @@ static tree
vect_gen_prolog_loop_niters (loop_vec_info loop_vinfo,
basic_block bb, int *bound)
{
- struct data_reference *dr = LOOP_VINFO_UNALIGNED_DR (loop_vinfo);
+ dr_vec_info *dr_info = LOOP_VINFO_UNALIGNED_DR (loop_vinfo);
tree var;
tree niters_type = TREE_TYPE (LOOP_VINFO_NITERS (loop_vinfo));
gimple_seq stmts = NULL, new_stmts = NULL;
tree iters, iters_name;
- gimple *dr_stmt = vect_dr_stmt (dr);
- stmt_vec_info stmt_info = vinfo_for_stmt (dr_stmt);
+ stmt_vec_info stmt_info = dr_info->stmt;
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
- unsigned int target_align = DR_TARGET_ALIGNMENT (dr);
+ unsigned int target_align = DR_TARGET_ALIGNMENT (dr_info);
if (LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) > 0)
{
@@ -1659,7 +1656,8 @@ vect_gen_prolog_loop_niters (loop_vec_info loop_vinfo,
/* Create: (niters_type) ((align_in_elems - misalign_in_elems)
& (align_in_elems - 1)). */
- bool negative = tree_int_cst_compare (DR_STEP (dr), size_zero_node) < 0;
+ bool negative = tree_int_cst_compare (DR_STEP (dr_info->dr),
+ size_zero_node) < 0;
if (negative)
iters = fold_build2 (MINUS_EXPR, type, misalign_in_elems,
align_in_elems_tree);
@@ -1672,12 +1670,8 @@ vect_gen_prolog_loop_niters (loop_vec_info loop_vinfo,
}
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "niters for prolog loop: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, iters);
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "niters for prolog loop: %T\n", iters);
var = create_tmp_var (niters_type, "prolog_loop_niters");
iters_name = force_gimple_operand (iters, &new_stmts, false, var);
@@ -1753,8 +1747,8 @@ vect_update_inits_of_drs (loop_vec_info loop_vinfo, tree niters,
FOR_EACH_VEC_ELT (datarefs, i, dr)
{
- gimple *stmt = DR_STMT (dr);
- if (!STMT_VINFO_GATHER_SCATTER_P (vinfo_for_stmt (stmt)))
+ dr_vec_info *dr_info = loop_vinfo->lookup_dr (dr);
+ if (!STMT_VINFO_GATHER_SCATTER_P (dr_info->stmt))
vect_update_init_of_dr (dr, niters, code);
}
}
@@ -1796,12 +1790,9 @@ vect_prepare_for_masked_peels (loop_vec_info loop_vinfo)
}
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "misalignment for fully-masked loop: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, misalign_in_elems);
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "misalignment for fully-masked loop: %T\n",
+ misalign_in_elems);
LOOP_VINFO_MASK_SKIP_NITERS (loop_vinfo) = misalign_in_elems;
@@ -2089,7 +2080,8 @@ slpeel_update_phi_nodes_for_loops (loop_vec_info loop_vinfo,
tree arg = PHI_ARG_DEF_FROM_EDGE (orig_phi, first_latch_e);
/* Generate lcssa PHI node for the first loop. */
gphi *vect_phi = (loop == first) ? orig_phi : update_phi;
- if (create_lcssa_for_iv_phis || !iv_phi_p (vect_phi))
+ stmt_vec_info vect_phi_info = loop_vinfo->lookup_stmt (vect_phi);
+ if (create_lcssa_for_iv_phis || !iv_phi_p (vect_phi_info))
{
tree new_res = copy_ssa_name (PHI_RESULT (orig_phi));
gphi *lcssa_phi = create_phi_node (new_res, between_bb);
@@ -2774,9 +2766,9 @@ vect_create_cond_for_align_checks (loop_vec_info loop_vinfo,
tree *cond_expr,
gimple_seq *cond_expr_stmt_list)
{
- vec<gimple *> may_misalign_stmts
+ vec<stmt_vec_info> may_misalign_stmts
= LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo);
- gimple *ref_stmt;
+ stmt_vec_info stmt_info;
int mask = LOOP_VINFO_PTR_MASK (loop_vinfo);
tree mask_cst;
unsigned int i;
@@ -2797,23 +2789,22 @@ vect_create_cond_for_align_checks (loop_vec_info loop_vinfo,
/* Create expression (mask & (dr_1 || ... || dr_n)) where dr_i is the address
of the first vector of the i'th data reference. */
- FOR_EACH_VEC_ELT (may_misalign_stmts, i, ref_stmt)
+ FOR_EACH_VEC_ELT (may_misalign_stmts, i, stmt_info)
{
gimple_seq new_stmt_list = NULL;
tree addr_base;
tree addr_tmp_name;
tree new_or_tmp_name;
gimple *addr_stmt, *or_stmt;
- stmt_vec_info stmt_vinfo = vinfo_for_stmt (ref_stmt);
- tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
bool negative = tree_int_cst_compare
- (DR_STEP (STMT_VINFO_DATA_REF (stmt_vinfo)), size_zero_node) < 0;
+ (DR_STEP (STMT_VINFO_DATA_REF (stmt_info)), size_zero_node) < 0;
tree offset = negative
? size_int (-TYPE_VECTOR_SUBPARTS (vectype) + 1) : size_zero_node;
/* create: addr_tmp = (int)(address_of_first_vector) */
addr_base =
- vect_create_addr_base_for_vector_ref (ref_stmt, &new_stmt_list,
+ vect_create_addr_base_for_vector_ref (stmt_info, &new_stmt_list,
offset);
if (new_stmt_list != NULL)
gimple_seq_add_seq (cond_expr_stmt_list, new_stmt_list);
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 9b7147c..fdac10b 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -213,11 +213,10 @@ static bool
vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf,
vec<stmt_vec_info > *mask_producers)
{
+ vec_info *vinfo = stmt_info->vinfo;
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "==> examining statement: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt_info->stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "==> examining statement: %G",
+ stmt_info->stmt);
if (!vect_determine_vf_for_stmt_1 (stmt_info, false, vf, mask_producers))
return false;
@@ -225,31 +224,26 @@ vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf,
&& STMT_VINFO_RELATED_STMT (stmt_info))
{
gimple *pattern_def_seq = STMT_VINFO_PATTERN_DEF_SEQ (stmt_info);
- stmt_info = vinfo_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info));
+ stmt_info = STMT_VINFO_RELATED_STMT (stmt_info);
/* If a pattern statement has def stmts, analyze them too. */
for (gimple_stmt_iterator si = gsi_start (pattern_def_seq);
!gsi_end_p (si); gsi_next (&si))
{
- stmt_vec_info def_stmt_info = vinfo_for_stmt (gsi_stmt (si));
+ stmt_vec_info def_stmt_info = vinfo->lookup_stmt (gsi_stmt (si));
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "==> examining pattern def stmt: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM,
- def_stmt_info->stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "==> examining pattern def stmt: %G",
+ def_stmt_info->stmt);
if (!vect_determine_vf_for_stmt_1 (def_stmt_info, true,
vf, mask_producers))
return false;
}
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "==> examining pattern statement: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt_info->stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "==> examining pattern statement: %G",
+ stmt_info->stmt);
if (!vect_determine_vf_for_stmt_1 (stmt_info, true, vf, mask_producers))
return false;
}
@@ -306,12 +300,10 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
gsi_next (&si))
{
phi = si.phi ();
- stmt_info = vinfo_for_stmt (phi);
+ stmt_info = loop_vinfo->lookup_stmt (phi);
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "==> examining phi: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, phi, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "==> examining phi: %G",
+ phi);
gcc_assert (stmt_info);
@@ -322,35 +314,25 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
scalar_type = TREE_TYPE (PHI_RESULT (phi));
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "get vectype for scalar type: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, scalar_type);
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "get vectype for scalar type: %T\n",
+ scalar_type);
vectype = get_vectype_for_scalar_type (scalar_type);
if (!vectype)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: unsupported "
- "data-type ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- scalar_type);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: unsupported "
+ "data-type %T\n",
+ scalar_type);
return false;
}
STMT_VINFO_VECTYPE (stmt_info) = vectype;
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "vectype: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, vectype);
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "vectype: %T\n",
+ vectype);
if (dump_enabled_p ())
{
@@ -366,7 +348,7 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si);
gsi_next (&si))
{
- stmt_info = vinfo_for_stmt (gsi_stmt (si));
+ stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si));
if (!vect_determine_vf_for_stmt (stmt_info, &vectorization_factor,
&mask_producers))
return false;
@@ -431,13 +413,8 @@ vect_is_simple_iv_evolution (unsigned loop_nb, tree access_fn, tree * init,
init_expr = unshare_expr (initial_condition_in_loop_num (access_fn, loop_nb));
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "step: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, step_expr);
- dump_printf (MSG_NOTE, ", init: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, init_expr);
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "step: %T, init: %T\n",
+ step_expr, init_expr);
*init = init_expr;
*step = step_expr;
@@ -461,6 +438,40 @@ vect_is_simple_iv_evolution (unsigned loop_nb, tree access_fn, tree * init,
return true;
}
+/* Return true if PHI, described by STMT_INFO, is the inner PHI in
+ what we are assuming is a double reduction. For example, given
+ a structure like this:
+
+ outer1:
+ x_1 = PHI <x_4(outer2), ...>;
+ ...
+
+ inner:
+ x_2 = PHI <x_1(outer1), ...>;
+ ...
+ x_3 = ...;
+ ...
+
+ outer2:
+ x_4 = PHI <x_3(inner)>;
+ ...
+
+ outer loop analysis would treat x_1 as a double reduction phi and
+ this function would then return true for x_2. */
+
+static bool
+vect_inner_phi_in_double_reduction_p (stmt_vec_info stmt_info, gphi *phi)
+{
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
+ use_operand_p use_p;
+ ssa_op_iter op_iter;
+ FOR_EACH_PHI_ARG (use_p, phi, op_iter, SSA_OP_USE)
+ if (stmt_vec_info def_info = loop_vinfo->lookup_def (USE_FROM_PTR (use_p)))
+ if (STMT_VINFO_DEF_TYPE (def_info) == vect_double_reduction_def)
+ return true;
+ return false;
+}
+
/* Function vect_analyze_scalar_cycles_1.
Examine the cross iteration def-use cycles of scalar variables
@@ -473,7 +484,7 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
{
basic_block bb = loop->header;
tree init, step;
- auto_vec<gimple *, 64> worklist;
+ auto_vec<stmt_vec_info, 64> worklist;
gphi_iterator gsi;
bool double_reduc;
@@ -487,13 +498,10 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
gphi *phi = gsi.phi ();
tree access_fn = NULL;
tree def = PHI_RESULT (phi);
- stmt_vec_info stmt_vinfo = vinfo_for_stmt (phi);
+ stmt_vec_info stmt_vinfo = loop_vinfo->lookup_stmt (phi);
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "Analyze phi: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, phi, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "Analyze phi: %G", phi);
/* Skip virtual phi's. The data dependences that are associated with
virtual defs/uses (i.e., memory accesses) are analyzed elsewhere. */
@@ -508,12 +516,8 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
{
STRIP_NOPS (access_fn);
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "Access function of PHI: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, access_fn);
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Access function of PHI: %T\n", access_fn);
STMT_VINFO_LOOP_PHI_EVOLUTION_BASE_UNCHANGED (stmt_vinfo)
= initial_condition_in_loop_num (access_fn, loop->num);
STMT_VINFO_LOOP_PHI_EVOLUTION_PART (stmt_vinfo)
@@ -521,11 +525,12 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
}
if (!access_fn
+ || vect_inner_phi_in_double_reduction_p (stmt_vinfo, phi)
|| !vect_is_simple_iv_evolution (loop->num, access_fn, &init, &step)
|| (LOOP_VINFO_LOOP (loop_vinfo) != loop
&& TREE_CODE (step) != INTEGER_CST))
{
- worklist.safe_push (phi);
+ worklist.safe_push (stmt_vinfo);
continue;
}
@@ -542,23 +547,20 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
/* Second - identify all reductions and nested cycles. */
while (worklist.length () > 0)
{
- gimple *phi = worklist.pop ();
+ stmt_vec_info stmt_vinfo = worklist.pop ();
+ gphi *phi = as_a <gphi *> (stmt_vinfo->stmt);
tree def = PHI_RESULT (phi);
- stmt_vec_info stmt_vinfo = vinfo_for_stmt (phi);
- gimple *reduc_stmt;
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "Analyze phi: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, phi, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "Analyze phi: %G", phi);
gcc_assert (!virtual_operand_p (def)
&& STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_unknown_def_type);
- reduc_stmt = vect_force_simple_reduction (loop_vinfo, phi,
- &double_reduc, false);
- if (reduc_stmt)
+ stmt_vec_info reduc_stmt_info
+ = vect_force_simple_reduction (loop_vinfo, stmt_vinfo,
+ &double_reduc, false);
+ if (reduc_stmt_info)
{
if (double_reduc)
{
@@ -567,8 +569,8 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
"Detected double reduction.\n");
STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_double_reduction_def;
- STMT_VINFO_DEF_TYPE (vinfo_for_stmt (reduc_stmt)) =
- vect_double_reduction_def;
+ STMT_VINFO_DEF_TYPE (reduc_stmt_info)
+ = vect_double_reduction_def;
}
else
{
@@ -579,8 +581,7 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
"Detected vectorizable nested cycle.\n");
STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_nested_cycle;
- STMT_VINFO_DEF_TYPE (vinfo_for_stmt (reduc_stmt)) =
- vect_nested_cycle;
+ STMT_VINFO_DEF_TYPE (reduc_stmt_info) = vect_nested_cycle;
}
else
{
@@ -589,13 +590,13 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
"Detected reduction.\n");
STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_reduction_def;
- STMT_VINFO_DEF_TYPE (vinfo_for_stmt (reduc_stmt)) =
- vect_reduction_def;
+ STMT_VINFO_DEF_TYPE (reduc_stmt_info) = vect_reduction_def;
/* Store the reduction cycles for possible vectorization in
loop-aware SLP if it was not detected as reduction
chain. */
- if (! REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (reduc_stmt)))
- LOOP_VINFO_REDUCTIONS (loop_vinfo).safe_push (reduc_stmt);
+ if (! REDUC_GROUP_FIRST_ELEMENT (reduc_stmt_info))
+ LOOP_VINFO_REDUCTIONS (loop_vinfo).safe_push
+ (reduc_stmt_info);
}
}
}
@@ -648,28 +649,28 @@ vect_analyze_scalar_cycles (loop_vec_info loop_vinfo)
vect_analyze_scalar_cycles_1 (loop_vinfo, loop->inner);
}
-/* Transfer group and reduction information from STMT to its pattern stmt. */
+/* Transfer group and reduction information from STMT_INFO to its
+ pattern stmt. */
static void
-vect_fixup_reduc_chain (gimple *stmt)
+vect_fixup_reduc_chain (stmt_vec_info stmt_info)
{
- gimple *firstp = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt));
- gimple *stmtp;
- gcc_assert (!REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (firstp))
- && REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)));
- REDUC_GROUP_SIZE (vinfo_for_stmt (firstp))
- = REDUC_GROUP_SIZE (vinfo_for_stmt (stmt));
+ stmt_vec_info firstp = STMT_VINFO_RELATED_STMT (stmt_info);
+ stmt_vec_info stmtp;
+ gcc_assert (!REDUC_GROUP_FIRST_ELEMENT (firstp)
+ && REDUC_GROUP_FIRST_ELEMENT (stmt_info));
+ REDUC_GROUP_SIZE (firstp) = REDUC_GROUP_SIZE (stmt_info);
do
{
- stmtp = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt));
- REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmtp)) = firstp;
- stmt = REDUC_GROUP_NEXT_ELEMENT (vinfo_for_stmt (stmt));
- if (stmt)
- REDUC_GROUP_NEXT_ELEMENT (vinfo_for_stmt (stmtp))
- = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt));
+ stmtp = STMT_VINFO_RELATED_STMT (stmt_info);
+ REDUC_GROUP_FIRST_ELEMENT (stmtp) = firstp;
+ stmt_info = REDUC_GROUP_NEXT_ELEMENT (stmt_info);
+ if (stmt_info)
+ REDUC_GROUP_NEXT_ELEMENT (stmtp)
+ = STMT_VINFO_RELATED_STMT (stmt_info);
}
- while (stmt);
- STMT_VINFO_DEF_TYPE (vinfo_for_stmt (stmtp)) = vect_reduction_def;
+ while (stmt_info);
+ STMT_VINFO_DEF_TYPE (stmtp) = vect_reduction_def;
}
/* Fixup scalar cycles that now have their stmts detected as patterns. */
@@ -677,18 +678,18 @@ vect_fixup_reduc_chain (gimple *stmt)
static void
vect_fixup_scalar_cycles_with_patterns (loop_vec_info loop_vinfo)
{
- gimple *first;
+ stmt_vec_info first;
unsigned i;
FOR_EACH_VEC_ELT (LOOP_VINFO_REDUCTION_CHAINS (loop_vinfo), i, first)
- if (STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (first)))
+ if (STMT_VINFO_IN_PATTERN_P (first))
{
- gimple *next = REDUC_GROUP_NEXT_ELEMENT (vinfo_for_stmt (first));
+ stmt_vec_info next = REDUC_GROUP_NEXT_ELEMENT (first);
while (next)
{
- if (! STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (next)))
+ if (! STMT_VINFO_IN_PATTERN_P (next))
break;
- next = REDUC_GROUP_NEXT_ELEMENT (vinfo_for_stmt (next));
+ next = REDUC_GROUP_NEXT_ELEMENT (next);
}
/* If not all stmt in the chain are patterns try to handle
the chain without patterns. */
@@ -696,7 +697,7 @@ vect_fixup_scalar_cycles_with_patterns (loop_vec_info loop_vinfo)
{
vect_fixup_reduc_chain (first);
LOOP_VINFO_REDUCTION_CHAINS (loop_vinfo)[i]
- = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (first));
+ = STMT_VINFO_RELATED_STMT (first);
}
}
}
@@ -834,37 +835,34 @@ _loop_vec_info::_loop_vec_info (struct loop *loop_in, vec_info_shared *shared)
scalar_loop (NULL),
orig_loop_info (NULL)
{
- /* Create/Update stmt_info for all stmts in the loop. */
- basic_block *body = get_loop_body (loop);
- for (unsigned int i = 0; i < loop->num_nodes; i++)
+ /* CHECKME: We want to visit all BBs before their successors (except for
+ latch blocks, for which this assertion wouldn't hold). In the simple
+ case of the loop forms we allow, a dfs order of the BBs would the same
+ as reversed postorder traversal, so we are safe. */
+
+ unsigned int nbbs = dfs_enumerate_from (loop->header, 0, bb_in_loop_p,
+ bbs, loop->num_nodes, loop);
+ gcc_assert (nbbs == loop->num_nodes);
+
+ for (unsigned int i = 0; i < nbbs; i++)
{
- basic_block bb = body[i];
+ basic_block bb = bbs[i];
gimple_stmt_iterator si;
for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
{
gimple *phi = gsi_stmt (si);
gimple_set_uid (phi, 0);
- set_vinfo_for_stmt (phi, new_stmt_vec_info (phi, this));
+ add_stmt (phi);
}
for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
{
gimple *stmt = gsi_stmt (si);
gimple_set_uid (stmt, 0);
- set_vinfo_for_stmt (stmt, new_stmt_vec_info (stmt, this));
+ add_stmt (stmt);
}
}
- free (body);
-
- /* CHECKME: We want to visit all BBs before their successors (except for
- latch blocks, for which this assertion wouldn't hold). In the simple
- case of the loop forms we allow, a dfs order of the BBs would the same
- as reversed postorder traversal, so we are safe. */
-
- unsigned int nbbs = dfs_enumerate_from (loop->header, 0, bb_in_loop_p,
- bbs, loop->num_nodes, loop);
- gcc_assert (nbbs == loop->num_nodes);
}
/* Free all levels of MASKS. */
@@ -888,15 +886,10 @@ _loop_vec_info::~_loop_vec_info ()
gimple_stmt_iterator si;
int j;
- /* ??? We're releasing loop_vinfos en-block. */
- set_stmt_vec_info_vec (&stmt_vec_infos);
nbbs = loop->num_nodes;
for (j = 0; j < nbbs; j++)
{
basic_block bb = bbs[j];
- for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
- free_stmt_vec_info (gsi_stmt (si));
-
for (si = gsi_start_bb (bb); !gsi_end_p (si); )
{
gimple *stmt = gsi_stmt (si);
@@ -936,9 +929,6 @@ _loop_vec_info::~_loop_vec_info ()
}
}
}
-
- /* Free stmt_vec_info. */
- free_stmt_vec_info (stmt);
gsi_next (&si);
}
}
@@ -1101,7 +1091,7 @@ vect_compute_single_scalar_iteration_cost (loop_vec_info loop_vinfo)
for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
{
gimple *stmt = gsi_stmt (si);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (stmt);
if (!is_gimple_assign (stmt) && !is_gimple_call (stmt))
continue;
@@ -1136,13 +1126,9 @@ vect_compute_single_scalar_iteration_cost (loop_vec_info loop_vinfo)
int j;
FOR_EACH_VEC_ELT (LOOP_VINFO_SCALAR_ITERATION_COST (loop_vinfo),
j, si)
- {
- struct _stmt_vec_info *stmt_info
- = si->stmt ? vinfo_for_stmt (si->stmt) : NULL;
- (void) add_stmt_cost (target_cost_data, si->count,
- si->kind, stmt_info, si->misalign,
- vect_body);
- }
+ (void) add_stmt_cost (target_cost_data, si->count,
+ si->kind, si->stmt_info, si->misalign,
+ vect_body);
unsigned dummy, body_cost = 0;
finish_cost (target_cost_data, &dummy, &body_cost, &dummy);
destroy_cost_data (target_cost_data);
@@ -1390,10 +1376,14 @@ vect_analyze_loop_form (struct loop *loop, vec_info_shared *shared)
}
}
- STMT_VINFO_TYPE (vinfo_for_stmt (loop_cond)) = loop_exit_ctrl_vec_info_type;
+ stmt_vec_info loop_cond_info = loop_vinfo->lookup_stmt (loop_cond);
+ STMT_VINFO_TYPE (loop_cond_info) = loop_exit_ctrl_vec_info_type;
if (inner_loop_cond)
- STMT_VINFO_TYPE (vinfo_for_stmt (inner_loop_cond))
- = loop_exit_ctrl_vec_info_type;
+ {
+ stmt_vec_info inner_loop_cond_info
+ = loop_vinfo->lookup_stmt (inner_loop_cond);
+ STMT_VINFO_TYPE (inner_loop_cond_info) = loop_exit_ctrl_vec_info_type;
+ }
gcc_assert (!loop->aux);
loop->aux = loop_vinfo;
@@ -1431,14 +1421,8 @@ vect_update_vf_for_slp (loop_vec_info loop_vinfo)
for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si);
gsi_next (&si))
{
- gimple *stmt = gsi_stmt (si);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
- if (STMT_VINFO_IN_PATTERN_P (stmt_info)
- && STMT_VINFO_RELATED_STMT (stmt_info))
- {
- stmt = STMT_VINFO_RELATED_STMT (stmt_info);
- stmt_info = vinfo_for_stmt (stmt);
- }
+ stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si));
+ stmt_info = vect_stmt_to_vectorize (stmt_info);
if ((STMT_VINFO_RELEVANT_P (stmt_info)
|| VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info)))
&& !PURE_SLP_STMT (stmt_info))
@@ -1498,8 +1482,7 @@ vect_active_double_reduction_p (stmt_vec_info stmt_info)
if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_double_reduction_def)
return false;
- gimple *other_phi = STMT_VINFO_REDUC_DEF (stmt_info);
- return STMT_VINFO_RELEVANT_P (vinfo_for_stmt (other_phi));
+ return STMT_VINFO_RELEVANT_P (STMT_VINFO_REDUC_DEF (stmt_info));
}
/* Function vect_analyze_loop_operations.
@@ -1532,12 +1515,9 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo)
gphi *phi = si.phi ();
ok = true;
- stmt_info = vinfo_for_stmt (phi);
+ stmt_info = loop_vinfo->lookup_stmt (phi);
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "examining phi: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, phi, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "examining phi: %G", phi);
if (virtual_operand_p (gimple_phi_result (phi)))
continue;
@@ -1564,26 +1544,19 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo)
if (STMT_VINFO_RELEVANT_P (stmt_info))
{
tree phi_op;
- gimple *op_def_stmt;
if (gimple_phi_num_args (phi) != 1)
return false;
phi_op = PHI_ARG_DEF (phi, 0);
- if (TREE_CODE (phi_op) != SSA_NAME)
- return false;
-
- op_def_stmt = SSA_NAME_DEF_STMT (phi_op);
- if (gimple_nop_p (op_def_stmt)
- || !flow_bb_inside_loop_p (loop, gimple_bb (op_def_stmt))
- || !vinfo_for_stmt (op_def_stmt))
+ stmt_vec_info op_def_info = loop_vinfo->lookup_def (phi_op);
+ if (!op_def_info)
return false;
- if (STMT_VINFO_RELEVANT (vinfo_for_stmt (op_def_stmt))
- != vect_used_in_outer
- && STMT_VINFO_RELEVANT (vinfo_for_stmt (op_def_stmt))
- != vect_used_in_outer_by_reduction)
- return false;
+ if (STMT_VINFO_RELEVANT (op_def_info) != vect_used_in_outer
+ && (STMT_VINFO_RELEVANT (op_def_info)
+ != vect_used_in_outer_by_reduction))
+ return false;
}
continue;
@@ -1607,11 +1580,12 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo)
need_to_vectorize = true;
if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def
&& ! PURE_SLP_STMT (stmt_info))
- ok = vectorizable_induction (phi, NULL, NULL, NULL, &cost_vec);
+ ok = vectorizable_induction (stmt_info, NULL, NULL, NULL,
+ &cost_vec);
else if ((STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def
|| STMT_VINFO_DEF_TYPE (stmt_info) == vect_nested_cycle)
&& ! PURE_SLP_STMT (stmt_info))
- ok = vectorizable_reduction (phi, NULL, NULL, NULL, NULL,
+ ok = vectorizable_reduction (stmt_info, NULL, NULL, NULL, NULL,
&cost_vec);
}
@@ -1619,18 +1593,15 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo)
if (ok
&& STMT_VINFO_LIVE_P (stmt_info)
&& !PURE_SLP_STMT (stmt_info))
- ok = vectorizable_live_operation (phi, NULL, NULL, -1, NULL,
+ ok = vectorizable_live_operation (stmt_info, NULL, NULL, -1, NULL,
&cost_vec);
if (!ok)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: relevant phi not "
- "supported: ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, phi, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: relevant phi not "
+ "supported: %G", phi);
return false;
}
}
@@ -1640,8 +1611,9 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo)
{
gimple *stmt = gsi_stmt (si);
if (!gimple_clobber_p (stmt)
- && !vect_analyze_stmt (stmt, &need_to_vectorize, NULL, NULL,
- &cost_vec))
+ && !vect_analyze_stmt (loop_vinfo->lookup_stmt (stmt),
+ &need_to_vectorize,
+ NULL, NULL, &cost_vec))
return false;
}
} /* bbs */
@@ -1981,7 +1953,7 @@ start_over:
dump_printf_loc (MSG_NOTE, vect_location,
"vectorization_factor = ");
dump_dec (MSG_NOTE, vectorization_factor);
- dump_printf (MSG_NOTE, ", niters = " HOST_WIDE_INT_PRINT_DEC "\n",
+ dump_printf (MSG_NOTE, ", niters = %wd\n",
LOOP_VINFO_INT_NITERS (loop_vinfo));
}
@@ -2007,20 +1979,21 @@ start_over:
if (!ok)
return false;
- /* Do not invoke vect_enhance_data_refs_alignment for eplilogue
- vectorization. */
+ /* Do not invoke vect_enhance_data_refs_alignment for epilogue
+ vectorization, since we do not want to add extra peeling or
+ add versioning for alignment. */
if (!LOOP_VINFO_EPILOGUE_P (loop_vinfo))
- {
/* This pass will decide on using loop versioning and/or loop peeling in
order to enhance the alignment of data references in the loop. */
ok = vect_enhance_data_refs_alignment (loop_vinfo);
- if (!ok)
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "bad data alignment.\n");
- return false;
- }
+ else
+ ok = vect_verify_datarefs_alignment (loop_vinfo);
+ if (!ok)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "bad data alignment.\n");
+ return false;
}
if (slp)
@@ -2101,14 +2074,22 @@ start_over:
/* The main loop handles all iterations. */
LOOP_VINFO_PEELING_FOR_NITER (loop_vinfo) = false;
else if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
- && LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) > 0)
+ && LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) >= 0)
{
- if (!multiple_p (LOOP_VINFO_INT_NITERS (loop_vinfo)
- - LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo),
+ /* Work out the (constant) number of iterations that need to be
+ peeled for reasons other than niters. */
+ unsigned int peel_niter = LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo);
+ if (LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo))
+ peel_niter += 1;
+ if (!multiple_p (LOOP_VINFO_INT_NITERS (loop_vinfo) - peel_niter,
LOOP_VINFO_VECT_FACTOR (loop_vinfo)))
LOOP_VINFO_PEELING_FOR_NITER (loop_vinfo) = true;
}
else if (LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo)
+ /* ??? When peeling for gaps but not alignment, we could
+ try to check whether the (variable) niters is known to be
+ VF * N + 1. That's something of a niche case though. */
+ || LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo)
|| !LOOP_VINFO_VECT_FACTOR (loop_vinfo).is_constant (&const_vf)
|| ((tree_ctz (LOOP_VINFO_NITERS (loop_vinfo))
< (unsigned) exact_log2 (const_vf))
@@ -2152,9 +2133,8 @@ start_over:
/* Niters for peeled prolog loop. */
if (LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) < 0)
{
- struct data_reference *dr = LOOP_VINFO_UNALIGNED_DR (loop_vinfo);
- tree vectype
- = STMT_VINFO_VECTYPE (vinfo_for_stmt (vect_dr_stmt (dr)));
+ dr_vec_info *dr_info = LOOP_VINFO_UNALIGNED_DR (loop_vinfo);
+ tree vectype = STMT_VINFO_VECTYPE (dr_info->stmt);
niters_th += TYPE_VECTOR_SUBPARTS (vectype) - 1;
}
else
@@ -2194,11 +2174,10 @@ again:
FOR_EACH_VEC_ELT (LOOP_VINFO_SLP_INSTANCES (loop_vinfo), i, instance)
{
stmt_vec_info vinfo;
- vinfo = vinfo_for_stmt
- (SLP_TREE_SCALAR_STMTS (SLP_INSTANCE_TREE (instance))[0]);
+ vinfo = SLP_TREE_SCALAR_STMTS (SLP_INSTANCE_TREE (instance))[0];
if (! STMT_VINFO_GROUPED_ACCESS (vinfo))
continue;
- vinfo = vinfo_for_stmt (DR_GROUP_FIRST_ELEMENT (vinfo));
+ vinfo = DR_GROUP_FIRST_ELEMENT (vinfo);
unsigned int size = DR_GROUP_SIZE (vinfo);
tree vectype = STMT_VINFO_VECTYPE (vinfo);
if (! vect_store_lanes_supported (vectype, size, false)
@@ -2207,8 +2186,8 @@ again:
return false;
FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (instance), j, node)
{
- vinfo = vinfo_for_stmt (SLP_TREE_SCALAR_STMTS (node)[0]);
- vinfo = vinfo_for_stmt (DR_GROUP_FIRST_ELEMENT (vinfo));
+ vinfo = SLP_TREE_SCALAR_STMTS (node)[0];
+ vinfo = DR_GROUP_FIRST_ELEMENT (vinfo);
bool single_element_p = !DR_GROUP_NEXT_ELEMENT (vinfo);
size = DR_GROUP_SIZE (vinfo);
vectype = STMT_VINFO_VECTYPE (vinfo);
@@ -2229,7 +2208,7 @@ again:
LOOP_VINFO_VECT_FACTOR (loop_vinfo) = saved_vectorization_factor;
/* Free the SLP instances. */
FOR_EACH_VEC_ELT (LOOP_VINFO_SLP_INSTANCES (loop_vinfo), j, instance)
- vect_free_slp_instance (instance);
+ vect_free_slp_instance (instance, false);
LOOP_VINFO_SLP_INSTANCES (loop_vinfo).release ();
/* Reset SLP type to loop_vect on all stmts. */
for (i = 0; i < LOOP_VINFO_LOOP (loop_vinfo)->num_nodes; ++i)
@@ -2238,25 +2217,23 @@ again:
for (gimple_stmt_iterator si = gsi_start_phis (bb);
!gsi_end_p (si); gsi_next (&si))
{
- stmt_vec_info stmt_info = vinfo_for_stmt (gsi_stmt (si));
+ stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si));
STMT_SLP_TYPE (stmt_info) = loop_vect;
}
for (gimple_stmt_iterator si = gsi_start_bb (bb);
!gsi_end_p (si); gsi_next (&si))
{
- stmt_vec_info stmt_info = vinfo_for_stmt (gsi_stmt (si));
+ stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si));
STMT_SLP_TYPE (stmt_info) = loop_vect;
if (STMT_VINFO_IN_PATTERN_P (stmt_info))
{
gimple *pattern_def_seq = STMT_VINFO_PATTERN_DEF_SEQ (stmt_info);
- stmt_info = vinfo_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info));
+ stmt_info = STMT_VINFO_RELATED_STMT (stmt_info);
STMT_SLP_TYPE (stmt_info) = loop_vect;
for (gimple_stmt_iterator pi = gsi_start (pattern_def_seq);
!gsi_end_p (pi); gsi_next (&pi))
- {
- gimple *pstmt = gsi_stmt (pi);
- STMT_SLP_TYPE (vinfo_for_stmt (pstmt)) = loop_vect;
- }
+ STMT_SLP_TYPE (loop_vinfo->lookup_stmt (gsi_stmt (pi)))
+ = loop_vect;
}
}
}
@@ -2452,12 +2429,11 @@ static tree
neutral_op_for_slp_reduction (slp_tree slp_node, tree_code code,
bool reduc_chain)
{
- vec<gimple *> stmts = SLP_TREE_SCALAR_STMTS (slp_node);
- gimple *stmt = stmts[0];
- stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
+ vec<stmt_vec_info> stmts = SLP_TREE_SCALAR_STMTS (slp_node);
+ stmt_vec_info stmt_vinfo = stmts[0];
tree vector_type = STMT_VINFO_VECTYPE (stmt_vinfo);
tree scalar_type = TREE_TYPE (vector_type);
- struct loop *loop = gimple_bb (stmt)->loop_father;
+ struct loop *loop = gimple_bb (stmt_vinfo->stmt)->loop_father;
gcc_assert (loop);
switch (code)
@@ -2483,7 +2459,8 @@ neutral_op_for_slp_reduction (slp_tree slp_node, tree_code code,
has only a single initial value, so that value is neutral for
all statements. */
if (reduc_chain)
- return PHI_ARG_DEF_FROM_EDGE (stmt, loop_preheader_edge (loop));
+ return PHI_ARG_DEF_FROM_EDGE (stmt_vinfo->stmt,
+ loop_preheader_edge (loop));
return NULL_TREE;
default:
@@ -2497,10 +2474,23 @@ neutral_op_for_slp_reduction (slp_tree slp_node, tree_code code,
static void
report_vect_op (dump_flags_t msg_type, gimple *stmt, const char *msg)
{
- dump_printf_loc (msg_type, vect_location, "%s", msg);
- dump_gimple_stmt (msg_type, TDF_SLIM, stmt, 0);
+ dump_printf_loc (msg_type, vect_location, "%s%G", msg, stmt);
}
+/* DEF_STMT_INFO occurs in a loop that contains a potential reduction
+ operation. Return true if the results of DEF_STMT_INFO are something
+ that can be accumulated by such a reduction. */
+
+static bool
+vect_valid_reduction_input_p (stmt_vec_info def_stmt_info)
+{
+ return (is_gimple_assign (def_stmt_info->stmt)
+ || is_gimple_call (def_stmt_info->stmt)
+ || STMT_VINFO_DEF_TYPE (def_stmt_info) == vect_induction_def
+ || (gimple_code (def_stmt_info->stmt) == GIMPLE_PHI
+ && STMT_VINFO_DEF_TYPE (def_stmt_info) == vect_internal_def
+ && !is_loop_header_bb_p (gimple_bb (def_stmt_info->stmt))));
+}
/* Detect SLP reduction of the form:
@@ -2525,8 +2515,8 @@ vect_is_slp_reduction (loop_vec_info loop_info, gimple *phi,
struct loop *loop = (gimple_bb (phi))->loop_father;
struct loop *vect_loop = LOOP_VINFO_LOOP (loop_info);
enum tree_code code;
- gimple *current_stmt = NULL, *loop_use_stmt = NULL, *first, *next_stmt;
- stmt_vec_info use_stmt_info, current_stmt_info;
+ gimple *loop_use_stmt = NULL;
+ stmt_vec_info use_stmt_info, current_stmt_info = NULL;
tree lhs;
imm_use_iterator imm_iter;
use_operand_p use_p;
@@ -2587,19 +2577,18 @@ vect_is_slp_reduction (loop_vec_info loop_info, gimple *phi,
return false;
/* Insert USE_STMT into reduction chain. */
- use_stmt_info = vinfo_for_stmt (loop_use_stmt);
- if (current_stmt)
+ use_stmt_info = loop_info->lookup_stmt (loop_use_stmt);
+ if (current_stmt_info)
{
- current_stmt_info = vinfo_for_stmt (current_stmt);
- REDUC_GROUP_NEXT_ELEMENT (current_stmt_info) = loop_use_stmt;
+ REDUC_GROUP_NEXT_ELEMENT (current_stmt_info) = use_stmt_info;
REDUC_GROUP_FIRST_ELEMENT (use_stmt_info)
= REDUC_GROUP_FIRST_ELEMENT (current_stmt_info);
}
else
- REDUC_GROUP_FIRST_ELEMENT (use_stmt_info) = loop_use_stmt;
+ REDUC_GROUP_FIRST_ELEMENT (use_stmt_info) = use_stmt_info;
lhs = gimple_assign_lhs (loop_use_stmt);
- current_stmt = loop_use_stmt;
+ current_stmt_info = use_stmt_info;
size++;
}
@@ -2609,34 +2598,24 @@ vect_is_slp_reduction (loop_vec_info loop_info, gimple *phi,
/* Swap the operands, if needed, to make the reduction operand be the second
operand. */
lhs = PHI_RESULT (phi);
- next_stmt = REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (current_stmt));
- while (next_stmt)
+ stmt_vec_info next_stmt_info = REDUC_GROUP_FIRST_ELEMENT (current_stmt_info);
+ while (next_stmt_info)
{
+ gassign *next_stmt = as_a <gassign *> (next_stmt_info->stmt);
if (gimple_assign_rhs2 (next_stmt) == lhs)
{
tree op = gimple_assign_rhs1 (next_stmt);
- gimple *def_stmt = NULL;
-
- if (TREE_CODE (op) == SSA_NAME)
- def_stmt = SSA_NAME_DEF_STMT (op);
+ stmt_vec_info def_stmt_info = loop_info->lookup_def (op);
/* Check that the other def is either defined in the loop
("vect_internal_def"), or it's an induction (defined by a
loop-header phi-node). */
- if (def_stmt
- && gimple_bb (def_stmt)
- && flow_bb_inside_loop_p (loop, gimple_bb (def_stmt))
- && (is_gimple_assign (def_stmt)
- || is_gimple_call (def_stmt)
- || STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt))
- == vect_induction_def
- || (gimple_code (def_stmt) == GIMPLE_PHI
- && STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt))
- == vect_internal_def
- && !is_loop_header_bb_p (gimple_bb (def_stmt)))))
+ if (def_stmt_info
+ && flow_bb_inside_loop_p (loop, gimple_bb (def_stmt_info->stmt))
+ && vect_valid_reduction_input_p (def_stmt_info))
{
lhs = gimple_assign_lhs (next_stmt);
- next_stmt = REDUC_GROUP_NEXT_ELEMENT (vinfo_for_stmt (next_stmt));
+ next_stmt_info = REDUC_GROUP_NEXT_ELEMENT (next_stmt_info);
continue;
}
@@ -2645,31 +2624,18 @@ vect_is_slp_reduction (loop_vec_info loop_info, gimple *phi,
else
{
tree op = gimple_assign_rhs2 (next_stmt);
- gimple *def_stmt = NULL;
-
- if (TREE_CODE (op) == SSA_NAME)
- def_stmt = SSA_NAME_DEF_STMT (op);
+ stmt_vec_info def_stmt_info = loop_info->lookup_def (op);
/* Check that the other def is either defined in the loop
("vect_internal_def"), or it's an induction (defined by a
loop-header phi-node). */
- if (def_stmt
- && gimple_bb (def_stmt)
- && flow_bb_inside_loop_p (loop, gimple_bb (def_stmt))
- && (is_gimple_assign (def_stmt)
- || is_gimple_call (def_stmt)
- || STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt))
- == vect_induction_def
- || (gimple_code (def_stmt) == GIMPLE_PHI
- && STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt))
- == vect_internal_def
- && !is_loop_header_bb_p (gimple_bb (def_stmt)))))
+ if (def_stmt_info
+ && flow_bb_inside_loop_p (loop, gimple_bb (def_stmt_info->stmt))
+ && vect_valid_reduction_input_p (def_stmt_info))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "swapping oprnds: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, next_stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "swapping oprnds: %G",
+ next_stmt);
swap_ssa_operands (next_stmt,
gimple_assign_rhs1_ptr (next_stmt),
@@ -2684,13 +2650,14 @@ vect_is_slp_reduction (loop_vec_info loop_info, gimple *phi,
}
lhs = gimple_assign_lhs (next_stmt);
- next_stmt = REDUC_GROUP_NEXT_ELEMENT (vinfo_for_stmt (next_stmt));
+ next_stmt_info = REDUC_GROUP_NEXT_ELEMENT (next_stmt_info);
}
/* Save the chain for further analysis in SLP detection. */
- first = REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (current_stmt));
- LOOP_VINFO_REDUCTION_CHAINS (loop_info).safe_push (first);
- REDUC_GROUP_SIZE (vinfo_for_stmt (first)) = size;
+ stmt_vec_info first_stmt_info
+ = REDUC_GROUP_FIRST_ELEMENT (current_stmt_info);
+ LOOP_VINFO_REDUCTION_CHAINS (loop_info).safe_push (first_stmt_info);
+ REDUC_GROUP_SIZE (first_stmt_info) = size;
return true;
}
@@ -2800,10 +2767,7 @@ pop:
unsigned i;
std::pair<ssa_op_iter, use_operand_p> *x;
FOR_EACH_VEC_ELT (path, i, x)
- {
- dump_generic_expr (MSG_NOTE, TDF_SLIM, USE_FROM_PTR (x->second));
- dump_printf (MSG_NOTE, " ");
- }
+ dump_printf (MSG_NOTE, "%T ", USE_FROM_PTR (x->second));
dump_printf (MSG_NOTE, "\n");
}
@@ -2884,15 +2848,16 @@ pop:
*/
-static gimple *
-vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
+static stmt_vec_info
+vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info,
bool *double_reduc,
bool need_wrapping_integral_overflow,
enum vect_reduction_type *v_reduc_type)
{
+ gphi *phi = as_a <gphi *> (phi_info->stmt);
struct loop *loop = (gimple_bb (phi))->loop_father;
struct loop *vect_loop = LOOP_VINFO_LOOP (loop_info);
- gimple *def_stmt, *def1 = NULL, *def2 = NULL, *phi_use_stmt = NULL;
+ gimple *phi_use_stmt = NULL;
enum tree_code orig_code, code;
tree op1, op2, op3 = NULL_TREE, op4 = NULL_TREE;
tree type;
@@ -2945,22 +2910,22 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
if (TREE_CODE (loop_arg) != SSA_NAME)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "reduction: not ssa_name: ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, loop_arg);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "reduction: not ssa_name: %T\n", loop_arg);
return NULL;
}
- def_stmt = SSA_NAME_DEF_STMT (loop_arg);
- if (is_gimple_assign (def_stmt))
+ stmt_vec_info def_stmt_info = loop_info->lookup_def (loop_arg);
+ if (!def_stmt_info
+ || !flow_bb_inside_loop_p (loop, gimple_bb (def_stmt_info->stmt)))
+ return NULL;
+
+ if (gassign *def_stmt = dyn_cast <gassign *> (def_stmt_info->stmt))
{
name = gimple_assign_lhs (def_stmt);
phi_def = false;
}
- else if (gimple_code (def_stmt) == GIMPLE_PHI)
+ else if (gphi *def_stmt = dyn_cast <gphi *> (def_stmt_info->stmt))
{
name = PHI_RESULT (def_stmt);
phi_def = true;
@@ -2968,17 +2933,12 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
else
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "reduction: unhandled reduction operation: ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, def_stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "reduction: unhandled reduction operation: %G",
+ def_stmt_info->stmt);
return NULL;
}
- if (! flow_bb_inside_loop_p (loop, gimple_bb (def_stmt)))
- return NULL;
-
nloop_uses = 0;
auto_vec<gphi *, 3> lcphis;
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, name)
@@ -3004,6 +2964,7 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
defined in the inner loop. */
if (phi_def)
{
+ gphi *def_stmt = as_a <gphi *> (def_stmt_info->stmt);
op1 = PHI_ARG_DEF (def_stmt, 0);
if (gimple_phi_num_args (def_stmt) != 1
@@ -3016,12 +2977,13 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
return NULL;
}
- def1 = SSA_NAME_DEF_STMT (op1);
+ gimple *def1 = SSA_NAME_DEF_STMT (op1);
if (gimple_bb (def1)
&& flow_bb_inside_loop_p (loop, gimple_bb (def_stmt))
&& loop->inner
&& flow_bb_inside_loop_p (loop->inner, gimple_bb (def1))
&& is_gimple_assign (def1)
+ && is_a <gphi *> (phi_use_stmt)
&& flow_bb_inside_loop_p (loop->inner, gimple_bb (phi_use_stmt)))
{
if (dump_enabled_p ())
@@ -3029,7 +2991,7 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
"detected double reduction: ");
*double_reduc = true;
- return def_stmt;
+ return def_stmt_info;
}
return NULL;
@@ -3055,6 +3017,7 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
}
}
+ gassign *def_stmt = as_a <gassign *> (def_stmt_info->stmt);
bool nested_in_vect_loop = flow_loop_nested_p (vect_loop, loop);
code = orig_code = gimple_assign_rhs_code (def_stmt);
@@ -3130,27 +3093,14 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
if (dump_enabled_p ())
{
dump_printf_loc (MSG_NOTE, vect_location,
- "reduction: multiple types: operation type: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, type);
- dump_printf (MSG_NOTE, ", operands types: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM,
- TREE_TYPE (op1));
- dump_printf (MSG_NOTE, ",");
- dump_generic_expr (MSG_NOTE, TDF_SLIM,
- TREE_TYPE (op2));
+ "reduction: multiple types: operation type: "
+ "%T, operands types: %T,%T",
+ type, TREE_TYPE (op1), TREE_TYPE (op2));
if (op3)
- {
- dump_printf (MSG_NOTE, ",");
- dump_generic_expr (MSG_NOTE, TDF_SLIM,
- TREE_TYPE (op3));
- }
+ dump_printf (MSG_NOTE, ",%T", TREE_TYPE (op3));
if (op4)
- {
- dump_printf (MSG_NOTE, ",");
- dump_generic_expr (MSG_NOTE, TDF_SLIM,
- TREE_TYPE (op4));
- }
+ dump_printf (MSG_NOTE, ",%T", TREE_TYPE (op4));
dump_printf (MSG_NOTE, "\n");
}
@@ -3174,14 +3124,9 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
1) integer arithmetic and no trapv
2) floating point arithmetic, and special flags permit this optimization
3) nested cycle (i.e., outer loop vectorization). */
- if (TREE_CODE (op1) == SSA_NAME)
- def1 = SSA_NAME_DEF_STMT (op1);
-
- if (TREE_CODE (op2) == SSA_NAME)
- def2 = SSA_NAME_DEF_STMT (op2);
-
- if (code != COND_EXPR
- && ((!def1 || gimple_nop_p (def1)) && (!def2 || gimple_nop_p (def2))))
+ stmt_vec_info def1_info = loop_info->lookup_def (op1);
+ stmt_vec_info def2_info = loop_info->lookup_def (op2);
+ if (code != COND_EXPR && !def1_info && !def2_info)
{
if (dump_enabled_p ())
report_vect_op (MSG_NOTE, def_stmt, "reduction: no defs for operands: ");
@@ -3192,38 +3137,24 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
the other def is either defined in the loop ("vect_internal_def"),
or it's an induction (defined by a loop-header phi-node). */
- if (def2 && def2 == phi
+ if (def2_info
+ && def2_info->stmt == phi
&& (code == COND_EXPR
- || !def1 || gimple_nop_p (def1)
- || !flow_bb_inside_loop_p (loop, gimple_bb (def1))
- || (def1 && flow_bb_inside_loop_p (loop, gimple_bb (def1))
- && (is_gimple_assign (def1)
- || is_gimple_call (def1)
- || STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def1))
- == vect_induction_def
- || (gimple_code (def1) == GIMPLE_PHI
- && STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def1))
- == vect_internal_def
- && !is_loop_header_bb_p (gimple_bb (def1)))))))
+ || !def1_info
+ || !flow_bb_inside_loop_p (loop, gimple_bb (def1_info->stmt))
+ || vect_valid_reduction_input_p (def1_info)))
{
if (dump_enabled_p ())
report_vect_op (MSG_NOTE, def_stmt, "detected reduction: ");
- return def_stmt;
+ return def_stmt_info;
}
- if (def1 && def1 == phi
+ if (def1_info
+ && def1_info->stmt == phi
&& (code == COND_EXPR
- || !def2 || gimple_nop_p (def2)
- || !flow_bb_inside_loop_p (loop, gimple_bb (def2))
- || (def2 && flow_bb_inside_loop_p (loop, gimple_bb (def2))
- && (is_gimple_assign (def2)
- || is_gimple_call (def2)
- || STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def2))
- == vect_induction_def
- || (gimple_code (def2) == GIMPLE_PHI
- && STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def2))
- == vect_internal_def
- && !is_loop_header_bb_p (gimple_bb (def2)))))))
+ || !def2_info
+ || !flow_bb_inside_loop_p (loop, gimple_bb (def2_info->stmt))
+ || vect_valid_reduction_input_p (def2_info)))
{
if (! nested_in_vect_loop && orig_code != MINUS_EXPR)
{
@@ -3275,7 +3206,7 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
report_vect_op (MSG_NOTE, def_stmt, "detected reduction: ");
}
- return def_stmt;
+ return def_stmt_info;
}
/* Try to find SLP reduction chain. */
@@ -3288,23 +3219,22 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
report_vect_op (MSG_NOTE, def_stmt,
"reduction: detected reduction chain: ");
- return def_stmt;
+ return def_stmt_info;
}
/* Dissolve group eventually half-built by vect_is_slp_reduction. */
- gimple *first = REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (def_stmt));
+ stmt_vec_info first = REDUC_GROUP_FIRST_ELEMENT (def_stmt_info);
while (first)
{
- gimple *next = REDUC_GROUP_NEXT_ELEMENT (vinfo_for_stmt (first));
- REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (first)) = NULL;
- REDUC_GROUP_NEXT_ELEMENT (vinfo_for_stmt (first)) = NULL;
+ stmt_vec_info next = REDUC_GROUP_NEXT_ELEMENT (first);
+ REDUC_GROUP_FIRST_ELEMENT (first) = NULL;
+ REDUC_GROUP_NEXT_ELEMENT (first) = NULL;
first = next;
}
/* Look for the expression computing loop_arg from loop PHI result. */
- if (check_reduction_path (vect_location, loop, as_a <gphi *> (phi), loop_arg,
- code))
- return def_stmt;
+ if (check_reduction_path (vect_location, loop, phi, loop_arg, code))
+ return def_stmt_info;
if (dump_enabled_p ())
{
@@ -3319,25 +3249,24 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
in-place if it enables detection of more reductions. Arguments
as there. */
-gimple *
-vect_force_simple_reduction (loop_vec_info loop_info, gimple *phi,
+stmt_vec_info
+vect_force_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info,
bool *double_reduc,
bool need_wrapping_integral_overflow)
{
enum vect_reduction_type v_reduc_type;
- gimple *def = vect_is_simple_reduction (loop_info, phi, double_reduc,
- need_wrapping_integral_overflow,
- &v_reduc_type);
- if (def)
- {
- stmt_vec_info reduc_def_info = vinfo_for_stmt (phi);
- STMT_VINFO_REDUC_TYPE (reduc_def_info) = v_reduc_type;
- STMT_VINFO_REDUC_DEF (reduc_def_info) = def;
- reduc_def_info = vinfo_for_stmt (def);
- STMT_VINFO_REDUC_TYPE (reduc_def_info) = v_reduc_type;
- STMT_VINFO_REDUC_DEF (reduc_def_info) = phi;
- }
- return def;
+ stmt_vec_info def_info
+ = vect_is_simple_reduction (loop_info, phi_info, double_reduc,
+ need_wrapping_integral_overflow,
+ &v_reduc_type);
+ if (def_info)
+ {
+ STMT_VINFO_REDUC_TYPE (phi_info) = v_reduc_type;
+ STMT_VINFO_REDUC_DEF (phi_info) = def_info;
+ STMT_VINFO_REDUC_TYPE (def_info) = v_reduc_type;
+ STMT_VINFO_REDUC_DEF (def_info) = phi_info;
+ }
+ return def_info;
}
/* Calculate cost of peeling the loop PEEL_ITERS_PROLOGUE times. */
@@ -3382,24 +3311,16 @@ vect_get_known_peeling_cost (loop_vec_info loop_vinfo, int peel_iters_prologue,
int j;
if (peel_iters_prologue)
FOR_EACH_VEC_ELT (*scalar_cost_vec, j, si)
- {
- stmt_vec_info stmt_info
- = si->stmt ? vinfo_for_stmt (si->stmt) : NULL;
- retval += record_stmt_cost (prologue_cost_vec,
- si->count * peel_iters_prologue,
- si->kind, stmt_info, si->misalign,
- vect_prologue);
- }
+ retval += record_stmt_cost (prologue_cost_vec,
+ si->count * peel_iters_prologue,
+ si->kind, si->stmt_info, si->misalign,
+ vect_prologue);
if (*peel_iters_epilogue)
FOR_EACH_VEC_ELT (*scalar_cost_vec, j, si)
- {
- stmt_vec_info stmt_info
- = si->stmt ? vinfo_for_stmt (si->stmt) : NULL;
- retval += record_stmt_cost (epilogue_cost_vec,
- si->count * *peel_iters_epilogue,
- si->kind, stmt_info, si->misalign,
- vect_epilogue);
- }
+ retval += record_stmt_cost (epilogue_cost_vec,
+ si->count * *peel_iters_epilogue,
+ si->kind, si->stmt_info, si->misalign,
+ vect_epilogue);
return retval;
}
@@ -3535,13 +3456,9 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo,
int j;
FOR_EACH_VEC_ELT (LOOP_VINFO_SCALAR_ITERATION_COST (loop_vinfo),
j, si)
- {
- struct _stmt_vec_info *stmt_info
- = si->stmt ? vinfo_for_stmt (si->stmt) : NULL;
- (void) add_stmt_cost (target_cost_data, si->count,
- si->kind, stmt_info, si->misalign,
- vect_epilogue);
- }
+ (void) add_stmt_cost (target_cost_data, si->count,
+ si->kind, si->stmt_info, si->misalign,
+ vect_epilogue);
}
}
else if (npeel < 0)
@@ -3573,15 +3490,13 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo,
int j;
FOR_EACH_VEC_ELT (LOOP_VINFO_SCALAR_ITERATION_COST (loop_vinfo), j, si)
{
- struct _stmt_vec_info *stmt_info
- = si->stmt ? vinfo_for_stmt (si->stmt) : NULL;
(void) add_stmt_cost (target_cost_data,
si->count * peel_iters_prologue,
- si->kind, stmt_info, si->misalign,
+ si->kind, si->stmt_info, si->misalign,
vect_prologue);
(void) add_stmt_cost (target_cost_data,
si->count * peel_iters_epilogue,
- si->kind, stmt_info, si->misalign,
+ si->kind, si->stmt_info, si->misalign,
vect_epilogue);
}
}
@@ -3604,20 +3519,12 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo,
&epilogue_cost_vec);
FOR_EACH_VEC_ELT (prologue_cost_vec, j, si)
- {
- struct _stmt_vec_info *stmt_info
- = si->stmt ? vinfo_for_stmt (si->stmt) : NULL;
- (void) add_stmt_cost (data, si->count, si->kind, stmt_info,
- si->misalign, vect_prologue);
- }
+ (void) add_stmt_cost (data, si->count, si->kind, si->stmt_info,
+ si->misalign, vect_prologue);
FOR_EACH_VEC_ELT (epilogue_cost_vec, j, si)
- {
- struct _stmt_vec_info *stmt_info
- = si->stmt ? vinfo_for_stmt (si->stmt) : NULL;
- (void) add_stmt_cost (data, si->count, si->kind, stmt_info,
- si->misalign, vect_epilogue);
- }
+ (void) add_stmt_cost (data, si->count, si->kind, si->stmt_info,
+ si->misalign, vect_epilogue);
prologue_cost_vec.release ();
epilogue_cost_vec.release ();
@@ -3869,7 +3776,6 @@ vect_model_reduction_cost (stmt_vec_info stmt_info, internal_fn reduc_fn,
enum tree_code code;
optab optab;
tree vectype;
- gimple *orig_stmt;
machine_mode mode;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
struct loop *loop = NULL;
@@ -3885,12 +3791,9 @@ vect_model_reduction_cost (stmt_vec_info stmt_info, internal_fn reduc_fn,
vectype = STMT_VINFO_VECTYPE (stmt_info);
mode = TYPE_MODE (vectype);
- orig_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
+ stmt_vec_info orig_stmt_info = vect_orig_stmt (stmt_info);
- if (!orig_stmt)
- orig_stmt = STMT_VINFO_STMT (stmt_info);
-
- code = gimple_assign_rhs_code (orig_stmt);
+ code = gimple_assign_rhs_code (orig_stmt_info->stmt);
if (reduction_type == EXTRACT_LAST_REDUCTION
|| reduction_type == FOLD_LEFT_REDUCTION)
@@ -3935,7 +3838,7 @@ vect_model_reduction_cost (stmt_vec_info stmt_info, internal_fn reduc_fn,
We have a reduction operator that will reduce the vector in one statement.
Also requires scalar extract. */
- if (!loop || !nested_in_vect_loop_p (loop, orig_stmt))
+ if (!loop || !nested_in_vect_loop_p (loop, orig_stmt_info))
{
if (reduc_fn != IFN_LAST)
{
@@ -3986,7 +3889,7 @@ vect_model_reduction_cost (stmt_vec_info stmt_info, internal_fn reduc_fn,
{
int vec_size_in_bits = tree_to_uhwi (TYPE_SIZE (vectype));
tree bitsize =
- TYPE_SIZE (TREE_TYPE (gimple_assign_lhs (orig_stmt)));
+ TYPE_SIZE (TREE_TYPE (gimple_assign_lhs (orig_stmt_info->stmt)));
int element_bitsize = tree_to_uhwi (bitsize);
int nelements = vec_size_in_bits / element_bitsize;
@@ -4061,15 +3964,15 @@ vect_model_induction_cost (stmt_vec_info stmt_info, int ncopies,
/* Function get_initial_def_for_reduction
Input:
- STMT - a stmt that performs a reduction operation in the loop.
+ STMT_VINFO - a stmt that performs a reduction operation in the loop.
INIT_VAL - the initial value of the reduction variable
Output:
ADJUSTMENT_DEF - a tree that holds a value to be added to the final result
of the reduction (used for adjusting the epilog - see below).
- Return a vector variable, initialized according to the operation that STMT
- performs. This vector will be used as the initial value of the
- vector of partial results.
+ Return a vector variable, initialized according to the operation that
+ STMT_VINFO performs. This vector will be used as the initial value
+ of the vector of partial results.
Option1 (adjust in epilog): Initialize the vector as follows:
add/bit or/xor: [0,0,...,0,0]
@@ -4090,7 +3993,7 @@ vect_model_induction_cost (stmt_vec_info stmt_info, int ncopies,
for (i=0;i<n;i++)
s = s + a[i];
- STMT is 's = s + a[i]', and the reduction variable is 's'.
+ STMT_VINFO is 's = s + a[i]', and the reduction variable is 's'.
For a vector of 4 units, we want to return either [0,0,0,init_val],
or [0,0,0,0] and let the caller know that it needs to adjust
the result at the end by 'init_val'.
@@ -4102,21 +4005,18 @@ vect_model_induction_cost (stmt_vec_info stmt_info, int ncopies,
A cost model should help decide between these two schemes. */
tree
-get_initial_def_for_reduction (gimple *stmt, tree init_val,
+get_initial_def_for_reduction (stmt_vec_info stmt_vinfo, tree init_val,
tree *adjustment_def)
{
- stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
tree scalar_type = TREE_TYPE (init_val);
tree vectype = get_vectype_for_scalar_type (scalar_type);
- enum tree_code code = gimple_assign_rhs_code (stmt);
+ enum tree_code code = gimple_assign_rhs_code (stmt_vinfo->stmt);
tree def_for_init;
tree init_def;
- bool nested_in_vect_loop = false;
REAL_VALUE_TYPE real_init_val = dconst0;
int int_init_val = 0;
- gimple *def_stmt = NULL;
gimple_seq stmts = NULL;
gcc_assert (vectype);
@@ -4124,39 +4024,12 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val,
gcc_assert (POINTER_TYPE_P (scalar_type) || INTEGRAL_TYPE_P (scalar_type)
|| SCALAR_FLOAT_TYPE_P (scalar_type));
- if (nested_in_vect_loop_p (loop, stmt))
- nested_in_vect_loop = true;
- else
- gcc_assert (loop == (gimple_bb (stmt))->loop_father);
-
- /* In case of double reduction we only create a vector variable to be put
- in the reduction phi node. The actual statement creation is done in
- vect_create_epilog_for_reduction. */
- if (adjustment_def && nested_in_vect_loop
- && TREE_CODE (init_val) == SSA_NAME
- && (def_stmt = SSA_NAME_DEF_STMT (init_val))
- && gimple_code (def_stmt) == GIMPLE_PHI
- && flow_bb_inside_loop_p (loop, gimple_bb (def_stmt))
- && vinfo_for_stmt (def_stmt)
- && STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt))
- == vect_double_reduction_def)
- {
- *adjustment_def = NULL;
- return vect_create_destination_var (init_val, vectype);
- }
+ gcc_assert (nested_in_vect_loop_p (loop, stmt_vinfo)
+ || loop == (gimple_bb (stmt_vinfo->stmt))->loop_father);
vect_reduction_type reduction_type
= STMT_VINFO_VEC_REDUCTION_TYPE (stmt_vinfo);
- /* In case of a nested reduction do not use an adjustment def as
- that case is not supported by the epilogue generation correctly
- if ncopies is not one. */
- if (adjustment_def && nested_in_vect_loop)
- {
- *adjustment_def = NULL;
- return vect_get_vec_def_for_operand (init_val, stmt);
- }
-
switch (code)
{
case WIDEN_SUM_EXPR:
@@ -4221,7 +4094,7 @@ get_initial_def_for_reduction (gimple *stmt, tree init_val,
if (reduction_type != COND_REDUCTION
&& reduction_type != EXTRACT_LAST_REDUCTION)
{
- init_def = vect_get_vec_def_for_operand (init_val, stmt);
+ init_def = vect_get_vec_def_for_operand (init_val, stmt_vinfo);
break;
}
}
@@ -4250,9 +4123,8 @@ get_initial_defs_for_reduction (slp_tree slp_node,
unsigned int number_of_vectors,
bool reduc_chain, tree neutral_op)
{
- vec<gimple *> stmts = SLP_TREE_SCALAR_STMTS (slp_node);
- gimple *stmt = stmts[0];
- stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
+ vec<stmt_vec_info> stmts = SLP_TREE_SCALAR_STMTS (slp_node);
+ stmt_vec_info stmt_vinfo = stmts[0];
unsigned HOST_WIDE_INT nunits;
unsigned j, number_of_places_left_in_vector;
tree vector_type;
@@ -4269,7 +4141,7 @@ get_initial_defs_for_reduction (slp_tree slp_node,
gcc_assert (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def);
- loop = (gimple_bb (stmt))->loop_father;
+ loop = (gimple_bb (stmt_vinfo->stmt))->loop_father;
gcc_assert (loop);
edge pe = loop_preheader_edge (loop);
@@ -4302,7 +4174,7 @@ get_initial_defs_for_reduction (slp_tree slp_node,
elts.quick_grow (nunits);
for (j = 0; j < number_of_copies; j++)
{
- for (i = group_size - 1; stmts.iterate (i, &stmt); i--)
+ for (i = group_size - 1; stmts.iterate (i, &stmt_vinfo); i--)
{
tree op;
/* Get the def before the loop. In reduction chain we have only
@@ -4312,7 +4184,7 @@ get_initial_defs_for_reduction (slp_tree slp_node,
&& neutral_op)
op = neutral_op;
else
- op = PHI_ARG_DEF_FROM_EDGE (stmt, pe);
+ op = PHI_ARG_DEF_FROM_EDGE (stmt_vinfo->stmt, pe);
/* Create 'vect_ = {op0,op1,...,opn}'. */
number_of_places_left_in_vector--;
@@ -4414,7 +4286,7 @@ get_initial_defs_for_reduction (slp_tree slp_node,
VECT_DEFS is list of vector of partial results, i.e., the lhs's of vector
reduction statements.
- STMT is the scalar reduction stmt that is being vectorized.
+ STMT_INFO is the scalar reduction stmt that is being vectorized.
NCOPIES is > 1 in case the vectorization factor (VF) is bigger than the
number of elements that we can fit in a vectype (nunits). In this case
we have to generate more than one vector stmt - i.e - we need to "unroll"
@@ -4427,7 +4299,7 @@ get_initial_defs_for_reduction (slp_tree slp_node,
statement that is defined by REDUCTION_PHI.
DOUBLE_REDUC is TRUE if double reduction phi nodes should be handled.
SLP_NODE is an SLP node containing a group of reduction statements. The
- first one in this group is STMT.
+ first one in this group is STMT_INFO.
INDUC_VAL is for INTEGER_INDUC_COND_REDUCTION the value to use for the case
when the COND_EXPR is never true in the loop. For MAX_EXPR, it needs to
be smaller than any value of the IV in the loop, for MIN_EXPR larger than
@@ -4452,8 +4324,8 @@ get_initial_defs_for_reduction (slp_tree slp_node,
loop:
vec_def = phi <null, null> # REDUCTION_PHI
- VECT_DEF = vector_stmt # vectorized form of STMT
- s_loop = scalar_stmt # (scalar) STMT
+ VECT_DEF = vector_stmt # vectorized form of STMT_INFO
+ s_loop = scalar_stmt # (scalar) STMT_INFO
loop_exit:
s_out0 = phi <s_loop> # (scalar) EXIT_PHI
use <s_out0>
@@ -4463,8 +4335,8 @@ get_initial_defs_for_reduction (slp_tree slp_node,
loop:
vec_def = phi <vec_init, VECT_DEF> # REDUCTION_PHI
- VECT_DEF = vector_stmt # vectorized form of STMT
- s_loop = scalar_stmt # (scalar) STMT
+ VECT_DEF = vector_stmt # vectorized form of STMT_INFO
+ s_loop = scalar_stmt # (scalar) STMT_INFO
loop_exit:
s_out0 = phi <s_loop> # (scalar) EXIT_PHI
v_out1 = phi <VECT_DEF> # NEW_EXIT_PHI
@@ -4476,17 +4348,17 @@ get_initial_defs_for_reduction (slp_tree slp_node,
*/
static void
-vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
+vect_create_epilog_for_reduction (vec<tree> vect_defs,
+ stmt_vec_info stmt_info,
gimple *reduc_def_stmt,
int ncopies, internal_fn reduc_fn,
- vec<gimple *> reduction_phis,
+ vec<stmt_vec_info> reduction_phis,
bool double_reduc,
slp_tree slp_node,
slp_instance slp_node_instance,
tree induc_val, enum tree_code induc_code,
tree neutral_op)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
stmt_vec_info prev_phi_info;
tree vectype;
machine_mode mode;
@@ -4496,11 +4368,12 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
tree scalar_dest;
tree scalar_type;
gimple *new_phi = NULL, *phi;
+ stmt_vec_info phi_info;
gimple_stmt_iterator exit_gsi;
tree vec_dest;
tree new_temp = NULL_TREE, new_dest, new_name, new_scalar_dest;
gimple *epilog_stmt = NULL;
- enum tree_code code = gimple_assign_rhs_code (stmt);
+ enum tree_code code = gimple_assign_rhs_code (stmt_info->stmt);
gimple *exit_phi;
tree bitsize;
tree adjustment_def = NULL;
@@ -4509,11 +4382,11 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
tree orig_name, scalar_result;
imm_use_iterator imm_iter, phi_imm_iter;
use_operand_p use_p, phi_use_p;
- gimple *use_stmt, *orig_stmt, *reduction_phi = NULL;
+ gimple *use_stmt;
+ stmt_vec_info reduction_phi_info = NULL;
bool nested_in_vect_loop = false;
auto_vec<gimple *> new_phis;
- auto_vec<gimple *> inner_phis;
- enum vect_def_type dt = vect_unknown_def_type;
+ auto_vec<stmt_vec_info> inner_phis;
int j, i;
auto_vec<tree> scalar_results;
unsigned int group_size = 1, k, ratio;
@@ -4522,13 +4395,13 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
bool slp_reduc = false;
bool direct_slp_reduc;
tree new_phi_result;
- gimple *inner_phi = NULL;
+ stmt_vec_info inner_phi = NULL;
tree induction_index = NULL_TREE;
if (slp_node)
group_size = SLP_TREE_SCALAR_STMTS (slp_node).length ();
- if (nested_in_vect_loop_p (loop, stmt))
+ if (nested_in_vect_loop_p (loop, stmt_info))
{
outer_loop = loop;
loop = loop->inner;
@@ -4586,15 +4459,30 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
|| (induc_code == MIN_EXPR
&& tree_int_cst_lt (induc_val, initial_def))))
induc_val = initial_def;
- vect_is_simple_use (initial_def, loop_vinfo, &initial_def_dt);
- vec_initial_def = get_initial_def_for_reduction (stmt, initial_def,
- &adjustment_def);
+
+ if (double_reduc)
+ /* In case of double reduction we only create a vector variable
+ to be put in the reduction phi node. The actual statement
+ creation is done later in this function. */
+ vec_initial_def = vect_create_destination_var (initial_def, vectype);
+ else if (nested_in_vect_loop)
+ {
+ /* Do not use an adjustment def as that case is not supported
+ correctly if ncopies is not one. */
+ vect_is_simple_use (initial_def, loop_vinfo, &initial_def_dt);
+ vec_initial_def = vect_get_vec_def_for_operand (initial_def,
+ stmt_info);
+ }
+ else
+ vec_initial_def
+ = get_initial_def_for_reduction (stmt_info, initial_def,
+ &adjustment_def);
vec_initial_defs.create (1);
vec_initial_defs.quick_push (vec_initial_def);
}
/* Set phi nodes arguments. */
- FOR_EACH_VEC_ELT (reduction_phis, i, phi)
+ FOR_EACH_VEC_ELT (reduction_phis, i, phi_info)
{
tree vec_init_def = vec_initial_defs[i];
tree def = vect_defs[i];
@@ -4602,15 +4490,15 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
{
if (j != 0)
{
- phi = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (phi));
+ phi_info = STMT_VINFO_RELATED_STMT (phi_info);
if (nested_in_vect_loop)
vec_init_def
- = vect_get_vec_def_for_stmt_copy (initial_def_dt,
- vec_init_def);
+ = vect_get_vec_def_for_stmt_copy (loop_vinfo, vec_init_def);
}
/* Set the loop-entry arg of the reduction-phi. */
+ gphi *phi = as_a <gphi *> (phi_info->stmt);
if (STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info)
== INTEGER_INDUC_COND_REDUCTION)
{
@@ -4623,27 +4511,23 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
tree induc_val_vec
= build_vector_from_val (vec_init_def_type, induc_val);
- add_phi_arg (as_a <gphi *> (phi), induc_val_vec,
- loop_preheader_edge (loop), UNKNOWN_LOCATION);
+ add_phi_arg (phi, induc_val_vec, loop_preheader_edge (loop),
+ UNKNOWN_LOCATION);
}
else
- add_phi_arg (as_a <gphi *> (phi), vec_init_def,
- loop_preheader_edge (loop), UNKNOWN_LOCATION);
+ add_phi_arg (phi, vec_init_def, loop_preheader_edge (loop),
+ UNKNOWN_LOCATION);
/* Set the loop-latch arg for the reduction-phi. */
if (j > 0)
- def = vect_get_vec_def_for_stmt_copy (vect_unknown_def_type, def);
+ def = vect_get_vec_def_for_stmt_copy (loop_vinfo, def);
- add_phi_arg (as_a <gphi *> (phi), def, loop_latch_edge (loop),
- UNKNOWN_LOCATION);
+ add_phi_arg (phi, def, loop_latch_edge (loop), UNKNOWN_LOCATION);
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "transform reduction: created def-use cycle: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, phi, 0);
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, SSA_NAME_DEF_STMT (def), 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "transform reduction: created def-use cycle: %G%G",
+ phi, SSA_NAME_DEF_STMT (def));
}
}
@@ -4659,7 +4543,7 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
tree indx_before_incr, indx_after_incr;
poly_uint64 nunits_out = TYPE_VECTOR_SUBPARTS (vectype);
- gimple *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
+ gimple *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info)->stmt;
gcc_assert (gimple_assign_rhs_code (vec_stmt) == VEC_COND_EXPR);
int scalar_precision
@@ -4696,8 +4580,7 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
/* Create a vector phi node. */
tree new_phi_tree = make_ssa_name (cr_index_vector_type);
new_phi = create_phi_node (new_phi_tree, loop->header);
- set_vinfo_for_stmt (new_phi,
- new_stmt_vec_info (new_phi, loop_vinfo));
+ loop_vinfo->add_stmt (new_phi);
add_phi_arg (as_a <gphi *> (new_phi), vec_zero,
loop_preheader_edge (loop), UNKNOWN_LOCATION);
@@ -4722,10 +4605,8 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
gimple *index_condition = gimple_build_assign (induction_index,
index_cond_expr);
gsi_insert_before (&incr_gsi, index_condition, GSI_SAME_STMT);
- stmt_vec_info index_vec_info = new_stmt_vec_info (index_condition,
- loop_vinfo);
+ stmt_vec_info index_vec_info = loop_vinfo->add_stmt (index_condition);
STMT_VINFO_VECTYPE (index_vec_info) = cr_index_vector_type;
- set_vinfo_for_stmt (index_condition, index_vec_info);
/* Update the phi with the vec cond. */
add_phi_arg (as_a <gphi *> (new_phi), induction_index,
@@ -4772,17 +4653,17 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
{
tree new_def = copy_ssa_name (def);
phi = create_phi_node (new_def, exit_bb);
- set_vinfo_for_stmt (phi, new_stmt_vec_info (phi, loop_vinfo));
+ stmt_vec_info phi_info = loop_vinfo->add_stmt (phi);
if (j == 0)
new_phis.quick_push (phi);
else
{
- def = vect_get_vec_def_for_stmt_copy (dt, def);
- STMT_VINFO_RELATED_STMT (prev_phi_info) = phi;
+ def = vect_get_vec_def_for_stmt_copy (loop_vinfo, def);
+ STMT_VINFO_RELATED_STMT (prev_phi_info) = phi_info;
}
SET_PHI_ARG_DEF (phi, single_exit (loop)->dest_idx, def);
- prev_phi_info = vinfo_for_stmt (phi);
+ prev_phi_info = phi_info;
}
}
@@ -4795,26 +4676,24 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
inner_phis.create (vect_defs.length ());
FOR_EACH_VEC_ELT (new_phis, i, phi)
{
+ stmt_vec_info phi_info = loop_vinfo->lookup_stmt (phi);
tree new_result = copy_ssa_name (PHI_RESULT (phi));
gphi *outer_phi = create_phi_node (new_result, exit_bb);
SET_PHI_ARG_DEF (outer_phi, single_exit (loop)->dest_idx,
PHI_RESULT (phi));
- set_vinfo_for_stmt (outer_phi, new_stmt_vec_info (outer_phi,
- loop_vinfo));
- inner_phis.quick_push (phi);
+ prev_phi_info = loop_vinfo->add_stmt (outer_phi);
+ inner_phis.quick_push (phi_info);
new_phis[i] = outer_phi;
- prev_phi_info = vinfo_for_stmt (outer_phi);
- while (STMT_VINFO_RELATED_STMT (vinfo_for_stmt (phi)))
+ while (STMT_VINFO_RELATED_STMT (phi_info))
{
- phi = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (phi));
- new_result = copy_ssa_name (PHI_RESULT (phi));
+ phi_info = STMT_VINFO_RELATED_STMT (phi_info);
+ new_result = copy_ssa_name (PHI_RESULT (phi_info->stmt));
outer_phi = create_phi_node (new_result, exit_bb);
SET_PHI_ARG_DEF (outer_phi, single_exit (loop)->dest_idx,
- PHI_RESULT (phi));
- set_vinfo_for_stmt (outer_phi, new_stmt_vec_info (outer_phi,
- loop_vinfo));
- STMT_VINFO_RELATED_STMT (prev_phi_info) = outer_phi;
- prev_phi_info = vinfo_for_stmt (outer_phi);
+ PHI_RESULT (phi_info->stmt));
+ stmt_vec_info outer_phi_info = loop_vinfo->add_stmt (outer_phi);
+ STMT_VINFO_RELATED_STMT (prev_phi_info) = outer_phi_info;
+ prev_phi_info = outer_phi_info;
}
}
}
@@ -4830,27 +4709,21 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
Otherwise (it is a regular reduction) - the tree-code and scalar-def
are taken from STMT. */
- orig_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
- if (!orig_stmt)
- {
- /* Regular reduction */
- orig_stmt = stmt;
- }
- else
+ stmt_vec_info orig_stmt_info = vect_orig_stmt (stmt_info);
+ if (orig_stmt_info != stmt_info)
{
/* Reduction pattern */
- stmt_vec_info stmt_vinfo = vinfo_for_stmt (orig_stmt);
- gcc_assert (STMT_VINFO_IN_PATTERN_P (stmt_vinfo));
- gcc_assert (STMT_VINFO_RELATED_STMT (stmt_vinfo) == stmt);
+ gcc_assert (STMT_VINFO_IN_PATTERN_P (orig_stmt_info));
+ gcc_assert (STMT_VINFO_RELATED_STMT (orig_stmt_info) == stmt_info);
}
- code = gimple_assign_rhs_code (orig_stmt);
+ code = gimple_assign_rhs_code (orig_stmt_info->stmt);
/* For MINUS_EXPR the initial vector is [init_val,0,...,0], therefore,
partial results are added and not subtracted. */
if (code == MINUS_EXPR)
code = PLUS_EXPR;
- scalar_dest = gimple_assign_lhs (orig_stmt);
+ scalar_dest = gimple_assign_lhs (orig_stmt_info->stmt);
scalar_type = TREE_TYPE (scalar_dest);
scalar_results.create (group_size);
new_scalar_dest = vect_create_destination_var (scalar_dest, NULL);
@@ -4870,7 +4743,7 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
# b1 = phi <b2, b0>
a2 = operation (a1)
b2 = operation (b1) */
- slp_reduc = (slp_node && !REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)));
+ slp_reduc = (slp_node && !REDUC_GROUP_FIRST_ELEMENT (stmt_info));
/* True if we should implement SLP_REDUC using native reduction operations
instead of scalar operations. */
@@ -4885,7 +4758,7 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
we may end up with more than one vector result. Here we reduce them to
one vector. */
- if (REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) || direct_slp_reduc)
+ if (REDUC_GROUP_FIRST_ELEMENT (stmt_info) || direct_slp_reduc)
{
tree first_vect = PHI_RESULT (new_phis[0]);
gassign *new_vec_stmt = NULL;
@@ -4915,11 +4788,11 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
tree first_vect = PHI_RESULT (new_phis[0]);
gassign *new_vec_stmt = NULL;
vec_dest = vect_create_destination_var (scalar_dest, vectype);
- gimple *next_phi = new_phis[0];
+ stmt_vec_info next_phi_info = loop_vinfo->lookup_stmt (new_phis[0]);
for (int k = 1; k < ncopies; ++k)
{
- next_phi = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (next_phi));
- tree second_vect = PHI_RESULT (next_phi);
+ next_phi_info = STMT_VINFO_RELATED_STMT (next_phi_info);
+ tree second_vect = PHI_RESULT (next_phi_info->stmt);
tree tem = make_ssa_name (vec_dest, new_vec_stmt);
new_vec_stmt = gimple_build_assign (tem, code,
first_vect, second_vect);
@@ -5187,7 +5060,8 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
gcc_assert (pow2p_hwi (group_size));
slp_tree orig_phis_slp_node = slp_node_instance->reduc_phis;
- vec<gimple *> orig_phis = SLP_TREE_SCALAR_STMTS (orig_phis_slp_node);
+ vec<stmt_vec_info> orig_phis
+ = SLP_TREE_SCALAR_STMTS (orig_phis_slp_node);
gimple_seq seq = NULL;
/* Build a vector {0, 1, 2, ...}, with the same number of elements
@@ -5218,7 +5092,7 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
if (!neutral_op)
{
tree scalar_value
- = PHI_ARG_DEF_FROM_EDGE (orig_phis[i],
+ = PHI_ARG_DEF_FROM_EDGE (orig_phis[i]->stmt,
loop_preheader_edge (loop));
vector_identity = gimple_build_vector_from_val (&seq, vectype,
scalar_value);
@@ -5263,6 +5137,9 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
if (STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info)
== INTEGER_INDUC_COND_REDUCTION)
code = induc_code;
+ else if (STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info)
+ == CONST_COND_REDUCTION)
+ code = STMT_VINFO_VEC_CONST_COND_REDUC_CODE (stmt_info);
else
code = MAX_EXPR;
}
@@ -5584,10 +5461,9 @@ vect_finalize_reduction:
gsi_insert_before (&exit_gsi, epilog_stmt, GSI_SAME_STMT);
if (nested_in_vect_loop)
{
- set_vinfo_for_stmt (epilog_stmt,
- new_stmt_vec_info (epilog_stmt, loop_vinfo));
- STMT_VINFO_RELATED_STMT (vinfo_for_stmt (epilog_stmt)) =
- STMT_VINFO_RELATED_STMT (vinfo_for_stmt (new_phi));
+ stmt_vec_info epilog_stmt_info = loop_vinfo->add_stmt (epilog_stmt);
+ STMT_VINFO_RELATED_STMT (epilog_stmt_info)
+ = STMT_VINFO_RELATED_STMT (loop_vinfo->lookup_stmt (new_phi));
if (!double_reduc)
scalar_results.quick_push (new_temp);
@@ -5630,14 +5506,11 @@ vect_finalize_reduction:
necessary, hence we set here REDUC_GROUP_SIZE to 1. SCALAR_DEST is the
LHS of the last stmt in the reduction chain, since we are looking for
the loop exit phi node. */
- if (REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)))
+ if (REDUC_GROUP_FIRST_ELEMENT (stmt_info))
{
- gimple *dest_stmt = SLP_TREE_SCALAR_STMTS (slp_node)[group_size - 1];
- /* Handle reduction patterns. */
- if (STMT_VINFO_RELATED_STMT (vinfo_for_stmt (dest_stmt)))
- dest_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (dest_stmt));
-
- scalar_dest = gimple_assign_lhs (dest_stmt);
+ stmt_vec_info dest_stmt_info
+ = vect_orig_stmt (SLP_TREE_SCALAR_STMTS (slp_node)[group_size - 1]);
+ scalar_dest = gimple_assign_lhs (dest_stmt_info->stmt);
group_size = 1;
}
@@ -5655,24 +5528,25 @@ vect_finalize_reduction:
else
ratio = 1;
+ stmt_vec_info epilog_stmt_info = NULL;
for (k = 0; k < group_size; k++)
{
if (k % ratio == 0)
{
- epilog_stmt = new_phis[k / ratio];
- reduction_phi = reduction_phis[k / ratio];
+ epilog_stmt_info = loop_vinfo->lookup_stmt (new_phis[k / ratio]);
+ reduction_phi_info = reduction_phis[k / ratio];
if (double_reduc)
inner_phi = inner_phis[k / ratio];
}
if (slp_reduc)
{
- gimple *current_stmt = SLP_TREE_SCALAR_STMTS (slp_node)[k];
+ stmt_vec_info scalar_stmt_info = SLP_TREE_SCALAR_STMTS (slp_node)[k];
- orig_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (current_stmt));
- /* SLP statements can't participate in patterns. */
- gcc_assert (!orig_stmt);
- scalar_dest = gimple_assign_lhs (current_stmt);
+ orig_stmt_info = STMT_VINFO_RELATED_STMT (scalar_stmt_info);
+ /* SLP statements can't participate in patterns. */
+ gcc_assert (!orig_stmt_info);
+ scalar_dest = gimple_assign_lhs (scalar_stmt_info->stmt);
}
phis.create (3);
@@ -5691,7 +5565,8 @@ vect_finalize_reduction:
{
if (outer_loop)
{
- stmt_vec_info exit_phi_vinfo = vinfo_for_stmt (exit_phi);
+ stmt_vec_info exit_phi_vinfo
+ = loop_vinfo->lookup_stmt (exit_phi);
gphi *vect_phi;
/* FORNOW. Currently not supporting the case that an inner-loop
@@ -5704,7 +5579,7 @@ vect_finalize_reduction:
if (double_reduc)
STMT_VINFO_VEC_STMT (exit_phi_vinfo) = inner_phi;
else
- STMT_VINFO_VEC_STMT (exit_phi_vinfo) = epilog_stmt;
+ STMT_VINFO_VEC_STMT (exit_phi_vinfo) = epilog_stmt_info;
if (!double_reduc
|| STMT_VINFO_DEF_TYPE (exit_phi_vinfo)
!= vect_double_reduction_def)
@@ -5728,10 +5603,8 @@ vect_finalize_reduction:
FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, orig_name)
{
stmt_vec_info use_stmt_vinfo;
- stmt_vec_info new_phi_vinfo;
tree vect_phi_init, preheader_arg, vect_phi_res;
basic_block bb = gimple_bb (use_stmt);
- gimple *use;
/* Check that USE_STMT is really double reduction phi
node. */
@@ -5739,7 +5612,7 @@ vect_finalize_reduction:
|| gimple_phi_num_args (use_stmt) != 2
|| bb->loop_father != outer_loop)
continue;
- use_stmt_vinfo = vinfo_for_stmt (use_stmt);
+ use_stmt_vinfo = loop_vinfo->lookup_stmt (use_stmt);
if (!use_stmt_vinfo
|| STMT_VINFO_DEF_TYPE (use_stmt_vinfo)
!= vect_double_reduction_def)
@@ -5755,41 +5628,38 @@ vect_finalize_reduction:
/* Create vector phi node. */
vect_phi = create_phi_node (vec_initial_def, bb);
- new_phi_vinfo = new_stmt_vec_info (vect_phi,
- loop_vec_info_for_loop (outer_loop));
- set_vinfo_for_stmt (vect_phi, new_phi_vinfo);
+ loop_vec_info_for_loop (outer_loop)->add_stmt (vect_phi);
/* Create vs0 - initial def of the double reduction phi. */
preheader_arg = PHI_ARG_DEF_FROM_EDGE (use_stmt,
loop_preheader_edge (outer_loop));
vect_phi_init = get_initial_def_for_reduction
- (stmt, preheader_arg, NULL);
+ (stmt_info, preheader_arg, NULL);
/* Update phi node arguments with vs0 and vs2. */
add_phi_arg (vect_phi, vect_phi_init,
loop_preheader_edge (outer_loop),
UNKNOWN_LOCATION);
- add_phi_arg (vect_phi, PHI_RESULT (inner_phi),
- loop_latch_edge (outer_loop), UNKNOWN_LOCATION);
+ add_phi_arg (vect_phi, PHI_RESULT (inner_phi->stmt),
+ loop_latch_edge (outer_loop), UNKNOWN_LOCATION);
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "created double reduction phi node: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, vect_phi, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "created double reduction phi node: %G",
+ vect_phi);
vect_phi_res = PHI_RESULT (vect_phi);
/* Replace the use, i.e., set the correct vs1 in the regular
reduction phi node. FORNOW, NCOPIES is always 1, so the
loop is redundant. */
- use = reduction_phi;
- for (j = 0; j < ncopies; j++)
- {
- edge pr_edge = loop_preheader_edge (loop);
- SET_PHI_ARG_DEF (use, pr_edge->dest_idx, vect_phi_res);
- use = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (use));
- }
+ stmt_vec_info use_info = reduction_phi_info;
+ for (j = 0; j < ncopies; j++)
+ {
+ edge pr_edge = loop_preheader_edge (loop);
+ SET_PHI_ARG_DEF (as_a <gphi *> (use_info->stmt),
+ pr_edge->dest_idx, vect_phi_res);
+ use_info = STMT_VINFO_RELATED_STMT (use_info);
+ }
}
}
}
@@ -5898,9 +5768,9 @@ vect_expand_fold_left (gimple_stmt_iterator *gsi, tree scalar_dest,
return lhs;
}
-/* Perform an in-order reduction (FOLD_LEFT_REDUCTION). STMT is the
+/* Perform an in-order reduction (FOLD_LEFT_REDUCTION). STMT_INFO is the
statement that sets the live-out value. REDUC_DEF_STMT is the phi
- statement. CODE is the operation performed by STMT and OPS are
+ statement. CODE is the operation performed by STMT_INFO and OPS are
its scalar operands. REDUC_INDEX is the index of the operand in
OPS that is set by REDUC_DEF_STMT. REDUC_FN is the function that
implements in-order reduction, or IFN_LAST if we should open-code it.
@@ -5908,18 +5778,18 @@ vect_expand_fold_left (gimple_stmt_iterator *gsi, tree scalar_dest,
that should be used to control the operation in a fully-masked loop. */
static bool
-vectorize_fold_left_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
- gimple **vec_stmt, slp_tree slp_node,
+vectorize_fold_left_reduction (stmt_vec_info stmt_info,
+ gimple_stmt_iterator *gsi,
+ stmt_vec_info *vec_stmt, slp_tree slp_node,
gimple *reduc_def_stmt,
tree_code code, internal_fn reduc_fn,
tree ops[3], tree vectype_in,
int reduc_index, vec_loop_masks *masks)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
tree vectype_out = STMT_VINFO_VECTYPE (stmt_info);
- gimple *new_stmt = NULL;
+ stmt_vec_info new_stmt_info = NULL;
int ncopies;
if (slp_node)
@@ -5927,7 +5797,7 @@ vectorize_fold_left_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
else
ncopies = vect_get_num_copies (loop_vinfo, vectype_in);
- gcc_assert (!nested_in_vect_loop_p (loop, stmt));
+ gcc_assert (!nested_in_vect_loop_p (loop, stmt_info));
gcc_assert (ncopies == 1);
gcc_assert (TREE_CODE_LENGTH (code) == binary_op);
gcc_assert (reduc_index == (code == MINUS_EXPR ? 0 : 1));
@@ -5941,23 +5811,24 @@ vectorize_fold_left_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
tree op0 = ops[1 - reduc_index];
int group_size = 1;
- gimple *scalar_dest_def;
+ stmt_vec_info scalar_dest_def_info;
auto_vec<tree> vec_oprnds0;
if (slp_node)
{
- vect_get_vec_defs (op0, NULL_TREE, stmt, &vec_oprnds0, NULL, slp_node);
+ vect_get_vec_defs (op0, NULL_TREE, stmt_info, &vec_oprnds0, NULL,
+ slp_node);
group_size = SLP_TREE_SCALAR_STMTS (slp_node).length ();
- scalar_dest_def = SLP_TREE_SCALAR_STMTS (slp_node)[group_size - 1];
+ scalar_dest_def_info = SLP_TREE_SCALAR_STMTS (slp_node)[group_size - 1];
}
else
{
- tree loop_vec_def0 = vect_get_vec_def_for_operand (op0, stmt);
+ tree loop_vec_def0 = vect_get_vec_def_for_operand (op0, stmt_info);
vec_oprnds0.create (1);
vec_oprnds0.quick_push (loop_vec_def0);
- scalar_dest_def = stmt;
+ scalar_dest_def_info = stmt_info;
}
- tree scalar_dest = gimple_assign_lhs (scalar_dest_def);
+ tree scalar_dest = gimple_assign_lhs (scalar_dest_def_info->stmt);
tree scalar_type = TREE_TYPE (scalar_dest);
tree reduc_var = gimple_phi_result (reduc_def_stmt);
@@ -5975,6 +5846,7 @@ vectorize_fold_left_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
tree def0;
FOR_EACH_VEC_ELT (vec_oprnds0, i, def0)
{
+ gimple *new_stmt;
tree mask = NULL_TREE;
if (LOOP_VINFO_FULLY_MASKED_P (loop_vinfo))
mask = vect_get_loop_mask (gsi, masks, vec_num, vectype_in, i);
@@ -6023,33 +5895,35 @@ vectorize_fold_left_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
if (i == vec_num - 1)
{
gimple_set_lhs (new_stmt, scalar_dest);
- vect_finish_replace_stmt (scalar_dest_def, new_stmt);
+ new_stmt_info = vect_finish_replace_stmt (scalar_dest_def_info,
+ new_stmt);
}
else
- vect_finish_stmt_generation (scalar_dest_def, new_stmt, gsi);
+ new_stmt_info = vect_finish_stmt_generation (scalar_dest_def_info,
+ new_stmt, gsi);
if (slp_node)
- SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info);
}
if (!slp_node)
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info;
return true;
}
/* Function is_nonwrapping_integer_induction.
- Check if STMT (which is part of loop LOOP) both increments and
+ Check if STMT_VINO (which is part of loop LOOP) both increments and
does not cause overflow. */
static bool
-is_nonwrapping_integer_induction (gimple *stmt, struct loop *loop)
+is_nonwrapping_integer_induction (stmt_vec_info stmt_vinfo, struct loop *loop)
{
- stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
+ gphi *phi = as_a <gphi *> (stmt_vinfo->stmt);
tree base = STMT_VINFO_LOOP_PHI_EVOLUTION_BASE_UNCHANGED (stmt_vinfo);
tree step = STMT_VINFO_LOOP_PHI_EVOLUTION_PART (stmt_vinfo);
- tree lhs_type = TREE_TYPE (gimple_phi_result (stmt));
+ tree lhs_type = TREE_TYPE (gimple_phi_result (phi));
widest_int ni, max_loop_value, lhs_max;
wi::overflow_type overflow = wi::OVF_NONE;
@@ -6082,17 +5956,18 @@ is_nonwrapping_integer_induction (gimple *stmt, struct loop *loop)
/* Function vectorizable_reduction.
- Check if STMT performs a reduction operation that can be vectorized.
- If VEC_STMT is also passed, vectorize the STMT: create a vectorized
+ Check if STMT_INFO performs a reduction operation that can be vectorized.
+ If VEC_STMT is also passed, vectorize STMT_INFO: create a vectorized
stmt to replace it, put it in VEC_STMT, and insert it at GSI.
- Return FALSE if not a vectorizable STMT, TRUE otherwise.
+ Return true if STMT_INFO is vectorizable in this way.
This function also handles reduction idioms (patterns) that have been
- recognized in advance during vect_pattern_recog. In this case, STMT may be
- of this form:
+ recognized in advance during vect_pattern_recog. In this case, STMT_INFO
+ may be of this form:
X = pattern_expr (arg0, arg1, ..., X)
- and it's STMT_VINFO_RELATED_STMT points to the last stmt in the original
- sequence that had been detected and replaced by the pattern-stmt (STMT).
+ and its STMT_VINFO_RELATED_STMT points to the last stmt in the original
+ sequence that had been detected and replaced by the pattern-stmt
+ (STMT_INFO).
This function also handles reduction of condition expressions, for example:
for (int i = 0; i < N; i++)
@@ -6104,9 +5979,9 @@ is_nonwrapping_integer_induction (gimple *stmt, struct loop *loop)
index into the vector of results.
In some cases of reduction patterns, the type of the reduction variable X is
- different than the type of the other arguments of STMT.
- In such cases, the vectype that is used when transforming STMT into a vector
- stmt is different than the vectype that is used to determine the
+ different than the type of the other arguments of STMT_INFO.
+ In such cases, the vectype that is used when transforming STMT_INFO into
+ a vector stmt is different than the vectype that is used to determine the
vectorization factor, because it consists of a different number of elements
than the actual number of elements that are being operated upon in parallel.
@@ -6130,14 +6005,13 @@ is_nonwrapping_integer_induction (gimple *stmt, struct loop *loop)
does *NOT* necessarily hold for reduction patterns. */
bool
-vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
- gimple **vec_stmt, slp_tree slp_node,
+vectorizable_reduction (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ stmt_vec_info *vec_stmt, slp_tree slp_node,
slp_instance slp_node_instance,
stmt_vector_for_cost *cost_vec)
{
tree vec_dest;
tree scalar_dest;
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
tree vectype_out = STMT_VINFO_VECTYPE (stmt_info);
tree vectype_in = NULL_TREE;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
@@ -6148,64 +6022,53 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
int op_type;
optab optab;
tree new_temp = NULL_TREE;
- gimple *def_stmt;
enum vect_def_type dt, cond_reduc_dt = vect_unknown_def_type;
- gimple *cond_reduc_def_stmt = NULL;
+ stmt_vec_info cond_stmt_vinfo = NULL;
enum tree_code cond_reduc_op_code = ERROR_MARK;
tree scalar_type;
bool is_simple_use;
- gimple *orig_stmt;
- stmt_vec_info orig_stmt_info = NULL;
int i;
int ncopies;
int epilog_copies;
stmt_vec_info prev_stmt_info, prev_phi_info;
bool single_defuse_cycle = false;
- gimple *new_stmt = NULL;
+ stmt_vec_info new_stmt_info = NULL;
int j;
tree ops[3];
enum vect_def_type dts[3];
bool nested_cycle = false, found_nested_cycle_def = false;
bool double_reduc = false;
basic_block def_bb;
- struct loop * def_stmt_loop, *outer_loop = NULL;
+ struct loop * def_stmt_loop;
tree def_arg;
- gimple *def_arg_stmt;
auto_vec<tree> vec_oprnds0;
auto_vec<tree> vec_oprnds1;
auto_vec<tree> vec_oprnds2;
auto_vec<tree> vect_defs;
- auto_vec<gimple *> phis;
+ auto_vec<stmt_vec_info> phis;
int vec_num;
tree def0, tem;
- bool first_p = true;
tree cr_index_scalar_type = NULL_TREE, cr_index_vector_type = NULL_TREE;
tree cond_reduc_val = NULL_TREE;
/* Make sure it was already recognized as a reduction computation. */
- if (STMT_VINFO_DEF_TYPE (vinfo_for_stmt (stmt)) != vect_reduction_def
- && STMT_VINFO_DEF_TYPE (vinfo_for_stmt (stmt)) != vect_nested_cycle)
+ if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_reduction_def
+ && STMT_VINFO_DEF_TYPE (stmt_info) != vect_nested_cycle)
return false;
- if (nested_in_vect_loop_p (loop, stmt))
+ if (nested_in_vect_loop_p (loop, stmt_info))
{
- outer_loop = loop;
loop = loop->inner;
nested_cycle = true;
}
- /* In case of reduction chain we switch to the first stmt in the chain, but
- we don't update STMT_INFO, since only the last stmt is marked as reduction
- and has reduction properties. */
- if (REDUC_GROUP_FIRST_ELEMENT (stmt_info)
- && REDUC_GROUP_FIRST_ELEMENT (stmt_info) != stmt)
- {
- stmt = REDUC_GROUP_FIRST_ELEMENT (stmt_info);
- first_p = false;
- }
+ if (REDUC_GROUP_FIRST_ELEMENT (stmt_info))
+ gcc_assert (slp_node
+ && REDUC_GROUP_FIRST_ELEMENT (stmt_info) == stmt_info);
- if (gimple_code (stmt) == GIMPLE_PHI)
+ if (gphi *phi = dyn_cast <gphi *> (stmt_info->stmt))
{
+ tree phi_result = gimple_phi_result (phi);
/* Analysis is fully done on the reduction stmt invocation. */
if (! vec_stmt)
{
@@ -6222,20 +6085,19 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
for reductions involving a single statement. */
return true;
- gimple *reduc_stmt = STMT_VINFO_REDUC_DEF (stmt_info);
- if (STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (reduc_stmt)))
- reduc_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (reduc_stmt));
+ stmt_vec_info reduc_stmt_info = STMT_VINFO_REDUC_DEF (stmt_info);
+ reduc_stmt_info = vect_stmt_to_vectorize (reduc_stmt_info);
- if (STMT_VINFO_VEC_REDUCTION_TYPE (vinfo_for_stmt (reduc_stmt))
+ if (STMT_VINFO_VEC_REDUCTION_TYPE (reduc_stmt_info)
== EXTRACT_LAST_REDUCTION)
/* Leave the scalar phi in place. */
return true;
- gcc_assert (is_gimple_assign (reduc_stmt));
+ gassign *reduc_stmt = as_a <gassign *> (reduc_stmt_info->stmt);
for (unsigned k = 1; k < gimple_num_ops (reduc_stmt); ++k)
{
tree op = gimple_op (reduc_stmt, k);
- if (op == gimple_phi_result (stmt))
+ if (op == phi_result)
continue;
if (k == 1
&& gimple_assign_rhs_code (reduc_stmt) == COND_EXPR)
@@ -6253,15 +6115,11 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
else
ncopies = vect_get_num_copies (loop_vinfo, vectype_in);
- use_operand_p use_p;
- gimple *use_stmt;
+ stmt_vec_info use_stmt_info;
if (ncopies > 1
- && (STMT_VINFO_RELEVANT (vinfo_for_stmt (reduc_stmt))
- <= vect_used_only_live)
- && single_imm_use (gimple_phi_result (stmt), &use_p, &use_stmt)
- && (use_stmt == reduc_stmt
- || (STMT_VINFO_RELATED_STMT (vinfo_for_stmt (use_stmt))
- == reduc_stmt)))
+ && STMT_VINFO_RELEVANT (reduc_stmt_info) <= vect_used_only_live
+ && (use_stmt_info = loop_vinfo->lookup_single_use (phi_result))
+ && vect_stmt_to_vectorize (use_stmt_info) == reduc_stmt_info)
single_defuse_cycle = true;
/* Create the destination vector */
@@ -6288,18 +6146,18 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
/* Create the reduction-phi that defines the reduction
operand. */
gimple *new_phi = create_phi_node (vec_dest, loop->header);
- set_vinfo_for_stmt (new_phi,
- new_stmt_vec_info (new_phi, loop_vinfo));
+ stmt_vec_info new_phi_info = loop_vinfo->add_stmt (new_phi);
if (slp_node)
- SLP_TREE_VEC_STMTS (slp_node).quick_push (new_phi);
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_phi_info);
else
{
if (j == 0)
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_phi;
+ STMT_VINFO_VEC_STMT (stmt_info)
+ = *vec_stmt = new_phi_info;
else
- STMT_VINFO_RELATED_STMT (prev_phi_info) = new_phi;
- prev_phi_info = vinfo_for_stmt (new_phi);
+ STMT_VINFO_RELATED_STMT (prev_phi_info) = new_phi_info;
+ prev_phi_info = new_phi_info;
}
}
}
@@ -6328,10 +6186,9 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
the STMT_VINFO_RELATED_STMT field records the last stmt in
the original sequence that constitutes the pattern. */
- orig_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt));
- if (orig_stmt)
+ stmt_vec_info orig_stmt_info = STMT_VINFO_RELATED_STMT (stmt_info);
+ if (orig_stmt_info)
{
- orig_stmt_info = vinfo_for_stmt (orig_stmt);
gcc_assert (STMT_VINFO_IN_PATTERN_P (orig_stmt_info));
gcc_assert (!STMT_VINFO_IN_PATTERN_P (stmt_info));
}
@@ -6340,7 +6197,7 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
inside the loop body. The last operand is the reduction variable,
which is defined by the loop-header-phi. */
- gcc_assert (is_gimple_assign (stmt));
+ gassign *stmt = as_a <gassign *> (stmt_info->stmt);
/* Flatten RHS. */
switch (get_gimple_rhs_class (gimple_assign_rhs_code (stmt)))
@@ -6386,7 +6243,7 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
The last use is the reduction variable. In case of nested cycle this
assumption is not true: we use reduc_index to record the index of the
reduction variable. */
- gimple *reduc_def_stmt = NULL;
+ stmt_vec_info reduc_def_info = NULL;
int reduc_index = -1;
for (i = 0; i < op_type; i++)
{
@@ -6394,13 +6251,14 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
if (i == 0 && code == COND_EXPR)
continue;
- is_simple_use = vect_is_simple_use (ops[i], loop_vinfo,
- &dts[i], &tem, &def_stmt);
+ stmt_vec_info def_stmt_info;
+ is_simple_use = vect_is_simple_use (ops[i], loop_vinfo, &dts[i], &tem,
+ &def_stmt_info);
dt = dts[i];
gcc_assert (is_simple_use);
if (dt == vect_reduction_def)
{
- reduc_def_stmt = def_stmt;
+ reduc_def_info = def_stmt_info;
reduc_index = i;
continue;
}
@@ -6422,11 +6280,11 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
return false;
if (dt == vect_nested_cycle)
- {
- found_nested_cycle_def = true;
- reduc_def_stmt = def_stmt;
- reduc_index = i;
- }
+ {
+ found_nested_cycle_def = true;
+ reduc_def_info = def_stmt_info;
+ reduc_index = i;
+ }
if (i == 1 && code == COND_EXPR)
{
@@ -6437,11 +6295,11 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
cond_reduc_val = ops[i];
}
if (dt == vect_induction_def
- && def_stmt != NULL
- && is_nonwrapping_integer_induction (def_stmt, loop))
+ && def_stmt_info
+ && is_nonwrapping_integer_induction (def_stmt_info, loop))
{
cond_reduc_dt = dt;
- cond_reduc_def_stmt = def_stmt;
+ cond_stmt_vinfo = def_stmt_info;
}
}
}
@@ -6461,13 +6319,17 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
return false;
}
- if (orig_stmt)
- reduc_def_stmt = STMT_VINFO_REDUC_DEF (orig_stmt_info);
+ if (orig_stmt_info)
+ reduc_def_info = STMT_VINFO_REDUC_DEF (orig_stmt_info);
else
- reduc_def_stmt = STMT_VINFO_REDUC_DEF (stmt_info);
+ reduc_def_info = STMT_VINFO_REDUC_DEF (stmt_info);
}
- if (! reduc_def_stmt || gimple_code (reduc_def_stmt) != GIMPLE_PHI)
+ if (! reduc_def_info)
+ return false;
+
+ gphi *reduc_def_phi = dyn_cast <gphi *> (reduc_def_info->stmt);
+ if (!reduc_def_phi)
return false;
if (!(reduc_index == -1
@@ -6482,16 +6344,15 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
/* For pattern recognized stmts, orig_stmt might be a reduction,
but some helper statements for the pattern might not, or
might be COND_EXPRs with reduction uses in the condition. */
- gcc_assert (orig_stmt);
+ gcc_assert (orig_stmt_info);
return false;
}
- stmt_vec_info reduc_def_info = vinfo_for_stmt (reduc_def_stmt);
/* PHIs should not participate in patterns. */
gcc_assert (!STMT_VINFO_RELATED_STMT (reduc_def_info));
enum vect_reduction_type v_reduc_type
= STMT_VINFO_REDUC_TYPE (reduc_def_info);
- gimple *tmp = STMT_VINFO_REDUC_DEF (reduc_def_info);
+ stmt_vec_info tmp = STMT_VINFO_REDUC_DEF (reduc_def_info);
STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info) = v_reduc_type;
/* If we have a condition reduction, see if we can simplify it further. */
@@ -6544,7 +6405,6 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
}
else if (cond_reduc_dt == vect_induction_def)
{
- stmt_vec_info cond_stmt_vinfo = vinfo_for_stmt (cond_reduc_def_stmt);
tree base
= STMT_VINFO_LOOP_PHI_EVOLUTION_BASE_UNCHANGED (cond_stmt_vinfo);
tree step = STMT_VINFO_LOOP_PHI_EVOLUTION_PART (cond_stmt_vinfo);
@@ -6616,17 +6476,16 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
}
}
- if (orig_stmt)
- gcc_assert (tmp == orig_stmt
- || (REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (tmp))
- == orig_stmt));
+ if (orig_stmt_info)
+ gcc_assert (tmp == orig_stmt_info
+ || REDUC_GROUP_FIRST_ELEMENT (tmp) == orig_stmt_info);
else
/* We changed STMT to be the first stmt in reduction chain, hence we
check that in this case the first element in the chain is STMT. */
- gcc_assert (stmt == tmp
- || REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (tmp)) == stmt);
+ gcc_assert (tmp == stmt_info
+ || REDUC_GROUP_FIRST_ELEMENT (tmp) == stmt_info);
- if (STMT_VINFO_LIVE_P (vinfo_for_stmt (reduc_def_stmt)))
+ if (STMT_VINFO_LIVE_P (reduc_def_info))
return false;
if (slp_node)
@@ -6643,7 +6502,7 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
{
/* Only call during the analysis stage, otherwise we'll lose
STMT_VINFO_TYPE. */
- if (!vec_stmt && !vectorizable_condition (stmt, gsi, NULL,
+ if (!vec_stmt && !vectorizable_condition (stmt_info, gsi, NULL,
ops[reduc_index], 0, NULL,
cost_vec))
{
@@ -6741,13 +6600,13 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
vect_reduction_type reduction_type
= STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info);
- if (orig_stmt
+ if (orig_stmt_info
&& (reduction_type == TREE_CODE_REDUCTION
|| reduction_type == FOLD_LEFT_REDUCTION))
{
/* This is a reduction pattern: get the vectype from the type of the
reduction variable, and get the tree-code from orig_stmt. */
- orig_code = gimple_assign_rhs_code (orig_stmt);
+ orig_code = gimple_assign_rhs_code (orig_stmt_info->stmt);
gcc_assert (vectype_out);
vec_mode = TYPE_MODE (vectype_out);
}
@@ -6773,17 +6632,14 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
if (nested_cycle)
{
- def_bb = gimple_bb (reduc_def_stmt);
+ def_bb = gimple_bb (reduc_def_phi);
def_stmt_loop = def_bb->loop_father;
- def_arg = PHI_ARG_DEF_FROM_EDGE (reduc_def_stmt,
+ def_arg = PHI_ARG_DEF_FROM_EDGE (reduc_def_phi,
loop_preheader_edge (def_stmt_loop));
- if (TREE_CODE (def_arg) == SSA_NAME
- && (def_arg_stmt = SSA_NAME_DEF_STMT (def_arg))
- && gimple_code (def_arg_stmt) == GIMPLE_PHI
- && flow_bb_inside_loop_p (outer_loop, gimple_bb (def_arg_stmt))
- && vinfo_for_stmt (def_arg_stmt)
- && STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_arg_stmt))
- == vect_double_reduction_def)
+ stmt_vec_info def_arg_stmt_info = loop_vinfo->lookup_def (def_arg);
+ if (def_arg_stmt_info
+ && (STMT_VINFO_DEF_TYPE (def_arg_stmt_info)
+ == vect_double_reduction_def))
double_reduc = true;
}
@@ -6835,6 +6691,7 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
}
if (reduction_type != EXTRACT_LAST_REDUCTION
+ && (!nested_cycle || double_reduc)
&& reduc_fn == IFN_LAST
&& !nunits_out.is_constant ())
{
@@ -6859,8 +6716,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
tree neutral_op = NULL_TREE;
if (slp_node)
neutral_op = neutral_op_for_slp_reduction
- (slp_node_instance->reduc_phis, code,
- REDUC_GROUP_FIRST_ELEMENT (stmt_info) != NULL);
+ (slp_node_instance->reduc_phis, code,
+ REDUC_GROUP_FIRST_ELEMENT (stmt_info) != NULL);
if (double_reduc && reduction_type == FOLD_LEFT_REDUCTION)
{
@@ -6887,7 +6744,7 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
if (reduction_type == FOLD_LEFT_REDUCTION
&& slp_node
- && !REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)))
+ && !REDUC_GROUP_FIRST_ELEMENT (stmt_info))
{
/* We cannot use in-order reductions in this case because there is
an implicit reassociation of the operations involved. */
@@ -6916,7 +6773,7 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
/* Check extra constraints for variable-length unchained SLP reductions. */
if (STMT_SLP_TYPE (stmt_info)
- && !REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt))
+ && !REDUC_GROUP_FIRST_ELEMENT (stmt_info)
&& !nunits_out.is_constant ())
{
/* We checked above that we could build the initial vector when
@@ -7027,13 +6884,12 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
This only works when we see both the reduction PHI and its only consumer
in vectorizable_reduction and there are no intermediate stmts
participating. */
- use_operand_p use_p;
- gimple *use_stmt;
+ stmt_vec_info use_stmt_info;
+ tree reduc_phi_result = gimple_phi_result (reduc_def_phi);
if (ncopies > 1
&& (STMT_VINFO_RELEVANT (stmt_info) <= vect_used_only_live)
- && single_imm_use (gimple_phi_result (reduc_def_stmt), &use_p, &use_stmt)
- && (use_stmt == stmt
- || STMT_VINFO_RELATED_STMT (vinfo_for_stmt (use_stmt)) == stmt))
+ && (use_stmt_info = loop_vinfo->lookup_single_use (reduc_phi_result))
+ && vect_stmt_to_vectorize (use_stmt_info) == stmt_info)
{
single_defuse_cycle = true;
epilog_copies = 1;
@@ -7066,8 +6922,7 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
if (!vec_stmt) /* transformation not required. */
{
- if (first_p)
- vect_model_reduction_cost (stmt_info, reduc_fn, ncopies, cost_vec);
+ vect_model_reduction_cost (stmt_info, reduc_fn, ncopies, cost_vec);
if (loop_vinfo && LOOP_VINFO_CAN_FULLY_MASK_P (loop_vinfo))
{
if (reduction_type != FOLD_LEFT_REDUCTION
@@ -7114,13 +6969,13 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
if (reduction_type == FOLD_LEFT_REDUCTION)
return vectorize_fold_left_reduction
- (stmt, gsi, vec_stmt, slp_node, reduc_def_stmt, code,
+ (stmt_info, gsi, vec_stmt, slp_node, reduc_def_phi, code,
reduc_fn, ops, vectype_in, reduc_index, masks);
if (reduction_type == EXTRACT_LAST_REDUCTION)
{
gcc_assert (!slp_node);
- return vectorizable_condition (stmt, gsi, vec_stmt,
+ return vectorizable_condition (stmt_info, gsi, vec_stmt,
NULL, reduc_index, NULL, NULL);
}
@@ -7145,16 +7000,16 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
if (slp_node)
phis.splice (SLP_TREE_VEC_STMTS (slp_node_instance->reduc_phis));
else
- phis.quick_push (STMT_VINFO_VEC_STMT (vinfo_for_stmt (reduc_def_stmt)));
+ phis.quick_push (STMT_VINFO_VEC_STMT (reduc_def_info));
for (j = 0; j < ncopies; j++)
{
if (code == COND_EXPR)
{
gcc_assert (!slp_node);
- vectorizable_condition (stmt, gsi, vec_stmt,
- PHI_RESULT (phis[0]),
- reduc_index, NULL, NULL);
+ vectorizable_condition (stmt_info, gsi, vec_stmt,
+ PHI_RESULT (phis[0]->stmt),
+ reduc_index, NULL, NULL);
/* Multiple types are not supported for condition. */
break;
}
@@ -7189,12 +7044,12 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
else
{
vec_oprnds0.quick_push
- (vect_get_vec_def_for_operand (ops[0], stmt));
+ (vect_get_vec_def_for_operand (ops[0], stmt_info));
vec_oprnds1.quick_push
- (vect_get_vec_def_for_operand (ops[1], stmt));
+ (vect_get_vec_def_for_operand (ops[1], stmt_info));
if (op_type == ternary_op)
vec_oprnds2.quick_push
- (vect_get_vec_def_for_operand (ops[2], stmt));
+ (vect_get_vec_def_for_operand (ops[2], stmt_info));
}
}
else
@@ -7204,22 +7059,25 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
gcc_assert (reduc_index != -1 || ! single_defuse_cycle);
if (single_defuse_cycle && reduc_index == 0)
- vec_oprnds0[0] = gimple_get_lhs (new_stmt);
+ vec_oprnds0[0] = gimple_get_lhs (new_stmt_info->stmt);
else
vec_oprnds0[0]
- = vect_get_vec_def_for_stmt_copy (dts[0], vec_oprnds0[0]);
+ = vect_get_vec_def_for_stmt_copy (loop_vinfo,
+ vec_oprnds0[0]);
if (single_defuse_cycle && reduc_index == 1)
- vec_oprnds1[0] = gimple_get_lhs (new_stmt);
+ vec_oprnds1[0] = gimple_get_lhs (new_stmt_info->stmt);
else
vec_oprnds1[0]
- = vect_get_vec_def_for_stmt_copy (dts[1], vec_oprnds1[0]);
+ = vect_get_vec_def_for_stmt_copy (loop_vinfo,
+ vec_oprnds1[0]);
if (op_type == ternary_op)
{
if (single_defuse_cycle && reduc_index == 2)
- vec_oprnds2[0] = gimple_get_lhs (new_stmt);
+ vec_oprnds2[0] = gimple_get_lhs (new_stmt_info->stmt);
else
vec_oprnds2[0]
- = vect_get_vec_def_for_stmt_copy (dts[2], vec_oprnds2[0]);
+ = vect_get_vec_def_for_stmt_copy (loop_vinfo,
+ vec_oprnds2[0]);
}
}
}
@@ -7243,22 +7101,25 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
new_temp = make_ssa_name (vec_dest, call);
gimple_call_set_lhs (call, new_temp);
gimple_call_set_nothrow (call, true);
- new_stmt = call;
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, call, gsi);
}
else
{
if (op_type == ternary_op)
vop[2] = vec_oprnds2[i];
+ gassign *new_stmt = gimple_build_assign (vec_dest, code,
+ vop[0], vop[1], vop[2]);
new_temp = make_ssa_name (vec_dest, new_stmt);
- new_stmt = gimple_build_assign (new_temp, code,
- vop[0], vop[1], vop[2]);
+ gimple_assign_set_lhs (new_stmt, new_temp);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
}
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
if (slp_node)
{
- SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info);
vect_defs.quick_push (new_temp);
}
else
@@ -7269,19 +7130,19 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
continue;
if (j == 0)
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info;
else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
- prev_stmt_info = vinfo_for_stmt (new_stmt);
+ prev_stmt_info = new_stmt_info;
}
/* Finalize the reduction-phi (set its arguments) and create the
epilog reduction code. */
if ((!single_defuse_cycle || code == COND_EXPR) && !slp_node)
- vect_defs[0] = gimple_get_lhs (*vec_stmt);
+ vect_defs[0] = gimple_get_lhs ((*vec_stmt)->stmt);
- vect_create_epilog_for_reduction (vect_defs, stmt, reduc_def_stmt,
+ vect_create_epilog_for_reduction (vect_defs, stmt_info, reduc_def_phi,
epilog_copies, reduc_fn, phis,
double_reduc, slp_node, slp_node_instance,
cond_reduc_val, cond_reduc_op_code,
@@ -7332,18 +7193,17 @@ vect_worthwhile_without_simd_p (vec_info *vinfo, tree_code code)
/* Function vectorizable_induction
- Check if PHI performs an induction computation that can be vectorized.
+ Check if STMT_INFO performs an induction computation that can be vectorized.
If VEC_STMT is also passed, vectorize the induction PHI: create a vectorized
phi to replace it, put it in VEC_STMT, and add it to the same basic block.
- Return FALSE if not a vectorizable STMT, TRUE otherwise. */
+ Return true if STMT_INFO is vectorizable in this way. */
bool
-vectorizable_induction (gimple *phi,
+vectorizable_induction (stmt_vec_info stmt_info,
gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
- gimple **vec_stmt, slp_tree slp_node,
+ stmt_vec_info *vec_stmt, slp_tree slp_node,
stmt_vector_for_cost *cost_vec)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (phi);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
unsigned ncopies;
@@ -7368,9 +7228,9 @@ vectorizable_induction (gimple *phi,
edge latch_e;
tree loop_arg;
gimple_stmt_iterator si;
- basic_block bb = gimple_bb (phi);
- if (gimple_code (phi) != GIMPLE_PHI)
+ gphi *phi = dyn_cast <gphi *> (stmt_info->stmt);
+ if (!phi)
return false;
if (!STMT_VINFO_RELEVANT_P (stmt_info))
@@ -7390,7 +7250,7 @@ vectorizable_induction (gimple *phi,
gcc_assert (ncopies >= 1);
/* FORNOW. These restrictions should be relaxed. */
- if (nested_in_vect_loop_p (loop, phi))
+ if (nested_in_vect_loop_p (loop, stmt_info))
{
imm_use_iterator imm_iter;
use_operand_p use_p;
@@ -7427,7 +7287,7 @@ vectorizable_induction (gimple *phi,
}
if (exit_phi)
{
- stmt_vec_info exit_phi_vinfo = vinfo_for_stmt (exit_phi);
+ stmt_vec_info exit_phi_vinfo = loop_vinfo->lookup_stmt (exit_phi);
if (!(STMT_VINFO_RELEVANT_P (exit_phi_vinfo)
&& !STMT_VINFO_LIVE_P (exit_phi_vinfo)))
{
@@ -7518,6 +7378,7 @@ vectorizable_induction (gimple *phi,
}
/* Find the first insertion point in the BB. */
+ basic_block bb = gimple_bb (phi);
si = gsi_after_labels (bb);
/* For SLP induction we have to generate several IVs as for example
@@ -7540,10 +7401,10 @@ vectorizable_induction (gimple *phi,
new_name = fold_build2 (MULT_EXPR, TREE_TYPE (step_expr),
expr, step_expr);
if (! CONSTANT_CLASS_P (new_name))
- new_name = vect_init_vector (phi, new_name,
+ new_name = vect_init_vector (stmt_info, new_name,
TREE_TYPE (step_expr), NULL);
new_vec = build_vector_from_val (vectype, new_name);
- vec_step = vect_init_vector (phi, new_vec, vectype, NULL);
+ vec_step = vect_init_vector (stmt_info, new_vec, vectype, NULL);
/* Now generate the IVs. */
unsigned group_size = SLP_TREE_SCALAR_STMTS (slp_node).length ();
@@ -7576,22 +7437,22 @@ vectorizable_induction (gimple *phi,
/* Create the induction-phi that defines the induction-operand. */
vec_dest = vect_get_new_vect_var (vectype, vect_simple_var, "vec_iv_");
induction_phi = create_phi_node (vec_dest, iv_loop->header);
- set_vinfo_for_stmt (induction_phi,
- new_stmt_vec_info (induction_phi, loop_vinfo));
+ stmt_vec_info induction_phi_info
+ = loop_vinfo->add_stmt (induction_phi);
induc_def = PHI_RESULT (induction_phi);
/* Create the iv update inside the loop */
vec_def = make_ssa_name (vec_dest);
new_stmt = gimple_build_assign (vec_def, PLUS_EXPR, induc_def, vec_step);
gsi_insert_before (&si, new_stmt, GSI_SAME_STMT);
- set_vinfo_for_stmt (new_stmt, new_stmt_vec_info (new_stmt, loop_vinfo));
+ loop_vinfo->add_stmt (new_stmt);
/* Set the arguments of the phi node: */
add_phi_arg (induction_phi, vec_init, pe, UNKNOWN_LOCATION);
add_phi_arg (induction_phi, vec_def, loop_latch_edge (iv_loop),
UNKNOWN_LOCATION);
- SLP_TREE_VEC_STMTS (slp_node).quick_push (induction_phi);
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (induction_phi_info);
}
/* Re-use IVs when we can. */
@@ -7610,13 +7471,13 @@ vectorizable_induction (gimple *phi,
new_name = fold_build2 (MULT_EXPR, TREE_TYPE (step_expr),
expr, step_expr);
if (! CONSTANT_CLASS_P (new_name))
- new_name = vect_init_vector (phi, new_name,
+ new_name = vect_init_vector (stmt_info, new_name,
TREE_TYPE (step_expr), NULL);
new_vec = build_vector_from_val (vectype, new_name);
- vec_step = vect_init_vector (phi, new_vec, vectype, NULL);
+ vec_step = vect_init_vector (stmt_info, new_vec, vectype, NULL);
for (; ivn < nvects; ++ivn)
{
- gimple *iv = SLP_TREE_VEC_STMTS (slp_node)[ivn - nivs];
+ gimple *iv = SLP_TREE_VEC_STMTS (slp_node)[ivn - nivs]->stmt;
tree def;
if (gimple_code (iv) == GIMPLE_PHI)
def = gimple_phi_result (iv);
@@ -7632,9 +7493,8 @@ vectorizable_induction (gimple *phi,
gimple_stmt_iterator tgsi = gsi_for_stmt (iv);
gsi_insert_after (&tgsi, new_stmt, GSI_CONTINUE_LINKING);
}
- set_vinfo_for_stmt (new_stmt,
- new_stmt_vec_info (new_stmt, loop_vinfo));
- SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
+ SLP_TREE_VEC_STMTS (slp_node).quick_push
+ (loop_vinfo->add_stmt (new_stmt));
}
}
@@ -7647,7 +7507,7 @@ vectorizable_induction (gimple *phi,
/* iv_loop is nested in the loop to be vectorized. init_expr had already
been created during vectorization of previous stmts. We obtain it
from the STMT_VINFO_VEC_STMT of the defining stmt. */
- vec_init = vect_get_vec_def_for_operand (init_expr, phi);
+ vec_init = vect_get_vec_def_for_operand (init_expr, stmt_info);
/* If the initial value is not of proper type, convert it. */
if (!useless_type_conversion_p (vectype, TREE_TYPE (vec_init)))
{
@@ -7662,8 +7522,7 @@ vectorizable_induction (gimple *phi,
new_bb = gsi_insert_on_edge_immediate (loop_preheader_edge (iv_loop),
new_stmt);
gcc_assert (!new_bb);
- set_vinfo_for_stmt (new_stmt,
- new_stmt_vec_info (new_stmt, loop_vinfo));
+ loop_vinfo->add_stmt (new_stmt);
}
}
else
@@ -7750,7 +7609,7 @@ vectorizable_induction (gimple *phi,
gcc_assert (CONSTANT_CLASS_P (new_name)
|| TREE_CODE (new_name) == SSA_NAME);
new_vec = build_vector_from_val (vectype, t);
- vec_step = vect_init_vector (phi, new_vec, vectype, NULL);
+ vec_step = vect_init_vector (stmt_info, new_vec, vectype, NULL);
/* Create the following def-use cycle:
@@ -7767,22 +7626,21 @@ vectorizable_induction (gimple *phi,
/* Create the induction-phi that defines the induction-operand. */
vec_dest = vect_get_new_vect_var (vectype, vect_simple_var, "vec_iv_");
induction_phi = create_phi_node (vec_dest, iv_loop->header);
- set_vinfo_for_stmt (induction_phi,
- new_stmt_vec_info (induction_phi, loop_vinfo));
+ stmt_vec_info induction_phi_info = loop_vinfo->add_stmt (induction_phi);
induc_def = PHI_RESULT (induction_phi);
/* Create the iv update inside the loop */
vec_def = make_ssa_name (vec_dest);
new_stmt = gimple_build_assign (vec_def, PLUS_EXPR, induc_def, vec_step);
gsi_insert_before (&si, new_stmt, GSI_SAME_STMT);
- set_vinfo_for_stmt (new_stmt, new_stmt_vec_info (new_stmt, loop_vinfo));
+ stmt_vec_info new_stmt_info = loop_vinfo->add_stmt (new_stmt);
/* Set the arguments of the phi node: */
add_phi_arg (induction_phi, vec_init, pe, UNKNOWN_LOCATION);
add_phi_arg (induction_phi, vec_def, loop_latch_edge (iv_loop),
UNKNOWN_LOCATION);
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = induction_phi;
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = induction_phi_info;
/* In case that vectorization factor (VF) is bigger than the number
of elements that we can fit in a vectype (nunits), we have to generate
@@ -7817,10 +7675,10 @@ vectorizable_induction (gimple *phi,
gcc_assert (CONSTANT_CLASS_P (new_name)
|| TREE_CODE (new_name) == SSA_NAME);
new_vec = build_vector_from_val (vectype, t);
- vec_step = vect_init_vector (phi, new_vec, vectype, NULL);
+ vec_step = vect_init_vector (stmt_info, new_vec, vectype, NULL);
vec_def = induc_def;
- prev_stmt_vinfo = vinfo_for_stmt (induction_phi);
+ prev_stmt_vinfo = induction_phi_info;
for (i = 1; i < ncopies; i++)
{
/* vec_i = vec_prev + vec_step */
@@ -7830,10 +7688,9 @@ vectorizable_induction (gimple *phi,
gimple_assign_set_lhs (new_stmt, vec_def);
gsi_insert_before (&si, new_stmt, GSI_SAME_STMT);
- set_vinfo_for_stmt (new_stmt,
- new_stmt_vec_info (new_stmt, loop_vinfo));
- STMT_VINFO_RELATED_STMT (prev_stmt_vinfo) = new_stmt;
- prev_stmt_vinfo = vinfo_for_stmt (new_stmt);
+ new_stmt_info = loop_vinfo->add_stmt (new_stmt);
+ STMT_VINFO_RELATED_STMT (prev_stmt_vinfo) = new_stmt_info;
+ prev_stmt_vinfo = new_stmt_info;
}
}
@@ -7856,48 +7713,41 @@ vectorizable_induction (gimple *phi,
}
if (exit_phi)
{
- stmt_vec_info stmt_vinfo = vinfo_for_stmt (exit_phi);
+ stmt_vec_info stmt_vinfo = loop_vinfo->lookup_stmt (exit_phi);
/* FORNOW. Currently not supporting the case that an inner-loop induction
is not used in the outer-loop (i.e. only outside the outer-loop). */
gcc_assert (STMT_VINFO_RELEVANT_P (stmt_vinfo)
&& !STMT_VINFO_LIVE_P (stmt_vinfo));
- STMT_VINFO_VEC_STMT (stmt_vinfo) = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_vinfo) = new_stmt_info;
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "vector of inductions after inner-loop:");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, new_stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "vector of inductions after inner-loop:%G",
+ new_stmt);
}
}
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "transform induction: created def-use cycle: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, induction_phi, 0);
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM,
- SSA_NAME_DEF_STMT (vec_def), 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "transform induction: created def-use cycle: %G%G",
+ induction_phi, SSA_NAME_DEF_STMT (vec_def));
return true;
}
/* Function vectorizable_live_operation.
- STMT computes a value that is used outside the loop. Check if
+ STMT_INFO computes a value that is used outside the loop. Check if
it can be supported. */
bool
-vectorizable_live_operation (gimple *stmt,
+vectorizable_live_operation (stmt_vec_info stmt_info,
gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
slp_tree slp_node, int slp_index,
- gimple **vec_stmt,
+ stmt_vec_info *vec_stmt,
stmt_vector_for_cost *)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
imm_use_iterator imm_iter;
@@ -7916,7 +7766,7 @@ vectorizable_live_operation (gimple *stmt,
return false;
/* FORNOW. CHECKME. */
- if (nested_in_vect_loop_p (loop, stmt))
+ if (nested_in_vect_loop_p (loop, stmt_info))
return false;
/* If STMT is not relevant and it is a simple assignment and its inputs are
@@ -7924,7 +7774,7 @@ vectorizable_live_operation (gimple *stmt,
scalar value that it computes will be used. */
if (!STMT_VINFO_RELEVANT_P (stmt_info))
{
- gcc_assert (is_simple_and_all_uses_invariant (stmt, loop_vinfo));
+ gcc_assert (is_simple_and_all_uses_invariant (stmt_info, loop_vinfo));
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"statement is simple and uses invariant. Leaving in "
@@ -8003,9 +7853,8 @@ vectorizable_live_operation (gimple *stmt,
return true;
}
- /* If stmt has a related stmt, then use that for getting the lhs. */
- if (is_pattern_stmt_p (stmt_info))
- stmt = STMT_VINFO_RELATED_STMT (stmt_info);
+ /* Use the lhs of the original scalar statement. */
+ gimple *stmt = vect_orig_stmt (stmt_info)->stmt;
lhs = (is_a <gphi *> (stmt)) ? gimple_phi_result (stmt)
: gimple_get_lhs (stmt);
@@ -8023,7 +7872,7 @@ vectorizable_live_operation (gimple *stmt,
gcc_assert (!LOOP_VINFO_FULLY_MASKED_P (loop_vinfo));
/* Get the correct slp vectorized stmt. */
- gimple *vec_stmt = SLP_TREE_VEC_STMTS (slp_node)[vec_entry];
+ gimple *vec_stmt = SLP_TREE_VEC_STMTS (slp_node)[vec_entry]->stmt;
if (gphi *phi = dyn_cast <gphi *> (vec_stmt))
vec_lhs = gimple_phi_result (phi);
else
@@ -8036,14 +7885,13 @@ vectorizable_live_operation (gimple *stmt,
else
{
enum vect_def_type dt = STMT_VINFO_DEF_TYPE (stmt_info);
- vec_lhs = vect_get_vec_def_for_operand_1 (stmt, dt);
+ vec_lhs = vect_get_vec_def_for_operand_1 (stmt_info, dt);
gcc_checking_assert (ncopies == 1
|| !LOOP_VINFO_FULLY_MASKED_P (loop_vinfo));
/* For multiple copies, get the last copy. */
for (int i = 1; i < ncopies; ++i)
- vec_lhs = vect_get_vec_def_for_stmt_copy (vect_unknown_def_type,
- vec_lhs);
+ vec_lhs = vect_get_vec_def_for_stmt_copy (loop_vinfo, vec_lhs);
/* Get the last lane in the vector. */
bitstart = int_const_binop (MINUS_EXPR, vec_bitsize, bitsize);
@@ -8106,17 +7954,17 @@ vectorizable_live_operation (gimple *stmt,
return true;
}
-/* Kill any debug uses outside LOOP of SSA names defined in STMT. */
+/* Kill any debug uses outside LOOP of SSA names defined in STMT_INFO. */
static void
-vect_loop_kill_debug_uses (struct loop *loop, gimple *stmt)
+vect_loop_kill_debug_uses (struct loop *loop, stmt_vec_info stmt_info)
{
ssa_op_iter op_iter;
imm_use_iterator imm_iter;
def_operand_p def_p;
gimple *ustmt;
- FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt, op_iter, SSA_OP_DEF)
+ FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt_info->stmt, op_iter, SSA_OP_DEF)
{
FOR_EACH_IMM_USE_STMT (ustmt, imm_iter, DEF_FROM_PTR (def_p))
{
@@ -8303,31 +8151,23 @@ scale_profile_for_vect_loop (struct loop *loop, unsigned vf)
scale_bbs_frequencies (&loop->latch, 1, exit_l->probability / prob);
}
-/* Vectorize STMT if relevant, inserting any new instructions before GSI.
- When vectorizing STMT as a store, set *SEEN_STORE to its stmt_vec_info.
- *SLP_SCHEDULE is a running record of whether we have called
- vect_schedule_slp. */
+/* Vectorize STMT_INFO if relevant, inserting any new instructions before GSI.
+ When vectorizing STMT_INFO as a store, set *SEEN_STORE to its
+ stmt_vec_info. */
static void
-vect_transform_loop_stmt (loop_vec_info loop_vinfo, gimple *stmt,
- gimple_stmt_iterator *gsi,
- stmt_vec_info *seen_store, bool *slp_scheduled)
+vect_transform_loop_stmt (loop_vec_info loop_vinfo, stmt_vec_info stmt_info,
+ gimple_stmt_iterator *gsi, stmt_vec_info *seen_store)
{
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
- if (!stmt_info)
- return;
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "------>vectorizing statement: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "------>vectorizing statement: %G", stmt_info->stmt);
if (MAY_HAVE_DEBUG_BIND_STMTS && !STMT_VINFO_LIVE_P (stmt_info))
- vect_loop_kill_debug_uses (loop, stmt);
+ vect_loop_kill_debug_uses (loop, stmt_info);
if (!STMT_VINFO_RELEVANT_P (stmt_info)
&& !STMT_VINFO_LIVE_P (stmt_info))
@@ -8345,30 +8185,15 @@ vect_transform_loop_stmt (loop_vec_info loop_vinfo, gimple *stmt,
dump_printf_loc (MSG_NOTE, vect_location, "multiple-types.\n");
}
- /* SLP. Schedule all the SLP instances when the first SLP stmt is
- reached. */
- if (slp_vect_type slptype = STMT_SLP_TYPE (stmt_info))
- {
-
- if (!*slp_scheduled)
- {
- *slp_scheduled = true;
-
- DUMP_VECT_SCOPE ("scheduling SLP instances");
-
- vect_schedule_slp (loop_vinfo);
- }
-
- /* Hybrid SLP stmts must be vectorized in addition to SLP. */
- if (slptype == pure_slp)
- return;
- }
+ /* Pure SLP statements have already been vectorized. We still need
+ to apply loop vectorization to hybrid SLP statements. */
+ if (PURE_SLP_STMT (stmt_info))
+ return;
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location, "transform statement.\n");
- bool grouped_store = false;
- if (vect_transform_stmt (stmt, gsi, &grouped_store, NULL, NULL))
+ if (vect_transform_stmt (stmt_info, gsi, NULL, NULL))
*seen_store = stmt_info;
}
@@ -8392,7 +8217,6 @@ vect_transform_loop (loop_vec_info loop_vinfo)
tree niters_vector_mult_vf = NULL_TREE;
poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
unsigned int lowest_vf = constant_lower_bound (vf);
- bool slp_scheduled = false;
gimple *stmt;
bool check_profitability = false;
unsigned int th;
@@ -8498,6 +8322,14 @@ vect_transform_loop (loop_vec_info loop_vinfo)
/* This will deal with any possible peeling. */
vect_prepare_for_masked_peels (loop_vinfo);
+ /* Schedule the SLP instances first, then handle loop vectorization
+ below. */
+ if (!loop_vinfo->slp_instances.is_empty ())
+ {
+ DUMP_VECT_SCOPE ("scheduling SLP instances");
+ vect_schedule_slp (loop_vinfo);
+ }
+
/* FORNOW: the vectorizer supports only loops which body consist
of one basic block (header + empty latch). When the vectorizer will
support more involved loop forms, the order by which the BBs are
@@ -8513,17 +8345,14 @@ vect_transform_loop (loop_vec_info loop_vinfo)
{
gphi *phi = si.phi ();
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "------>vectorizing phi: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, phi, 0);
- }
- stmt_info = vinfo_for_stmt (phi);
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "------>vectorizing phi: %G", phi);
+ stmt_info = loop_vinfo->lookup_stmt (phi);
if (!stmt_info)
continue;
if (MAY_HAVE_DEBUG_BIND_STMTS && !STMT_VINFO_LIVE_P (stmt_info))
- vect_loop_kill_debug_uses (loop, phi);
+ vect_loop_kill_debug_uses (loop, stmt_info);
if (!STMT_VINFO_RELEVANT_P (stmt_info)
&& !STMT_VINFO_LIVE_P (stmt_info))
@@ -8542,7 +8371,7 @@ vect_transform_loop (loop_vec_info loop_vinfo)
{
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location, "transform phi.\n");
- vect_transform_stmt (phi, NULL, NULL, NULL, NULL);
+ vect_transform_stmt (stmt_info, NULL, NULL, NULL);
}
}
@@ -8559,7 +8388,7 @@ vect_transform_loop (loop_vec_info loop_vinfo)
}
else
{
- stmt_info = vinfo_for_stmt (stmt);
+ stmt_info = loop_vinfo->lookup_stmt (stmt);
/* vector stmts created in the outer-loop during vectorization of
stmts in an inner-loop may not have a stmt_info, and do not
@@ -8572,39 +8401,32 @@ vect_transform_loop (loop_vec_info loop_vinfo)
gimple *def_seq = STMT_VINFO_PATTERN_DEF_SEQ (stmt_info);
for (gimple_stmt_iterator subsi = gsi_start (def_seq);
!gsi_end_p (subsi); gsi_next (&subsi))
- vect_transform_loop_stmt (loop_vinfo,
- gsi_stmt (subsi), &si,
- &seen_store,
- &slp_scheduled);
- gimple *pat_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
- vect_transform_loop_stmt (loop_vinfo, pat_stmt, &si,
- &seen_store, &slp_scheduled);
+ {
+ stmt_vec_info pat_stmt_info
+ = loop_vinfo->lookup_stmt (gsi_stmt (subsi));
+ vect_transform_loop_stmt (loop_vinfo, pat_stmt_info,
+ &si, &seen_store);
+ }
+ stmt_vec_info pat_stmt_info
+ = STMT_VINFO_RELATED_STMT (stmt_info);
+ vect_transform_loop_stmt (loop_vinfo, pat_stmt_info, &si,
+ &seen_store);
}
- vect_transform_loop_stmt (loop_vinfo, stmt, &si,
- &seen_store, &slp_scheduled);
+ vect_transform_loop_stmt (loop_vinfo, stmt_info, &si,
+ &seen_store);
}
+ gsi_next (&si);
if (seen_store)
{
if (STMT_VINFO_GROUPED_ACCESS (seen_store))
- {
- /* Interleaving. If IS_STORE is TRUE, the
- vectorization of the interleaving chain was
- completed - free all the stores in the chain. */
- gsi_next (&si);
- vect_remove_stores (DR_GROUP_FIRST_ELEMENT (seen_store));
- }
+ /* Interleaving. If IS_STORE is TRUE, the
+ vectorization of the interleaving chain was
+ completed - free all the stores in the chain. */
+ vect_remove_stores (DR_GROUP_FIRST_ELEMENT (seen_store));
else
- {
- /* Free the attached stmt_vec_info and remove the
- stmt. */
- free_stmt_vec_info (stmt);
- unlink_stmt_vdef (stmt);
- gsi_remove (&si, true);
- release_defs (stmt);
- }
+ /* Free the attached stmt_vec_info and remove the stmt. */
+ loop_vinfo->remove_stmt (stmt_info);
}
- else
- gsi_next (&si);
}
}
@@ -8708,7 +8530,7 @@ vect_transform_loop (loop_vec_info loop_vinfo)
won't work. */
slp_instance instance;
FOR_EACH_VEC_ELT (LOOP_VINFO_SLP_INSTANCES (loop_vinfo), i, instance)
- vect_free_slp_instance (instance);
+ vect_free_slp_instance (instance, true);
LOOP_VINFO_SLP_INSTANCES (loop_vinfo).release ();
/* Clear-up safelen field since its value is invalid after vectorization
since vectorized loop can have loop-carried dependencies. */
@@ -8894,11 +8716,8 @@ optimize_mask_stores (struct loop *loop)
/* Setup GSI_TO to the non-empty block start. */
gsi_to = gsi_start_bb (store_bb);
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "Move stmt to created bb\n");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, last, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Move stmt to created bb\n%G", last);
/* Move all stored value producers if possible. */
while (!gsi_end_p (gsi))
{
@@ -8962,11 +8781,8 @@ optimize_mask_stores (struct loop *loop)
/* Can move STMT1 to STORE_BB. */
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "Move stmt to created bb\n");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt1, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Move stmt to created bb\n%G", stmt1);
gsi_move_before (&gsi_from, &gsi_to);
/* Shift GSI_TO for further insertion. */
gsi_prev (&gsi_to);
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 0f63ccf..7956c13 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -88,33 +88,30 @@ static void
vect_pattern_detected (const char *name, gimple *stmt)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "%s: detected: ", name);
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "%s: detected: %G", name, stmt);
}
-/* Associate pattern statement PATTERN_STMT with ORIG_STMT_INFO.
- Set its vector type to VECTYPE if it doesn't have one already. */
+/* Associate pattern statement PATTERN_STMT with ORIG_STMT_INFO and
+ return the pattern statement's stmt_vec_info. Set its vector type to
+ VECTYPE if it doesn't have one already. */
-static void
+static stmt_vec_info
vect_init_pattern_stmt (gimple *pattern_stmt, stmt_vec_info orig_stmt_info,
tree vectype)
{
- stmt_vec_info pattern_stmt_info = vinfo_for_stmt (pattern_stmt);
+ vec_info *vinfo = orig_stmt_info->vinfo;
+ stmt_vec_info pattern_stmt_info = vinfo->lookup_stmt (pattern_stmt);
if (pattern_stmt_info == NULL)
- {
- pattern_stmt_info = new_stmt_vec_info (pattern_stmt,
- orig_stmt_info->vinfo);
- set_vinfo_for_stmt (pattern_stmt, pattern_stmt_info);
- }
+ pattern_stmt_info = orig_stmt_info->vinfo->add_stmt (pattern_stmt);
gimple_set_bb (pattern_stmt, gimple_bb (orig_stmt_info->stmt));
- STMT_VINFO_RELATED_STMT (pattern_stmt_info) = orig_stmt_info->stmt;
+ pattern_stmt_info->pattern_stmt_p = true;
+ STMT_VINFO_RELATED_STMT (pattern_stmt_info) = orig_stmt_info;
STMT_VINFO_DEF_TYPE (pattern_stmt_info)
= STMT_VINFO_DEF_TYPE (orig_stmt_info);
if (!STMT_VINFO_VECTYPE (pattern_stmt_info))
STMT_VINFO_VECTYPE (pattern_stmt_info) = vectype;
+ return pattern_stmt_info;
}
/* Set the pattern statement of ORIG_STMT_INFO to PATTERN_STMT.
@@ -126,8 +123,8 @@ vect_set_pattern_stmt (gimple *pattern_stmt, stmt_vec_info orig_stmt_info,
tree vectype)
{
STMT_VINFO_IN_PATTERN_P (orig_stmt_info) = true;
- STMT_VINFO_RELATED_STMT (orig_stmt_info) = pattern_stmt;
- vect_init_pattern_stmt (pattern_stmt, orig_stmt_info, vectype);
+ STMT_VINFO_RELATED_STMT (orig_stmt_info)
+ = vect_init_pattern_stmt (pattern_stmt, orig_stmt_info, vectype);
}
/* Add NEW_STMT to STMT_INFO's pattern definition statements. If VECTYPE
@@ -141,9 +138,7 @@ append_pattern_def_seq (stmt_vec_info stmt_info, gimple *new_stmt,
vec_info *vinfo = stmt_info->vinfo;
if (vectype)
{
- gcc_assert (!vinfo_for_stmt (new_stmt));
- stmt_vec_info new_stmt_info = new_stmt_vec_info (new_stmt, vinfo);
- set_vinfo_for_stmt (new_stmt, new_stmt_info);
+ stmt_vec_info new_stmt_info = vinfo->add_stmt (new_stmt);
STMT_VINFO_VECTYPE (new_stmt_info) = vectype;
}
gimple_seq_add_stmt_without_update (&STMT_VINFO_PATTERN_DEF_SEQ (stmt_info),
@@ -232,33 +227,30 @@ vect_element_precision (unsigned int precision)
static stmt_vec_info
vect_get_internal_def (vec_info *vinfo, tree op)
{
- vect_def_type dt;
- gimple *def_stmt;
- if (TREE_CODE (op) != SSA_NAME
- || !vect_is_simple_use (op, vinfo, &dt, &def_stmt)
- || dt != vect_internal_def)
- return NULL;
-
- return vinfo_for_stmt (def_stmt);
+ stmt_vec_info def_stmt_info = vinfo->lookup_def (op);
+ if (def_stmt_info
+ && STMT_VINFO_DEF_TYPE (def_stmt_info) == vect_internal_def)
+ return def_stmt_info;
+ return NULL;
}
-/* Check whether NAME, an ssa-name used in USE_STMT,
+/* Check whether NAME, an ssa-name used in STMT_VINFO,
is a result of a type promotion, such that:
DEF_STMT: NAME = NOP (name0)
If CHECK_SIGN is TRUE, check that either both types are signed or both are
unsigned. */
static bool
-type_conversion_p (tree name, gimple *use_stmt, bool check_sign,
+type_conversion_p (tree name, stmt_vec_info stmt_vinfo, bool check_sign,
tree *orig_type, gimple **def_stmt, bool *promotion)
{
- stmt_vec_info stmt_vinfo;
tree type = TREE_TYPE (name);
tree oprnd0;
enum vect_def_type dt;
- stmt_vinfo = vinfo_for_stmt (use_stmt);
- if (!vect_is_simple_use (name, stmt_vinfo->vinfo, &dt, def_stmt))
+ stmt_vec_info def_stmt_info;
+ if (!vect_is_simple_use (name, stmt_vinfo->vinfo, &dt, &def_stmt_info,
+ def_stmt))
return false;
if (dt != vect_internal_def
@@ -379,9 +371,10 @@ vect_look_through_possible_promotion (vec_info *vinfo, tree op,
while (TREE_CODE (op) == SSA_NAME && INTEGRAL_TYPE_P (op_type))
{
/* See whether OP is simple enough to vectorize. */
+ stmt_vec_info def_stmt_info;
gimple *def_stmt;
vect_def_type dt;
- if (!vect_is_simple_use (op, vinfo, &dt, &def_stmt))
+ if (!vect_is_simple_use (op, vinfo, &dt, &def_stmt_info, &def_stmt))
break;
/* If OP is the input of a demotion, skip over it to see whether
@@ -415,17 +408,15 @@ vect_look_through_possible_promotion (vec_info *vinfo, tree op,
the cast is potentially vectorizable. */
if (!def_stmt)
break;
- if (dt == vect_internal_def)
- {
- caster = vinfo_for_stmt (def_stmt);
- /* Ignore pattern statements, since we don't link uses for them. */
- if (single_use_p
- && !STMT_VINFO_RELATED_STMT (caster)
- && !has_single_use (res))
- *single_use_p = false;
- }
- else
- caster = NULL;
+ caster = def_stmt_info;
+
+ /* Ignore pattern statements, since we don't link uses for them. */
+ if (caster
+ && single_use_p
+ && !STMT_VINFO_RELATED_STMT (caster)
+ && !has_single_use (res))
+ *single_use_p = false;
+
gassign *assign = dyn_cast <gassign *> (def_stmt);
if (!assign || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
break;
@@ -533,6 +524,7 @@ vect_widened_op_tree (stmt_vec_info stmt_info, tree_code code,
vect_unpromoted_value *unprom, tree *common_type)
{
/* Check for an integer operation with the right code. */
+ vec_info *vinfo = stmt_info->vinfo;
gassign *assign = dyn_cast <gassign *> (stmt_info->stmt);
if (!assign)
return 0;
@@ -589,7 +581,7 @@ vect_widened_op_tree (stmt_vec_info stmt_info, tree_code code,
/* Recursively process the definition of the operand. */
stmt_vec_info def_stmt_info
- = vinfo_for_stmt (SSA_NAME_DEF_STMT (this_unprom->op));
+ = vinfo->lookup_def (this_unprom->op);
nops = vect_widened_op_tree (def_stmt_info, code, widened_code,
shift_p, max_nops, this_unprom,
common_type);
@@ -640,16 +632,12 @@ vect_split_statement (stmt_vec_info stmt2_info, tree new_rhs,
{
/* STMT2_INFO is part of a pattern. Get the statement to which
the pattern is attached. */
- stmt_vec_info orig_stmt2_info
- = vinfo_for_stmt (STMT_VINFO_RELATED_STMT (stmt2_info));
+ stmt_vec_info orig_stmt2_info = STMT_VINFO_RELATED_STMT (stmt2_info);
vect_init_pattern_stmt (stmt1, orig_stmt2_info, vectype);
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "Splitting pattern statement: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt2_info->stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Splitting pattern statement: %G", stmt2_info->stmt);
/* Since STMT2_INFO is a pattern statement, we can change it
in-situ without worrying about changing the code for the
@@ -658,14 +646,13 @@ vect_split_statement (stmt_vec_info stmt2_info, tree new_rhs,
if (dump_enabled_p ())
{
- dump_printf_loc (MSG_NOTE, vect_location, "into: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt1, 0);
- dump_printf_loc (MSG_NOTE, vect_location, "and: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt2_info->stmt, 0);
+ dump_printf_loc (MSG_NOTE, vect_location, "into: %G", stmt1);
+ dump_printf_loc (MSG_NOTE, vect_location, "and: %G",
+ stmt2_info->stmt);
}
gimple_seq *def_seq = &STMT_VINFO_PATTERN_DEF_SEQ (orig_stmt2_info);
- if (STMT_VINFO_RELATED_STMT (orig_stmt2_info) == stmt2_info->stmt)
+ if (STMT_VINFO_RELATED_STMT (orig_stmt2_info) == stmt2_info)
/* STMT2_INFO is the actual pattern statement. Add STMT1
to the end of the definition sequence. */
gimple_seq_add_stmt_without_update (def_seq, stmt1);
@@ -689,11 +676,8 @@ vect_split_statement (stmt_vec_info stmt2_info, tree new_rhs,
return false;
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "Splitting statement: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt2_info->stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Splitting statement: %G", stmt2_info->stmt);
/* Add STMT1 as a singleton pattern definition sequence. */
gimple_seq *def_seq = &STMT_VINFO_PATTERN_DEF_SEQ (stmt2_info);
@@ -708,10 +692,8 @@ vect_split_statement (stmt_vec_info stmt2_info, tree new_rhs,
if (dump_enabled_p ())
{
dump_printf_loc (MSG_NOTE, vect_location,
- "into pattern statements: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt1, 0);
- dump_printf_loc (MSG_NOTE, vect_location, "and: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, new_stmt2, 0);
+ "into pattern statements: %G", stmt1);
+ dump_printf_loc (MSG_NOTE, vect_location, "and: %G", new_stmt2);
}
return true;
@@ -847,7 +829,7 @@ vect_reassociating_reduction_p (stmt_vec_info stmt_info, tree_code code,
/* We don't allow changing the order of the computation in the inner-loop
when doing outer-loop vectorization. */
struct loop *loop = LOOP_VINFO_LOOP (loop_info);
- if (loop && nested_in_vect_loop_p (loop, assign))
+ if (loop && nested_in_vect_loop_p (loop, stmt_info))
return false;
if (!vect_reassociating_reduction_p (stmt_info))
@@ -1201,7 +1183,7 @@ vect_recog_widen_op_pattern (stmt_vec_info last_stmt_info, tree *type_out,
auto_vec<tree> dummy_vec;
if (!vectype
|| !vecitype
- || !supportable_widening_operation (wide_code, last_stmt,
+ || !supportable_widening_operation (wide_code, last_stmt_info,
vecitype, vectype,
&dummy_code, &dummy_code,
&dummy_int, &dummy_vec))
@@ -1668,13 +1650,8 @@ vect_recog_over_widening_pattern (stmt_vec_info last_stmt_info, tree *type_out)
return NULL;
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "demoting ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, type);
- dump_printf (MSG_NOTE, " to ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, new_type);
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "demoting %T to %T\n",
+ type, new_type);
/* Calculate the rhs operands for an operation on NEW_TYPE. */
tree ops[3] = {};
@@ -1690,11 +1667,8 @@ vect_recog_over_widening_pattern (stmt_vec_info last_stmt_info, tree *type_out)
gimple_set_location (pattern_stmt, gimple_location (last_stmt));
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "created pattern stmt: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "created pattern stmt: %G", pattern_stmt);
pattern_stmt = vect_convert_output (last_stmt_info, type,
pattern_stmt, new_vectype);
@@ -1837,11 +1811,8 @@ vect_recog_average_pattern (stmt_vec_info last_stmt_info, tree *type_out)
gimple_set_location (average_stmt, gimple_location (last_stmt));
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "created pattern stmt: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, average_stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "created pattern stmt: %G", average_stmt);
return vect_convert_output (last_stmt_info, type, average_stmt, new_vectype);
}
@@ -1995,7 +1966,8 @@ vect_recog_rotate_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
|| !TYPE_UNSIGNED (type))
return NULL;
- if (!vect_is_simple_use (oprnd1, vinfo, &dt, &def_stmt))
+ stmt_vec_info def_stmt_info;
+ if (!vect_is_simple_use (oprnd1, vinfo, &dt, &def_stmt_info, &def_stmt))
return NULL;
if (dt != vect_internal_def
@@ -3122,11 +3094,11 @@ vect_recog_mixed_size_cond_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
return NULL;
if ((TREE_CODE (then_clause) != INTEGER_CST
- && !type_conversion_p (then_clause, last_stmt, false, &orig_type0,
- &def_stmt0, &promotion))
+ && !type_conversion_p (then_clause, stmt_vinfo, false, &orig_type0,
+ &def_stmt0, &promotion))
|| (TREE_CODE (else_clause) != INTEGER_CST
- && !type_conversion_p (else_clause, last_stmt, false, &orig_type1,
- &def_stmt1, &promotion)))
+ && !type_conversion_p (else_clause, stmt_vinfo, false, &orig_type1,
+ &def_stmt1, &promotion)))
return NULL;
if (orig_type0 && orig_type1
@@ -3502,12 +3474,12 @@ sort_after_uid (const void *p1, const void *p2)
}
/* Create pattern stmts for all stmts participating in the bool pattern
- specified by BOOL_STMT_SET and its root STMT with the desired type
+ specified by BOOL_STMT_SET and its root STMT_INFO with the desired type
OUT_TYPE. Return the def of the pattern root. */
static tree
adjust_bool_stmts (hash_set <gimple *> &bool_stmt_set,
- tree out_type, gimple *stmt)
+ tree out_type, stmt_vec_info stmt_info)
{
/* Gather original stmts in the bool pattern in their order of appearance
in the IL. */
@@ -3521,11 +3493,11 @@ adjust_bool_stmts (hash_set <gimple *> &bool_stmt_set,
hash_map <tree, tree> defs;
for (unsigned i = 0; i < bool_stmts.length (); ++i)
adjust_bool_pattern (gimple_assign_lhs (bool_stmts[i]),
- out_type, vinfo_for_stmt (stmt), defs);
+ out_type, stmt_info, defs);
/* Pop the last pattern seq stmt and install it as pattern root for STMT. */
gimple *pattern_stmt
- = gimple_seq_last_stmt (STMT_VINFO_PATTERN_DEF_SEQ (vinfo_for_stmt (stmt)));
+ = gimple_seq_last_stmt (STMT_VINFO_PATTERN_DEF_SEQ (stmt_info));
return gimple_assign_lhs (pattern_stmt);
}
@@ -3711,7 +3683,7 @@ vect_recog_bool_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
if (check_bool_pattern (var, vinfo, bool_stmts))
{
- rhs = adjust_bool_stmts (bool_stmts, TREE_TYPE (lhs), last_stmt);
+ rhs = adjust_bool_stmts (bool_stmts, TREE_TYPE (lhs), stmt_vinfo);
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 (lhs, SSA_NAME, rhs);
@@ -3778,7 +3750,7 @@ vect_recog_bool_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
if (!check_bool_pattern (var, vinfo, bool_stmts))
return NULL;
- rhs = adjust_bool_stmts (bool_stmts, type, last_stmt);
+ rhs = adjust_bool_stmts (bool_stmts, type, stmt_vinfo);
lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
pattern_stmt
@@ -3802,7 +3774,7 @@ vect_recog_bool_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
return NULL;
if (check_bool_pattern (var, vinfo, bool_stmts))
- rhs = adjust_bool_stmts (bool_stmts, TREE_TYPE (vectype), last_stmt);
+ rhs = adjust_bool_stmts (bool_stmts, TREE_TYPE (vectype), stmt_vinfo);
else
{
tree type = search_type_for_mask (var, vinfo);
@@ -3832,12 +3804,8 @@ vect_recog_bool_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
rhs = rhs2;
}
pattern_stmt = gimple_build_assign (lhs, SSA_NAME, rhs);
- pattern_stmt_info = new_stmt_vec_info (pattern_stmt, vinfo);
- set_vinfo_for_stmt (pattern_stmt, pattern_stmt_info);
- STMT_VINFO_DATA_REF (pattern_stmt_info)
- = STMT_VINFO_DATA_REF (stmt_vinfo);
- STMT_VINFO_DR_WRT_VEC_LOOP (pattern_stmt_info)
- = STMT_VINFO_DR_WRT_VEC_LOOP (stmt_vinfo);
+ pattern_stmt_info = vinfo->add_stmt (pattern_stmt);
+ vinfo->move_dr (pattern_stmt_info, stmt_vinfo);
*type_out = vectype;
vect_pattern_detected ("vect_recog_bool_pattern", last_stmt);
@@ -3958,17 +3926,9 @@ vect_recog_mask_conversion_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
}
gimple_call_set_nothrow (pattern_stmt, true);
- pattern_stmt_info = new_stmt_vec_info (pattern_stmt, vinfo);
- set_vinfo_for_stmt (pattern_stmt, pattern_stmt_info);
+ pattern_stmt_info = vinfo->add_stmt (pattern_stmt);
if (STMT_VINFO_DATA_REF (stmt_vinfo))
- {
- STMT_VINFO_DATA_REF (pattern_stmt_info)
- = STMT_VINFO_DATA_REF (stmt_vinfo);
- STMT_VINFO_DR_WRT_VEC_LOOP (pattern_stmt_info)
- = STMT_VINFO_DR_WRT_VEC_LOOP (stmt_vinfo);
- STMT_VINFO_GATHER_SCATTER_P (pattern_stmt_info)
- = STMT_VINFO_GATHER_SCATTER_P (stmt_vinfo);
- }
+ vinfo->move_dr (pattern_stmt_info, stmt_vinfo);
*type_out = vectype1;
vect_pattern_detected ("vect_recog_mask_conversion_pattern", last_stmt);
@@ -4130,19 +4090,19 @@ vect_recog_mask_conversion_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
return pattern_stmt;
}
-/* STMT is a load or store. If the load or store is conditional, return
+/* STMT_INFO is a load or store. If the load or store is conditional, return
the boolean condition under which it occurs, otherwise return null. */
static tree
-vect_get_load_store_mask (gimple *stmt)
+vect_get_load_store_mask (stmt_vec_info stmt_info)
{
- if (gassign *def_assign = dyn_cast <gassign *> (stmt))
+ if (gassign *def_assign = dyn_cast <gassign *> (stmt_info->stmt))
{
gcc_assert (gimple_assign_single_p (def_assign));
return NULL_TREE;
}
- if (gcall *def_call = dyn_cast <gcall *> (stmt))
+ if (gcall *def_call = dyn_cast <gcall *> (stmt_info->stmt))
{
internal_fn ifn = gimple_call_internal_fn (def_call);
int mask_index = internal_fn_mask_index (ifn);
@@ -4238,13 +4198,12 @@ vect_recog_gather_scatter_pattern (stmt_vec_info stmt_info, tree *type_out)
/* Get the boolean that controls whether the load or store happens.
This is null if the operation is unconditional. */
- gimple *stmt = stmt_info->stmt;
- tree mask = vect_get_load_store_mask (stmt);
+ tree mask = vect_get_load_store_mask (stmt_info);
/* Make sure that the target supports an appropriate internal
function for the gather/scatter operation. */
gather_scatter_info gs_info;
- if (!vect_check_gather_scatter (stmt, loop_vinfo, &gs_info)
+ if (!vect_check_gather_scatter (stmt_info, loop_vinfo, &gs_info)
|| gs_info.decl)
return NULL;
@@ -4277,7 +4236,7 @@ vect_recog_gather_scatter_pattern (stmt_vec_info stmt_info, tree *type_out)
}
else
{
- tree rhs = vect_get_store_rhs (stmt);
+ tree rhs = vect_get_store_rhs (stmt_info);
if (mask != NULL)
pattern_stmt = gimple_build_call_internal (IFN_MASK_SCATTER_STORE, 5,
base, offset, scale, rhs,
@@ -4290,18 +4249,12 @@ vect_recog_gather_scatter_pattern (stmt_vec_info stmt_info, tree *type_out)
/* Copy across relevant vectorization info and associate DR with the
new pattern statement instead of the original statement. */
- stmt_vec_info pattern_stmt_info = new_stmt_vec_info (pattern_stmt,
- loop_vinfo);
- set_vinfo_for_stmt (pattern_stmt, pattern_stmt_info);
- STMT_VINFO_DATA_REF (pattern_stmt_info) = dr;
- STMT_VINFO_DR_WRT_VEC_LOOP (pattern_stmt_info)
- = STMT_VINFO_DR_WRT_VEC_LOOP (stmt_info);
- STMT_VINFO_GATHER_SCATTER_P (pattern_stmt_info)
- = STMT_VINFO_GATHER_SCATTER_P (stmt_info);
+ stmt_vec_info pattern_stmt_info = loop_vinfo->add_stmt (pattern_stmt);
+ loop_vinfo->move_dr (pattern_stmt_info, stmt_info);
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
*type_out = vectype;
- vect_pattern_detected ("gather/scatter pattern", stmt);
+ vect_pattern_detected ("gather/scatter pattern", stmt_info->stmt);
return pattern_stmt;
}
@@ -4411,6 +4364,7 @@ static bool
vect_determine_min_output_precision_1 (stmt_vec_info stmt_info, tree lhs)
{
/* Take the maximum precision required by users of the result. */
+ vec_info *vinfo = stmt_info->vinfo;
unsigned int precision = 0;
imm_use_iterator iter;
use_operand_p use;
@@ -4419,21 +4373,24 @@ vect_determine_min_output_precision_1 (stmt_vec_info stmt_info, tree lhs)
gimple *use_stmt = USE_STMT (use);
if (is_gimple_debug (use_stmt))
continue;
- if (!vect_stmt_in_region_p (stmt_info->vinfo, use_stmt))
+ stmt_vec_info use_stmt_info = vinfo->lookup_stmt (use_stmt);
+ if (!use_stmt_info || !use_stmt_info->min_input_precision)
return false;
- stmt_vec_info use_stmt_info = vinfo_for_stmt (use_stmt);
- if (!use_stmt_info->min_input_precision)
+ /* The input precision recorded for COND_EXPRs applies only to the
+ "then" and "else" values. */
+ gassign *assign = dyn_cast <gassign *> (stmt_info->stmt);
+ if (assign
+ && gimple_assign_rhs_code (assign) == COND_EXPR
+ && use->use != gimple_assign_rhs2_ptr (assign)
+ && use->use != gimple_assign_rhs3_ptr (assign))
return false;
precision = MAX (precision, use_stmt_info->min_input_precision);
}
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "only the low %d bits of ",
- precision);
- dump_generic_expr (MSG_NOTE, TDF_SLIM, lhs);
- dump_printf (MSG_NOTE, " are significant\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "only the low %d bits of %T are significant\n",
+ precision, lhs);
stmt_info->min_output_precision = precision;
return true;
}
@@ -4541,13 +4498,10 @@ vect_determine_precisions_from_range (stmt_vec_info stmt_info, gassign *stmt)
return;
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "can narrow to %s:%d"
- " without loss of precision: ",
- sign == SIGNED ? "signed" : "unsigned",
- value_precision);
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "can narrow to %s:%d"
+ " without loss of precision: %G",
+ sign == SIGNED ? "signed" : "unsigned",
+ value_precision, stmt);
vect_set_operation_type (stmt_info, type, value_precision, sign);
vect_set_min_input_precision (stmt_info, type, value_precision);
@@ -4616,13 +4570,10 @@ vect_determine_precisions_from_users (stmt_vec_info stmt_info, gassign *stmt)
if (operation_precision < precision)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "can narrow to %s:%d"
- " without affecting users: ",
- TYPE_UNSIGNED (type) ? "unsigned" : "signed",
- operation_precision);
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "can narrow to %s:%d"
+ " without affecting users: %G",
+ TYPE_UNSIGNED (type) ? "unsigned" : "signed",
+ operation_precision, stmt);
vect_set_operation_type (stmt_info, type, operation_precision,
TYPE_SIGN (type));
}
@@ -4667,7 +4618,8 @@ vect_determine_precisions (vec_info *vinfo)
basic_block bb = bbs[nbbs - i - 1];
for (gimple_stmt_iterator si = gsi_last_bb (bb);
!gsi_end_p (si); gsi_prev (&si))
- vect_determine_stmt_precisions (vinfo_for_stmt (gsi_stmt (si)));
+ vect_determine_stmt_precisions
+ (vinfo->lookup_stmt (gsi_stmt (si)));
}
}
else
@@ -4682,7 +4634,7 @@ vect_determine_precisions (vec_info *vinfo)
else
gsi_prev (&si);
stmt = gsi_stmt (si);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ stmt_vec_info stmt_info = vinfo->lookup_stmt (stmt);
if (stmt_info && STMT_VINFO_VECTORIZABLE (stmt_info))
vect_determine_stmt_precisions (stmt_info);
}
@@ -4731,43 +4683,37 @@ const unsigned int NUM_PATTERNS = ARRAY_SIZE (vect_vect_recog_func_ptrs);
/* Mark statements that are involved in a pattern. */
static inline void
-vect_mark_pattern_stmts (gimple *orig_stmt, gimple *pattern_stmt,
+vect_mark_pattern_stmts (stmt_vec_info orig_stmt_info, gimple *pattern_stmt,
tree pattern_vectype)
{
- stmt_vec_info orig_stmt_info = vinfo_for_stmt (orig_stmt);
gimple *def_seq = STMT_VINFO_PATTERN_DEF_SEQ (orig_stmt_info);
- bool old_pattern_p = is_pattern_stmt_p (orig_stmt_info);
- if (old_pattern_p)
+ gimple *orig_pattern_stmt = NULL;
+ if (is_pattern_stmt_p (orig_stmt_info))
{
/* We're replacing a statement in an existing pattern definition
sequence. */
+ orig_pattern_stmt = orig_stmt_info->stmt;
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "replacing earlier pattern ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, orig_stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "replacing earlier pattern %G", orig_pattern_stmt);
/* To keep the book-keeping simple, just swap the lhs of the
old and new statements, so that the old one has a valid but
unused lhs. */
- tree old_lhs = gimple_get_lhs (orig_stmt);
- gimple_set_lhs (orig_stmt, gimple_get_lhs (pattern_stmt));
+ tree old_lhs = gimple_get_lhs (orig_pattern_stmt);
+ gimple_set_lhs (orig_pattern_stmt, gimple_get_lhs (pattern_stmt));
gimple_set_lhs (pattern_stmt, old_lhs);
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "with ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "with %G", pattern_stmt);
/* Switch to the statement that ORIG replaces. */
- orig_stmt_info
- = vinfo_for_stmt (STMT_VINFO_RELATED_STMT (orig_stmt_info));
+ orig_stmt_info = STMT_VINFO_RELATED_STMT (orig_stmt_info);
/* We shouldn't be replacing the main pattern statement. */
- gcc_assert (STMT_VINFO_RELATED_STMT (orig_stmt_info) != orig_stmt);
+ gcc_assert (STMT_VINFO_RELATED_STMT (orig_stmt_info)->stmt
+ != orig_pattern_stmt);
}
if (def_seq)
@@ -4775,13 +4721,14 @@ vect_mark_pattern_stmts (gimple *orig_stmt, gimple *pattern_stmt,
!gsi_end_p (si); gsi_next (&si))
vect_init_pattern_stmt (gsi_stmt (si), orig_stmt_info, pattern_vectype);
- if (old_pattern_p)
+ if (orig_pattern_stmt)
{
vect_init_pattern_stmt (pattern_stmt, orig_stmt_info, pattern_vectype);
/* Insert all the new pattern statements before the original one. */
gimple_seq *orig_def_seq = &STMT_VINFO_PATTERN_DEF_SEQ (orig_stmt_info);
- gimple_stmt_iterator gsi = gsi_for_stmt (orig_stmt, orig_def_seq);
+ gimple_stmt_iterator gsi = gsi_for_stmt (orig_pattern_stmt,
+ orig_def_seq);
gsi_insert_seq_before_without_update (&gsi, def_seq, GSI_SAME_STMT);
gsi_insert_before_without_update (&gsi, pattern_stmt, GSI_SAME_STMT);
@@ -4797,12 +4744,12 @@ vect_mark_pattern_stmts (gimple *orig_stmt, gimple *pattern_stmt,
Input:
PATTERN_RECOG_FUNC: A pointer to a function that detects a certain
computation pattern.
- STMT: A stmt from which the pattern search should start.
+ STMT_INFO: A stmt from which the pattern search should start.
If PATTERN_RECOG_FUNC successfully detected the pattern, it creates
a sequence of statements that has the same functionality and can be
- used to replace STMT. It returns the last statement in the sequence
- and adds any earlier statements to STMT's STMT_VINFO_PATTERN_DEF_SEQ.
+ used to replace STMT_INFO. It returns the last statement in the sequence
+ and adds any earlier statements to STMT_INFO's STMT_VINFO_PATTERN_DEF_SEQ.
PATTERN_RECOG_FUNC also sets *TYPE_OUT to the vector type of the final
statement, having first checked that the target supports the new operation
in that type.
@@ -4811,10 +4758,10 @@ vect_mark_pattern_stmts (gimple *orig_stmt, gimple *pattern_stmt,
for vect_recog_pattern. */
static void
-vect_pattern_recog_1 (vect_recog_func *recog_func, gimple_stmt_iterator si)
+vect_pattern_recog_1 (vect_recog_func *recog_func, stmt_vec_info stmt_info)
{
- gimple *stmt = gsi_stmt (si), *pattern_stmt;
- stmt_vec_info stmt_info;
+ vec_info *vinfo = stmt_info->vinfo;
+ gimple *pattern_stmt;
loop_vec_info loop_vinfo;
tree pattern_vectype;
@@ -4822,13 +4769,12 @@ vect_pattern_recog_1 (vect_recog_func *recog_func, gimple_stmt_iterator si)
leave the original statement alone, since the first match wins.
Instead try to match against the definition statements that feed
the main pattern statement. */
- stmt_info = vinfo_for_stmt (stmt);
if (STMT_VINFO_IN_PATTERN_P (stmt_info))
{
gimple_stmt_iterator gsi;
for (gsi = gsi_start (STMT_VINFO_PATTERN_DEF_SEQ (stmt_info));
!gsi_end_p (gsi); gsi_next (&gsi))
- vect_pattern_recog_1 (recog_func, gsi);
+ vect_pattern_recog_1 (recog_func, vinfo->lookup_stmt (gsi_stmt (gsi)));
return;
}
@@ -4846,23 +4792,21 @@ vect_pattern_recog_1 (vect_recog_func *recog_func, gimple_stmt_iterator si)
/* Found a vectorizable pattern. */
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "%s pattern recognized: ", recog_func->name);
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "%s pattern recognized: %G",
+ recog_func->name, pattern_stmt);
/* Mark the stmts that are involved in the pattern. */
- vect_mark_pattern_stmts (stmt, pattern_stmt, pattern_vectype);
+ vect_mark_pattern_stmts (stmt_info, pattern_stmt, pattern_vectype);
/* Patterns cannot be vectorized using SLP, because they change the order of
computation. */
if (loop_vinfo)
{
unsigned ix, ix2;
- gimple **elem_ptr;
+ stmt_vec_info *elem_ptr;
VEC_ORDERED_REMOVE_IF (LOOP_VINFO_REDUCTIONS (loop_vinfo), ix, ix2,
- elem_ptr, *elem_ptr == stmt);
+ elem_ptr, *elem_ptr == stmt_info);
}
}
@@ -4969,9 +4913,13 @@ vect_pattern_recog (vec_info *vinfo)
{
basic_block bb = bbs[i];
for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
- /* Scan over all generic vect_recog_xxx_pattern functions. */
- for (j = 0; j < NUM_PATTERNS; j++)
- vect_pattern_recog_1 (&vect_vect_recog_func_ptrs[j], si);
+ {
+ stmt_vec_info stmt_info = vinfo->lookup_stmt (gsi_stmt (si));
+ /* Scan over all generic vect_recog_xxx_pattern functions. */
+ for (j = 0; j < NUM_PATTERNS; j++)
+ vect_pattern_recog_1 (&vect_vect_recog_func_ptrs[j],
+ stmt_info);
+ }
}
}
else
@@ -4981,13 +4929,13 @@ vect_pattern_recog (vec_info *vinfo)
gsi_stmt (si) != gsi_stmt (bb_vinfo->region_end); gsi_next (&si))
{
gimple *stmt = gsi_stmt (si);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ stmt_vec_info stmt_info = bb_vinfo->lookup_stmt (stmt);
if (stmt_info && !STMT_VINFO_VECTORIZABLE (stmt_info))
continue;
/* Scan over all generic vect_recog_xxx_pattern functions. */
for (j = 0; j < NUM_PATTERNS; j++)
- vect_pattern_recog_1 (&vect_vect_recog_func_ptrs[j], si);
+ vect_pattern_recog_1 (&vect_vect_recog_func_ptrs[j], stmt_info);
}
}
}
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 8dc5763..ae1c453 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -47,25 +47,32 @@ along with GCC; see the file COPYING3. If not see
#include "internal-fn.h"
-/* Recursively free the memory allocated for the SLP tree rooted at NODE. */
+/* Recursively free the memory allocated for the SLP tree rooted at NODE.
+ FINAL_P is true if we have vectorized the instance or if we have
+ made a final decision not to vectorize the statements in any way. */
static void
-vect_free_slp_tree (slp_tree node)
+vect_free_slp_tree (slp_tree node, bool final_p)
{
int i;
slp_tree child;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
- vect_free_slp_tree (child);
+ vect_free_slp_tree (child, final_p);
- gimple *stmt;
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt)
- /* After transform some stmts are removed and thus their vinfo is gone. */
- if (vinfo_for_stmt (stmt))
- {
- gcc_assert (STMT_VINFO_NUM_SLP_USES (vinfo_for_stmt (stmt)) > 0);
- STMT_VINFO_NUM_SLP_USES (vinfo_for_stmt (stmt))--;
- }
+ /* Don't update STMT_VINFO_NUM_SLP_USES if it isn't relevant.
+ Some statements might no longer exist, after having been
+ removed by vect_transform_stmt. Updating the remaining
+ statements would be redundant. */
+ if (!final_p)
+ {
+ stmt_vec_info stmt_info;
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
+ {
+ gcc_assert (STMT_VINFO_NUM_SLP_USES (stmt_info) > 0);
+ STMT_VINFO_NUM_SLP_USES (stmt_info)--;
+ }
+ }
SLP_TREE_CHILDREN (node).release ();
SLP_TREE_SCALAR_STMTS (node).release ();
@@ -76,12 +83,14 @@ vect_free_slp_tree (slp_tree node)
}
-/* Free the memory allocated for the SLP instance. */
+/* Free the memory allocated for the SLP instance. FINAL_P is true if we
+ have vectorized the instance or if we have made a final decision not
+ to vectorize the statements in any way. */
void
-vect_free_slp_instance (slp_instance instance)
+vect_free_slp_instance (slp_instance instance, bool final_p)
{
- vect_free_slp_tree (SLP_INSTANCE_TREE (instance));
+ vect_free_slp_tree (SLP_INSTANCE_TREE (instance), final_p);
SLP_INSTANCE_LOADS (instance).release ();
free (instance);
}
@@ -90,21 +99,21 @@ vect_free_slp_instance (slp_instance instance)
/* Create an SLP node for SCALAR_STMTS. */
static slp_tree
-vect_create_new_slp_node (vec<gimple *> scalar_stmts)
+vect_create_new_slp_node (vec<stmt_vec_info> scalar_stmts)
{
slp_tree node;
- gimple *stmt = scalar_stmts[0];
+ stmt_vec_info stmt_info = scalar_stmts[0];
unsigned int nops;
- if (is_gimple_call (stmt))
+ if (gcall *stmt = dyn_cast <gcall *> (stmt_info->stmt))
nops = gimple_call_num_args (stmt);
- else if (is_gimple_assign (stmt))
+ else if (gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt))
{
nops = gimple_num_ops (stmt) - 1;
if (gimple_assign_rhs_code (stmt) == COND_EXPR)
nops++;
}
- else if (gimple_code (stmt) == GIMPLE_PHI)
+ else if (is_a <gphi *> (stmt_info->stmt))
nops = 0;
else
return NULL;
@@ -119,8 +128,8 @@ vect_create_new_slp_node (vec<gimple *> scalar_stmts)
SLP_TREE_DEF_TYPE (node) = vect_internal_def;
unsigned i;
- FOR_EACH_VEC_ELT (scalar_stmts, i, stmt)
- STMT_VINFO_NUM_SLP_USES (vinfo_for_stmt (stmt))++;
+ FOR_EACH_VEC_ELT (scalar_stmts, i, stmt_info)
+ STMT_VINFO_NUM_SLP_USES (stmt_info)++;
return node;
}
@@ -132,7 +141,7 @@ vect_create_new_slp_node (vec<gimple *> scalar_stmts)
typedef struct _slp_oprnd_info
{
/* Def-stmts for the operands. */
- vec<gimple *> def_stmts;
+ vec<stmt_vec_info> def_stmts;
/* Information about the first statement, its vector def-type, type, the
operand itself in case it's constant, and an indication if it's a pattern
stmt. */
@@ -186,27 +195,29 @@ vect_free_oprnd_info (vec<slp_oprnd_info> &oprnds_info)
}
-/* Find the place of the data-ref in STMT in the interleaving chain that starts
- from FIRST_STMT. Return -1 if the data-ref is not a part of the chain. */
+/* Find the place of the data-ref in STMT_INFO in the interleaving chain
+ that starts from FIRST_STMT_INFO. Return -1 if the data-ref is not a part
+ of the chain. */
int
-vect_get_place_in_interleaving_chain (gimple *stmt, gimple *first_stmt)
+vect_get_place_in_interleaving_chain (stmt_vec_info stmt_info,
+ stmt_vec_info first_stmt_info)
{
- gimple *next_stmt = first_stmt;
+ stmt_vec_info next_stmt_info = first_stmt_info;
int result = 0;
- if (first_stmt != DR_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)))
+ if (first_stmt_info != DR_GROUP_FIRST_ELEMENT (stmt_info))
return -1;
do
{
- if (next_stmt == stmt)
+ if (next_stmt_info == stmt_info)
return result;
- next_stmt = DR_GROUP_NEXT_ELEMENT (vinfo_for_stmt (next_stmt));
- if (next_stmt)
- result += DR_GROUP_GAP (vinfo_for_stmt (next_stmt));
+ next_stmt_info = DR_GROUP_NEXT_ELEMENT (next_stmt_info);
+ if (next_stmt_info)
+ result += DR_GROUP_GAP (next_stmt_info);
}
- while (next_stmt);
+ while (next_stmt_info);
return -1;
}
@@ -288,28 +299,32 @@ can_duplicate_and_interleave_p (unsigned int count, machine_mode elt_mode,
ok return 0. */
static int
vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char *swap,
- vec<gimple *> stmts, unsigned stmt_num,
+ vec<stmt_vec_info> stmts, unsigned stmt_num,
vec<slp_oprnd_info> *oprnds_info)
{
- gimple *stmt = stmts[stmt_num];
+ stmt_vec_info stmt_info = stmts[stmt_num];
tree oprnd;
unsigned int i, number_of_oprnds;
- gimple *def_stmt;
enum vect_def_type dt = vect_uninitialized_def;
bool pattern = false;
slp_oprnd_info oprnd_info;
int first_op_idx = 1;
- bool commutative = false;
+ unsigned int commutative_op = -1U;
bool first_op_cond = false;
bool first = stmt_num == 0;
bool second = stmt_num == 1;
- if (is_gimple_call (stmt))
+ if (gcall *stmt = dyn_cast <gcall *> (stmt_info->stmt))
{
number_of_oprnds = gimple_call_num_args (stmt);
first_op_idx = 3;
+ if (gimple_call_internal_p (stmt))
+ {
+ internal_fn ifn = gimple_call_internal_fn (stmt);
+ commutative_op = first_commutative_argument (ifn);
+ }
}
- else if (is_gimple_assign (stmt))
+ else if (gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt))
{
enum tree_code code = gimple_assign_rhs_code (stmt);
number_of_oprnds = gimple_num_ops (stmt) - 1;
@@ -322,7 +337,7 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char *swap,
number_of_oprnds++;
}
else
- commutative = commutative_tree_code (code);
+ commutative_op = commutative_tree_code (code) ? 0U : -1U;
}
else
return -1;
@@ -339,87 +354,27 @@ again:
int *map = maps[*swap];
if (i < 2)
- oprnd = TREE_OPERAND (gimple_op (stmt, first_op_idx), map[i]);
+ oprnd = TREE_OPERAND (gimple_op (stmt_info->stmt,
+ first_op_idx), map[i]);
else
- oprnd = gimple_op (stmt, map[i]);
+ oprnd = gimple_op (stmt_info->stmt, map[i]);
}
else
- oprnd = gimple_op (stmt, first_op_idx + (swapped ? !i : i));
+ oprnd = gimple_op (stmt_info->stmt, first_op_idx + (swapped ? !i : i));
oprnd_info = (*oprnds_info)[i];
- if (!vect_is_simple_use (oprnd, vinfo, &dt, &def_stmt))
+ stmt_vec_info def_stmt_info;
+ if (!vect_is_simple_use (oprnd, vinfo, &dt, &def_stmt_info))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Build SLP failed: can't analyze def for ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, oprnd);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Build SLP failed: can't analyze def for %T\n",
+ oprnd);
return -1;
}
- /* Check if DEF_STMT is a part of a pattern in LOOP and get the def stmt
- from the pattern. Check that all the stmts of the node are in the
- pattern. */
- if (def_stmt && gimple_bb (def_stmt)
- && vect_stmt_in_region_p (vinfo, def_stmt)
- && vinfo_for_stmt (def_stmt)
- && is_pattern_stmt_p (vinfo_for_stmt (def_stmt)))
- {
- pattern = true;
- if (!first && !oprnd_info->first_pattern
- /* Allow different pattern state for the defs of the
- first stmt in reduction chains. */
- && (oprnd_info->first_dt != vect_reduction_def
- || (!second && !oprnd_info->second_pattern)))
- {
- if (i == 0
- && !swapped
- && commutative)
- {
- swapped = true;
- goto again;
- }
-
- if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Build SLP failed: some of the stmts"
- " are in a pattern, and others are not ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, oprnd);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
-
- return 1;
- }
-
- dt = STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt));
-
- if (dt == vect_unknown_def_type)
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Unsupported pattern.\n");
- return -1;
- }
-
- switch (gimple_code (def_stmt))
- {
- case GIMPLE_PHI:
- case GIMPLE_ASSIGN:
- break;
-
- default:
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "unsupported defining stmt:\n");
- return -1;
- }
- }
-
if (second)
oprnd_info->second_pattern = pattern;
@@ -447,9 +402,7 @@ again:
|| !types_compatible_p (oprnd_info->first_op_type, type))
{
/* Try swapping operands if we got a mismatch. */
- if (i == 0
- && !swapped
- && commutative)
+ if (i == commutative_op && !swapped)
{
swapped = true;
goto again;
@@ -469,13 +422,9 @@ again:
TYPE_MODE (type))))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Build SLP failed: invalid type of def "
- "for variable-length SLP ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, oprnd);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Build SLP failed: invalid type of def "
+ "for variable-length SLP %T\n", oprnd);
return -1;
}
}
@@ -490,18 +439,15 @@ again:
case vect_reduction_def:
case vect_induction_def:
case vect_internal_def:
- oprnd_info->def_stmts.quick_push (def_stmt);
+ oprnd_info->def_stmts.quick_push (def_stmt_info);
break;
default:
/* FORNOW: Not supported. */
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Build SLP failed: illegal type of def ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, oprnd);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Build SLP failed: illegal type of def %T\n",
+ oprnd);
return -1;
}
@@ -512,20 +458,18 @@ again:
{
/* If there are already uses of this stmt in a SLP instance then
we've committed to the operand order and can't swap it. */
- if (STMT_VINFO_NUM_SLP_USES (vinfo_for_stmt (stmt)) != 0)
+ if (STMT_VINFO_NUM_SLP_USES (stmt_info) != 0)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Build SLP failed: cannot swap operands of "
- "shared stmt ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Build SLP failed: cannot swap operands of "
+ "shared stmt %G", stmt_info->stmt);
return -1;
}
if (first_op_cond)
{
+ gassign *stmt = as_a <gassign *> (stmt_info->stmt);
tree cond = gimple_assign_rhs1 (stmt);
enum tree_code code = TREE_CODE (cond);
@@ -548,14 +492,16 @@ again:
}
}
else
- swap_ssa_operands (stmt, gimple_assign_rhs1_ptr (stmt),
- gimple_assign_rhs2_ptr (stmt));
- if (dump_enabled_p ())
{
- dump_printf_loc (MSG_NOTE, vect_location,
- "swapped operands to match def types in ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
+ unsigned int op = commutative_op + first_op_idx;
+ swap_ssa_operands (stmt_info->stmt,
+ gimple_op_ptr (stmt_info->stmt, op),
+ gimple_op_ptr (stmt_info->stmt, op + 1));
}
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "swapped operands to match def types in %G",
+ stmt_info->stmt);
}
*swap = swapped;
@@ -598,25 +544,22 @@ compatible_calls_p (gcall *call1, gcall *call2)
}
/* A subroutine of vect_build_slp_tree for checking VECTYPE, which is the
- caller's attempt to find the vector type in STMT with the narrowest
+ caller's attempt to find the vector type in STMT_INFO with the narrowest
element type. Return true if VECTYPE is nonnull and if it is valid
- for VINFO. When returning true, update MAX_NUNITS to reflect the
- number of units in VECTYPE. VINFO, GORUP_SIZE and MAX_NUNITS are
- as for vect_build_slp_tree. */
+ for STMT_INFO. When returning true, update MAX_NUNITS to reflect the
+ number of units in VECTYPE. GROUP_SIZE and MAX_NUNITS are as for
+ vect_build_slp_tree. */
static bool
-vect_record_max_nunits (vec_info *vinfo, gimple *stmt, unsigned int group_size,
+vect_record_max_nunits (stmt_vec_info stmt_info, unsigned int group_size,
tree vectype, poly_uint64 *max_nunits)
{
if (!vectype)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Build SLP failed: unsupported data-type in ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Build SLP failed: unsupported data-type in %G\n",
+ stmt_info->stmt);
/* Fatal mismatch. */
return false;
}
@@ -625,7 +568,7 @@ vect_record_max_nunits (vec_info *vinfo, gimple *stmt, unsigned int group_size,
before adjusting *max_nunits for basic-block vectorization. */
poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
unsigned HOST_WIDE_INT const_nunits;
- if (is_a <bb_vec_info> (vinfo)
+ if (STMT_VINFO_BB_VINFO (stmt_info)
&& (!nunits.is_constant (&const_nunits)
|| const_nunits > group_size))
{
@@ -649,8 +592,9 @@ vect_record_max_nunits (vec_info *vinfo, gimple *stmt, unsigned int group_size,
would be permuted. */
static bool
-vect_two_operations_perm_ok_p (vec<gimple *> stmts, unsigned int group_size,
- tree vectype, tree_code alt_stmt_code)
+vect_two_operations_perm_ok_p (vec<stmt_vec_info> stmts,
+ unsigned int group_size, tree vectype,
+ tree_code alt_stmt_code)
{
unsigned HOST_WIDE_INT count;
if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant (&count))
@@ -660,7 +604,8 @@ vect_two_operations_perm_ok_p (vec<gimple *> stmts, unsigned int group_size,
for (unsigned int i = 0; i < count; ++i)
{
unsigned int elt = i;
- if (gimple_assign_rhs_code (stmts[i % group_size]) == alt_stmt_code)
+ gassign *stmt = as_a <gassign *> (stmts[i % group_size]->stmt);
+ if (gimple_assign_rhs_code (stmt) == alt_stmt_code)
elt += count;
sel.quick_push (elt);
}
@@ -683,13 +628,13 @@ vect_two_operations_perm_ok_p (vec<gimple *> stmts, unsigned int group_size,
to (B1 <= A1 ? X1 : Y1); or be inverted to (A1 < B1) ? Y1 : X1. */
static bool
-vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
- vec<gimple *> stmts, unsigned int group_size,
+vect_build_slp_tree_1 (unsigned char *swap,
+ vec<stmt_vec_info> stmts, unsigned int group_size,
poly_uint64 *max_nunits, bool *matches,
bool *two_operators)
{
unsigned int i;
- gimple *first_stmt = stmts[0], *stmt = stmts[0];
+ stmt_vec_info first_stmt_info = stmts[0];
enum tree_code first_stmt_code = ERROR_MARK;
enum tree_code alt_stmt_code = ERROR_MARK;
enum tree_code rhs_code = ERROR_MARK;
@@ -701,30 +646,26 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
int icode;
machine_mode optab_op2_mode;
machine_mode vec_mode;
- gimple *first_load = NULL, *prev_first_load = NULL;
+ stmt_vec_info first_load = NULL, prev_first_load = NULL;
/* For every stmt in NODE find its def stmt/s. */
- FOR_EACH_VEC_ELT (stmts, i, stmt)
+ stmt_vec_info stmt_info;
+ FOR_EACH_VEC_ELT (stmts, i, stmt_info)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ gimple *stmt = stmt_info->stmt;
swap[i] = 0;
matches[i] = false;
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "Build SLP for ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "Build SLP for %G", stmt);
/* Fail to vectorize statements marked as unvectorizable. */
- if (!STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (stmt)))
+ if (!STMT_VINFO_VECTORIZABLE (stmt_info))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Build SLP failed: unvectorizable statement ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Build SLP failed: unvectorizable statement %G",
+ stmt);
/* Fatal mismatch. */
matches[0] = false;
return false;
@@ -734,12 +675,9 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
if (lhs == NULL_TREE)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Build SLP failed: not GIMPLE_ASSIGN nor "
- "GIMPLE_CALL ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Build SLP failed: not GIMPLE_ASSIGN nor "
+ "GIMPLE_CALL %G", stmt);
/* Fatal mismatch. */
matches[0] = false;
return false;
@@ -749,7 +687,7 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
if (!vect_get_vector_types_for_stmt (stmt_info, &vectype,
&nunits_vectype)
|| (nunits_vectype
- && !vect_record_max_nunits (vinfo, stmt, group_size,
+ && !vect_record_max_nunits (stmt_info, group_size,
nunits_vectype, max_nunits)))
{
/* Fatal mismatch. */
@@ -771,12 +709,9 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
|| gimple_call_chain (call_stmt))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Build SLP failed: unsupported call type ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- call_stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Build SLP failed: unsupported call type %G",
+ call_stmt);
/* Fatal mismatch. */
matches[0] = false;
return false;
@@ -871,7 +806,7 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
&& (alt_stmt_code == PLUS_EXPR
|| alt_stmt_code == MINUS_EXPR)
&& rhs_code == alt_stmt_code)
- && !(STMT_VINFO_GROUPED_ACCESS (vinfo_for_stmt (stmt))
+ && !(STMT_VINFO_GROUPED_ACCESS (stmt_info)
&& (first_stmt_code == ARRAY_REF
|| first_stmt_code == BIT_FIELD_REF
|| first_stmt_code == INDIRECT_REF
@@ -882,12 +817,9 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
{
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"Build SLP failed: different operation "
- "in stmt ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
+ "in stmt %G", stmt);
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "original stmt ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- first_stmt, 0);
+ "original stmt %G", first_stmt_info->stmt);
}
/* Mismatch. */
continue;
@@ -897,29 +829,22 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
&& !operand_equal_p (first_op1, gimple_assign_rhs2 (stmt), 0))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Build SLP failed: different shift "
- "arguments in ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Build SLP failed: different shift "
+ "arguments in %G", stmt);
/* Mismatch. */
continue;
}
if (rhs_code == CALL_EXPR)
{
- gimple *first_stmt = stmts[0];
- if (!compatible_calls_p (as_a <gcall *> (first_stmt),
+ if (!compatible_calls_p (as_a <gcall *> (stmts[0]->stmt),
as_a <gcall *> (stmt)))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Build SLP failed: different calls in ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Build SLP failed: different calls in %G",
+ stmt);
/* Mismatch. */
continue;
}
@@ -927,7 +852,7 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
}
/* Grouped store or load. */
- if (STMT_VINFO_GROUPED_ACCESS (vinfo_for_stmt (stmt)))
+ if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
{
if (REFERENCE_CLASS_P (lhs))
{
@@ -937,7 +862,7 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
else
{
/* Load. */
- first_load = DR_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt));
+ first_load = DR_GROUP_FIRST_ELEMENT (stmt_info);
if (prev_first_load)
{
/* Check that there are no loads from different interleaving
@@ -945,14 +870,11 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
if (prev_first_load != first_load)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION,
- vect_location,
- "Build SLP failed: different "
- "interleaving chains in one node ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION,
+ vect_location,
+ "Build SLP failed: different "
+ "interleaving chains in one node %G",
+ stmt);
/* Mismatch. */
continue;
}
@@ -967,11 +889,8 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
{
/* Not grouped load. */
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Build SLP failed: not grouped load ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Build SLP failed: not grouped load %G", stmt);
/* FORNOW: Not grouped loads are not supported. */
/* Fatal mismatch. */
@@ -987,12 +906,9 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
&& rhs_code != CALL_EXPR)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Build SLP failed: operation");
- dump_printf (MSG_MISSED_OPTIMIZATION, " unsupported ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Build SLP failed: operation unsupported %G",
+ stmt);
/* Fatal mismatch. */
matches[0] = false;
return false;
@@ -1025,13 +941,9 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
else
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Build SLP failed: different"
- " operation");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Build SLP failed: different"
+ " operation %G", stmt);
/* Mismatch. */
continue;
}
@@ -1055,20 +967,16 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
vectype, alt_stmt_code))
{
for (i = 0; i < group_size; ++i)
- if (gimple_assign_rhs_code (stmts[i]) == alt_stmt_code)
+ if (gimple_assign_rhs_code (stmts[i]->stmt) == alt_stmt_code)
{
matches[i] = false;
if (dump_enabled_p ())
{
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"Build SLP failed: different operation "
- "in stmt ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- stmts[i], 0);
+ "in stmt %G", stmts[i]->stmt);
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "original stmt ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- first_stmt, 0);
+ "original stmt %G", first_stmt_info->stmt);
}
}
return false;
@@ -1084,8 +992,8 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
need a special value for deleted that differs from empty. */
struct bst_traits
{
- typedef vec <gimple *> value_type;
- typedef vec <gimple *> compare_type;
+ typedef vec <stmt_vec_info> value_type;
+ typedef vec <stmt_vec_info> compare_type;
static inline hashval_t hash (value_type);
static inline bool equal (value_type existing, value_type candidate);
static inline bool is_empty (value_type x) { return !x.exists (); }
@@ -1099,7 +1007,7 @@ bst_traits::hash (value_type x)
{
inchash::hash h;
for (unsigned i = 0; i < x.length (); ++i)
- h.add_int (gimple_uid (x[i]));
+ h.add_int (gimple_uid (x[i]->stmt));
return h.end ();
}
inline bool
@@ -1122,7 +1030,7 @@ typedef hash_map <vec <gimple *>, slp_tree,
static slp_tree
vect_build_slp_tree_2 (vec_info *vinfo,
- vec<gimple *> stmts, unsigned int group_size,
+ vec<stmt_vec_info> stmts, unsigned int group_size,
poly_uint64 *max_nunits,
vec<slp_tree> *loads,
bool *matches, unsigned *npermutes, unsigned *tree_size,
@@ -1130,7 +1038,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
static slp_tree
vect_build_slp_tree (vec_info *vinfo,
- vec<gimple *> stmts, unsigned int group_size,
+ vec<stmt_vec_info> stmts, unsigned int group_size,
poly_uint64 *max_nunits, vec<slp_tree> *loads,
bool *matches, unsigned *npermutes, unsigned *tree_size,
unsigned max_tree_size)
@@ -1145,7 +1053,7 @@ vect_build_slp_tree (vec_info *vinfo,
scalars, see PR81723. */
if (! res)
{
- vec <gimple *> x;
+ vec <stmt_vec_info> x;
x.create (stmts.length ());
x.splice (stmts);
bst_fail->add (x);
@@ -1162,7 +1070,7 @@ vect_build_slp_tree (vec_info *vinfo,
static slp_tree
vect_build_slp_tree_2 (vec_info *vinfo,
- vec<gimple *> stmts, unsigned int group_size,
+ vec<stmt_vec_info> stmts, unsigned int group_size,
poly_uint64 *max_nunits,
vec<slp_tree> *loads,
bool *matches, unsigned *npermutes, unsigned *tree_size,
@@ -1170,53 +1078,53 @@ vect_build_slp_tree_2 (vec_info *vinfo,
{
unsigned nops, i, this_tree_size = 0;
poly_uint64 this_max_nunits = *max_nunits;
- gimple *stmt;
slp_tree node;
matches[0] = false;
- stmt = stmts[0];
- if (is_gimple_call (stmt))
+ stmt_vec_info stmt_info = stmts[0];
+ if (gcall *stmt = dyn_cast <gcall *> (stmt_info->stmt))
nops = gimple_call_num_args (stmt);
- else if (is_gimple_assign (stmt))
+ else if (gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt))
{
nops = gimple_num_ops (stmt) - 1;
if (gimple_assign_rhs_code (stmt) == COND_EXPR)
nops++;
}
- else if (gimple_code (stmt) == GIMPLE_PHI)
+ else if (is_a <gphi *> (stmt_info->stmt))
nops = 0;
else
return NULL;
/* If the SLP node is a PHI (induction or reduction), terminate
the recursion. */
- if (gimple_code (stmt) == GIMPLE_PHI)
+ if (gphi *stmt = dyn_cast <gphi *> (stmt_info->stmt))
{
tree scalar_type = TREE_TYPE (PHI_RESULT (stmt));
tree vectype = get_vectype_for_scalar_type (scalar_type);
- if (!vect_record_max_nunits (vinfo, stmt, group_size, vectype,
- max_nunits))
+ if (!vect_record_max_nunits (stmt_info, group_size, vectype, max_nunits))
return NULL;
- vect_def_type def_type = STMT_VINFO_DEF_TYPE (vinfo_for_stmt (stmt));
+ vect_def_type def_type = STMT_VINFO_DEF_TYPE (stmt_info);
/* Induction from different IVs is not supported. */
if (def_type == vect_induction_def)
{
- FOR_EACH_VEC_ELT (stmts, i, stmt)
- if (stmt != stmts[0])
+ stmt_vec_info other_info;
+ FOR_EACH_VEC_ELT (stmts, i, other_info)
+ if (stmt_info != other_info)
return NULL;
}
else
{
/* Else def types have to match. */
- FOR_EACH_VEC_ELT (stmts, i, stmt)
+ stmt_vec_info other_info;
+ FOR_EACH_VEC_ELT (stmts, i, other_info)
{
/* But for reduction chains only check on the first stmt. */
- if (REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt))
- && REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) != stmt)
+ if (REDUC_GROUP_FIRST_ELEMENT (other_info)
+ && REDUC_GROUP_FIRST_ELEMENT (other_info) != stmt_info)
continue;
- if (STMT_VINFO_DEF_TYPE (vinfo_for_stmt (stmt)) != def_type)
+ if (STMT_VINFO_DEF_TYPE (other_info) != def_type)
return NULL;
}
}
@@ -1227,13 +1135,13 @@ vect_build_slp_tree_2 (vec_info *vinfo,
bool two_operators = false;
unsigned char *swap = XALLOCAVEC (unsigned char, group_size);
- if (!vect_build_slp_tree_1 (vinfo, swap, stmts, group_size,
+ if (!vect_build_slp_tree_1 (swap, stmts, group_size,
&this_max_nunits, matches, &two_operators))
return NULL;
/* If the SLP node is a load, terminate the recursion. */
- if (STMT_VINFO_GROUPED_ACCESS (vinfo_for_stmt (stmt))
- && DR_IS_READ (STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt))))
+ if (STMT_VINFO_GROUPED_ACCESS (stmt_info)
+ && DR_IS_READ (STMT_VINFO_DATA_REF (stmt_info)))
{
*max_nunits = this_max_nunits;
node = vect_create_new_slp_node (stmts);
@@ -1244,7 +1152,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
/* Get at the operands, verifying they are compatible. */
vec<slp_oprnd_info> oprnds_info = vect_create_oprnd_info (nops, group_size);
slp_oprnd_info oprnd_info;
- FOR_EACH_VEC_ELT (stmts, i, stmt)
+ FOR_EACH_VEC_ELT (stmts, i, stmt_info)
{
int res = vect_get_and_check_slp_defs (vinfo, &swap[i],
stmts, i, &oprnds_info);
@@ -1263,7 +1171,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
auto_vec<slp_tree, 4> children;
auto_vec<slp_tree> this_loads;
- stmt = stmts[0];
+ stmt_info = stmts[0];
if (tree_size)
max_tree_size -= *tree_size;
@@ -1284,7 +1192,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
if (++this_tree_size > max_tree_size)
{
FOR_EACH_VEC_ELT (children, j, child)
- vect_free_slp_tree (child);
+ vect_free_slp_tree (child, false);
vect_free_oprnd_info (oprnds_info);
return NULL;
}
@@ -1301,8 +1209,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
/* ??? Rejecting patterns this way doesn't work. We'd have to
do extra work to cancel the pattern so the uses see the
scalar version. */
- && !is_pattern_stmt_p
- (vinfo_for_stmt (SLP_TREE_SCALAR_STMTS (child)[0])))
+ && !is_pattern_stmt_p (SLP_TREE_SCALAR_STMTS (child)[0]))
{
slp_tree grandchild;
@@ -1315,7 +1222,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
this_loads.truncate (old_nloads);
this_tree_size = old_tree_size;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (child), j, grandchild)
- vect_free_slp_tree (grandchild);
+ vect_free_slp_tree (grandchild, false);
SLP_TREE_CHILDREN (child).truncate (0);
dump_printf_loc (MSG_NOTE, vect_location,
@@ -1346,7 +1253,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
/* ??? Rejecting patterns this way doesn't work. We'd have to
do extra work to cancel the pattern so the uses see the
scalar version. */
- && !is_pattern_stmt_p (vinfo_for_stmt (stmt)))
+ && !is_pattern_stmt_p (stmt_info))
{
dump_printf_loc (MSG_NOTE, vect_location,
"Building vector operands from scalars\n");
@@ -1367,7 +1274,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
as well as the arms under some constraints. */
&& nops == 2
&& oprnds_info[1]->first_dt == vect_internal_def
- && is_gimple_assign (stmt)
+ && is_gimple_assign (stmt_info->stmt)
/* Do so only if the number of not successful permutes was nor more
than a cut-ff as re-trying the recursive match on
possibly each level of the tree would expose exponential
@@ -1383,9 +1290,10 @@ vect_build_slp_tree_2 (vec_info *vinfo,
{
if (matches[j] != !swap_not_matching)
continue;
- gimple *stmt = stmts[j];
+ stmt_vec_info stmt_info = stmts[j];
/* Verify if we can swap operands of this stmt. */
- if (!is_gimple_assign (stmt)
+ gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt);
+ if (!stmt
|| !commutative_tree_code (gimple_assign_rhs_code (stmt)))
{
if (!swap_not_matching)
@@ -1400,19 +1308,16 @@ vect_build_slp_tree_2 (vec_info *vinfo,
node and temporarily do that when processing it
(or wrap operand accessors in a helper). */
else if (swap[j] != 0
- || STMT_VINFO_NUM_SLP_USES (vinfo_for_stmt (stmt)))
+ || STMT_VINFO_NUM_SLP_USES (stmt_info))
{
if (!swap_not_matching)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION,
- vect_location,
- "Build SLP failed: cannot swap "
- "operands of shared stmt ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION,
- TDF_SLIM, stmts[j], 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION,
+ vect_location,
+ "Build SLP failed: cannot swap "
+ "operands of shared stmt %G",
+ stmts[j]->stmt);
goto fail;
}
swap_not_matching = false;
@@ -1448,31 +1353,23 @@ vect_build_slp_tree_2 (vec_info *vinfo,
if we end up building the operand from scalars as
we'll continue to process swapped operand two. */
for (j = 0; j < group_size; ++j)
- {
- gimple *stmt = stmts[j];
- gimple_set_plf (stmt, GF_PLF_1, false);
- }
+ gimple_set_plf (stmts[j]->stmt, GF_PLF_1, false);
for (j = 0; j < group_size; ++j)
- {
- gimple *stmt = stmts[j];
- if (matches[j] == !swap_not_matching)
- {
- /* Avoid swapping operands twice. */
- if (gimple_plf (stmt, GF_PLF_1))
- continue;
- swap_ssa_operands (stmt, gimple_assign_rhs1_ptr (stmt),
- gimple_assign_rhs2_ptr (stmt));
- gimple_set_plf (stmt, GF_PLF_1, true);
- }
- }
+ if (matches[j] == !swap_not_matching)
+ {
+ gassign *stmt = as_a <gassign *> (stmts[j]->stmt);
+ /* Avoid swapping operands twice. */
+ if (gimple_plf (stmt, GF_PLF_1))
+ continue;
+ swap_ssa_operands (stmt, gimple_assign_rhs1_ptr (stmt),
+ gimple_assign_rhs2_ptr (stmt));
+ gimple_set_plf (stmt, GF_PLF_1, true);
+ }
/* Verify we swap all duplicates or none. */
if (flag_checking)
for (j = 0; j < group_size; ++j)
- {
- gimple *stmt = stmts[j];
- gcc_assert (gimple_plf (stmt, GF_PLF_1)
- == (matches[j] == !swap_not_matching));
- }
+ gcc_assert (gimple_plf (stmts[j]->stmt, GF_PLF_1)
+ == (matches[j] == !swap_not_matching));
/* If we have all children of child built up from scalars then
just throw that away and build it up this node from scalars. */
@@ -1480,8 +1377,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
/* ??? Rejecting patterns this way doesn't work. We'd have
to do extra work to cancel the pattern so the uses see the
scalar version. */
- && !is_pattern_stmt_p
- (vinfo_for_stmt (SLP_TREE_SCALAR_STMTS (child)[0])))
+ && !is_pattern_stmt_p (SLP_TREE_SCALAR_STMTS (child)[0]))
{
unsigned int j;
slp_tree grandchild;
@@ -1495,7 +1391,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
this_loads.truncate (old_nloads);
this_tree_size = old_tree_size;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (child), j, grandchild)
- vect_free_slp_tree (grandchild);
+ vect_free_slp_tree (grandchild, false);
SLP_TREE_CHILDREN (child).truncate (0);
dump_printf_loc (MSG_NOTE, vect_location,
@@ -1519,7 +1415,7 @@ vect_build_slp_tree_2 (vec_info *vinfo,
fail:
gcc_assert (child == NULL);
FOR_EACH_VEC_ELT (children, j, child)
- vect_free_slp_tree (child);
+ vect_free_slp_tree (child, false);
vect_free_oprnd_info (oprnds_info);
return NULL;
}
@@ -1544,17 +1440,14 @@ vect_print_slp_tree (dump_flags_t dump_kind, dump_location_t loc,
slp_tree node)
{
int i;
- gimple *stmt;
+ stmt_vec_info stmt_info;
slp_tree child;
dump_printf_loc (dump_kind, loc, "node%s\n",
SLP_TREE_DEF_TYPE (node) != vect_internal_def
? " (external)" : "");
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt)
- {
- dump_printf_loc (dump_kind, loc, "\tstmt %d ", i);
- dump_gimple_stmt (dump_kind, TDF_SLIM, stmt, 0);
- }
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
+ dump_printf_loc (dump_kind, loc, "\tstmt %d %G", i, stmt_info->stmt);
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
vect_print_slp_tree (dump_kind, loc, child);
}
@@ -1569,15 +1462,15 @@ static void
vect_mark_slp_stmts (slp_tree node, enum slp_vect_type mark, int j)
{
int i;
- gimple *stmt;
+ stmt_vec_info stmt_info;
slp_tree child;
if (SLP_TREE_DEF_TYPE (node) != vect_internal_def)
return;
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt)
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
if (j < 0 || i == j)
- STMT_SLP_TYPE (vinfo_for_stmt (stmt)) = mark;
+ STMT_SLP_TYPE (stmt_info) = mark;
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
vect_mark_slp_stmts (child, mark, j);
@@ -1590,16 +1483,14 @@ static void
vect_mark_slp_stmts_relevant (slp_tree node)
{
int i;
- gimple *stmt;
stmt_vec_info stmt_info;
slp_tree child;
if (SLP_TREE_DEF_TYPE (node) != vect_internal_def)
return;
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt)
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
{
- stmt_info = vinfo_for_stmt (stmt);
gcc_assert (!STMT_VINFO_RELEVANT (stmt_info)
|| STMT_VINFO_RELEVANT (stmt_info) == vect_used_in_scope);
STMT_VINFO_RELEVANT (stmt_info) = vect_used_in_scope;
@@ -1616,8 +1507,8 @@ static void
vect_slp_rearrange_stmts (slp_tree node, unsigned int group_size,
vec<unsigned> permutation)
{
- gimple *stmt;
- vec<gimple *> tmp_stmts;
+ stmt_vec_info stmt_info;
+ vec<stmt_vec_info> tmp_stmts;
unsigned int i;
slp_tree child;
@@ -1628,8 +1519,8 @@ vect_slp_rearrange_stmts (slp_tree node, unsigned int group_size,
tmp_stmts.create (group_size);
tmp_stmts.quick_grow_cleared (group_size);
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt)
- tmp_stmts[permutation[i]] = stmt;
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
+ tmp_stmts[permutation[i]] = stmt_info;
SLP_TREE_SCALAR_STMTS (node).release ();
SLP_TREE_SCALAR_STMTS (node) = tmp_stmts;
@@ -1690,13 +1581,13 @@ vect_attempt_slp_rearrange_stmts (slp_instance slp_instn)
poly_uint64 unrolling_factor = SLP_INSTANCE_UNROLLING_FACTOR (slp_instn);
FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (slp_instn), i, node)
{
- gimple *first_stmt = SLP_TREE_SCALAR_STMTS (node)[0];
- first_stmt = DR_GROUP_FIRST_ELEMENT (vinfo_for_stmt (first_stmt));
+ stmt_vec_info first_stmt_info = SLP_TREE_SCALAR_STMTS (node)[0];
+ first_stmt_info = DR_GROUP_FIRST_ELEMENT (first_stmt_info);
/* But we have to keep those permutations that are required because
of handling of gaps. */
if (known_eq (unrolling_factor, 1U)
- || (group_size == DR_GROUP_SIZE (vinfo_for_stmt (first_stmt))
- && DR_GROUP_GAP (vinfo_for_stmt (first_stmt)) == 0))
+ || (group_size == DR_GROUP_SIZE (first_stmt_info)
+ && DR_GROUP_GAP (first_stmt_info) == 0))
SLP_TREE_LOAD_PERMUTATION (node).release ();
else
for (j = 0; j < SLP_TREE_LOAD_PERMUTATION (node).length (); ++j)
@@ -1715,7 +1606,6 @@ vect_supported_load_permutation_p (slp_instance slp_instn)
unsigned int group_size = SLP_INSTANCE_GROUP_SIZE (slp_instn);
unsigned int i, j, k, next;
slp_tree node;
- gimple *stmt, *load, *next_load;
if (dump_enabled_p ())
{
@@ -1744,18 +1634,18 @@ vect_supported_load_permutation_p (slp_instance slp_instn)
return false;
node = SLP_INSTANCE_TREE (slp_instn);
- stmt = SLP_TREE_SCALAR_STMTS (node)[0];
+ stmt_vec_info stmt_info = SLP_TREE_SCALAR_STMTS (node)[0];
/* Reduction (there are no data-refs in the root).
In reduction chain the order of the loads is not important. */
- if (!STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt))
- && !REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)))
+ if (!STMT_VINFO_DATA_REF (stmt_info)
+ && !REDUC_GROUP_FIRST_ELEMENT (stmt_info))
vect_attempt_slp_rearrange_stmts (slp_instn);
/* In basic block vectorization we allow any subchain of an interleaving
chain.
FORNOW: not supported in loop SLP because of realignment compications. */
- if (STMT_VINFO_BB_VINFO (vinfo_for_stmt (stmt)))
+ if (STMT_VINFO_BB_VINFO (stmt_info))
{
/* Check whether the loads in an instance form a subchain and thus
no permutation is necessary. */
@@ -1764,25 +1654,25 @@ vect_supported_load_permutation_p (slp_instance slp_instn)
if (!SLP_TREE_LOAD_PERMUTATION (node).exists ())
continue;
bool subchain_p = true;
- next_load = NULL;
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), j, load)
- {
- if (j != 0
- && (next_load != load
- || DR_GROUP_GAP (vinfo_for_stmt (load)) != 1))
+ stmt_vec_info next_load_info = NULL;
+ stmt_vec_info load_info;
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), j, load_info)
+ {
+ if (j != 0
+ && (next_load_info != load_info
+ || DR_GROUP_GAP (load_info) != 1))
{
subchain_p = false;
break;
}
- next_load = DR_GROUP_NEXT_ELEMENT (vinfo_for_stmt (load));
- }
+ next_load_info = DR_GROUP_NEXT_ELEMENT (load_info);
+ }
if (subchain_p)
SLP_TREE_LOAD_PERMUTATION (node).release ();
else
{
- stmt_vec_info group_info
- = vinfo_for_stmt (SLP_TREE_SCALAR_STMTS (node)[0]);
- group_info = vinfo_for_stmt (DR_GROUP_FIRST_ELEMENT (group_info));
+ stmt_vec_info group_info = SLP_TREE_SCALAR_STMTS (node)[0];
+ group_info = DR_GROUP_FIRST_ELEMENT (group_info);
unsigned HOST_WIDE_INT nunits;
unsigned k, maxk = 0;
FOR_EACH_VEC_ELT (SLP_TREE_LOAD_PERMUTATION (node), j, k)
@@ -1825,7 +1715,7 @@ vect_supported_load_permutation_p (slp_instance slp_instn)
poly_uint64 test_vf
= force_common_multiple (SLP_INSTANCE_UNROLLING_FACTOR (slp_instn),
LOOP_VINFO_VECT_FACTOR
- (STMT_VINFO_LOOP_VINFO (vinfo_for_stmt (stmt))));
+ (STMT_VINFO_LOOP_VINFO (stmt_info)));
FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (slp_instn), i, node)
if (node->load_permutation.exists ()
&& !vect_transform_slp_perm_load (node, vNULL, NULL, test_vf,
@@ -1838,60 +1728,57 @@ vect_supported_load_permutation_p (slp_instance slp_instn)
/* Find the last store in SLP INSTANCE. */
-gimple *
+stmt_vec_info
vect_find_last_scalar_stmt_in_slp (slp_tree node)
{
- gimple *last = NULL, *stmt;
+ stmt_vec_info last = NULL;
+ stmt_vec_info stmt_vinfo;
- for (int i = 0; SLP_TREE_SCALAR_STMTS (node).iterate (i, &stmt); i++)
+ for (int i = 0; SLP_TREE_SCALAR_STMTS (node).iterate (i, &stmt_vinfo); i++)
{
- stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
- if (is_pattern_stmt_p (stmt_vinfo))
- last = get_later_stmt (STMT_VINFO_RELATED_STMT (stmt_vinfo), last);
- else
- last = get_later_stmt (stmt, last);
+ stmt_vinfo = vect_orig_stmt (stmt_vinfo);
+ last = last ? get_later_stmt (stmt_vinfo, last) : stmt_vinfo;
}
return last;
}
-/* Splits a group of stores, currently beginning at FIRST_STMT, into two groups:
- one (still beginning at FIRST_STMT) of size GROUP1_SIZE (also containing
- the first GROUP1_SIZE stmts, since stores are consecutive), the second
- containing the remainder.
+/* Splits a group of stores, currently beginning at FIRST_VINFO, into
+ two groups: one (still beginning at FIRST_VINFO) of size GROUP1_SIZE
+ (also containing the first GROUP1_SIZE stmts, since stores are
+ consecutive), the second containing the remainder.
Return the first stmt in the second group. */
-static gimple *
-vect_split_slp_store_group (gimple *first_stmt, unsigned group1_size)
+static stmt_vec_info
+vect_split_slp_store_group (stmt_vec_info first_vinfo, unsigned group1_size)
{
- stmt_vec_info first_vinfo = vinfo_for_stmt (first_stmt);
- gcc_assert (DR_GROUP_FIRST_ELEMENT (first_vinfo) == first_stmt);
+ gcc_assert (DR_GROUP_FIRST_ELEMENT (first_vinfo) == first_vinfo);
gcc_assert (group1_size > 0);
int group2_size = DR_GROUP_SIZE (first_vinfo) - group1_size;
gcc_assert (group2_size > 0);
DR_GROUP_SIZE (first_vinfo) = group1_size;
- gimple *stmt = first_stmt;
+ stmt_vec_info stmt_info = first_vinfo;
for (unsigned i = group1_size; i > 1; i--)
{
- stmt = DR_GROUP_NEXT_ELEMENT (vinfo_for_stmt (stmt));
- gcc_assert (DR_GROUP_GAP (vinfo_for_stmt (stmt)) == 1);
+ stmt_info = DR_GROUP_NEXT_ELEMENT (stmt_info);
+ gcc_assert (DR_GROUP_GAP (stmt_info) == 1);
}
/* STMT is now the last element of the first group. */
- gimple *group2 = DR_GROUP_NEXT_ELEMENT (vinfo_for_stmt (stmt));
- DR_GROUP_NEXT_ELEMENT (vinfo_for_stmt (stmt)) = 0;
+ stmt_vec_info group2 = DR_GROUP_NEXT_ELEMENT (stmt_info);
+ DR_GROUP_NEXT_ELEMENT (stmt_info) = 0;
- DR_GROUP_SIZE (vinfo_for_stmt (group2)) = group2_size;
- for (stmt = group2; stmt; stmt = DR_GROUP_NEXT_ELEMENT (vinfo_for_stmt (stmt)))
+ DR_GROUP_SIZE (group2) = group2_size;
+ for (stmt_info = group2; stmt_info;
+ stmt_info = DR_GROUP_NEXT_ELEMENT (stmt_info))
{
- DR_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) = group2;
- gcc_assert (DR_GROUP_GAP (vinfo_for_stmt (stmt)) == 1);
+ DR_GROUP_FIRST_ELEMENT (stmt_info) = group2;
+ gcc_assert (DR_GROUP_GAP (stmt_info) == 1);
}
/* For the second group, the DR_GROUP_GAP is that before the original group,
plus skipping over the first vector. */
- DR_GROUP_GAP (vinfo_for_stmt (group2))
- = DR_GROUP_GAP (first_vinfo) + group1_size;
+ DR_GROUP_GAP (group2) = DR_GROUP_GAP (first_vinfo) + group1_size;
/* DR_GROUP_GAP of the first group now has to skip over the second group too. */
DR_GROUP_GAP (first_vinfo) += group2_size;
@@ -1918,46 +1805,42 @@ calculate_unrolling_factor (poly_uint64 nunits, unsigned int group_size)
static bool
vect_analyze_slp_instance (vec_info *vinfo,
- gimple *stmt, unsigned max_tree_size)
+ stmt_vec_info stmt_info, unsigned max_tree_size)
{
slp_instance new_instance;
slp_tree node;
unsigned int group_size;
tree vectype, scalar_type = NULL_TREE;
- gimple *next;
unsigned int i;
vec<slp_tree> loads;
- struct data_reference *dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt));
- vec<gimple *> scalar_stmts;
+ struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
+ vec<stmt_vec_info> scalar_stmts;
- if (STMT_VINFO_GROUPED_ACCESS (vinfo_for_stmt (stmt)))
+ if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
{
scalar_type = TREE_TYPE (DR_REF (dr));
vectype = get_vectype_for_scalar_type (scalar_type);
- group_size = DR_GROUP_SIZE (vinfo_for_stmt (stmt));
+ group_size = DR_GROUP_SIZE (stmt_info);
}
- else if (!dr && REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)))
+ else if (!dr && REDUC_GROUP_FIRST_ELEMENT (stmt_info))
{
gcc_assert (is_a <loop_vec_info> (vinfo));
- vectype = STMT_VINFO_VECTYPE (vinfo_for_stmt (stmt));
- group_size = REDUC_GROUP_SIZE (vinfo_for_stmt (stmt));
+ vectype = STMT_VINFO_VECTYPE (stmt_info);
+ group_size = REDUC_GROUP_SIZE (stmt_info);
}
else
{
gcc_assert (is_a <loop_vec_info> (vinfo));
- vectype = STMT_VINFO_VECTYPE (vinfo_for_stmt (stmt));
+ vectype = STMT_VINFO_VECTYPE (stmt_info);
group_size = as_a <loop_vec_info> (vinfo)->reductions.length ();
}
if (!vectype)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Build SLP failed: unsupported data-type ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, scalar_type);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Build SLP failed: unsupported data-type %T\n",
+ scalar_type);
return false;
}
@@ -1965,46 +1848,36 @@ vect_analyze_slp_instance (vec_info *vinfo,
/* Create a node (a root of the SLP tree) for the packed grouped stores. */
scalar_stmts.create (group_size);
- next = stmt;
- if (STMT_VINFO_GROUPED_ACCESS (vinfo_for_stmt (stmt)))
+ stmt_vec_info next_info = stmt_info;
+ if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
{
/* Collect the stores and store them in SLP_TREE_SCALAR_STMTS. */
- while (next)
+ while (next_info)
{
- if (STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (next))
- && STMT_VINFO_RELATED_STMT (vinfo_for_stmt (next)))
- scalar_stmts.safe_push (
- STMT_VINFO_RELATED_STMT (vinfo_for_stmt (next)));
- else
- scalar_stmts.safe_push (next);
- next = DR_GROUP_NEXT_ELEMENT (vinfo_for_stmt (next));
+ scalar_stmts.safe_push (vect_stmt_to_vectorize (next_info));
+ next_info = DR_GROUP_NEXT_ELEMENT (next_info);
}
}
- else if (!dr && REDUC_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)))
+ else if (!dr && REDUC_GROUP_FIRST_ELEMENT (stmt_info))
{
/* Collect the reduction stmts and store them in
SLP_TREE_SCALAR_STMTS. */
- while (next)
+ while (next_info)
{
- if (STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (next))
- && STMT_VINFO_RELATED_STMT (vinfo_for_stmt (next)))
- scalar_stmts.safe_push (
- STMT_VINFO_RELATED_STMT (vinfo_for_stmt (next)));
- else
- scalar_stmts.safe_push (next);
- next = REDUC_GROUP_NEXT_ELEMENT (vinfo_for_stmt (next));
+ scalar_stmts.safe_push (vect_stmt_to_vectorize (next_info));
+ next_info = REDUC_GROUP_NEXT_ELEMENT (next_info);
}
/* Mark the first element of the reduction chain as reduction to properly
transform the node. In the reduction analysis phase only the last
element of the chain is marked as reduction. */
- STMT_VINFO_DEF_TYPE (vinfo_for_stmt (stmt)) = vect_reduction_def;
+ STMT_VINFO_DEF_TYPE (stmt_info) = vect_reduction_def;
}
else
{
/* Collect reduction statements. */
- vec<gimple *> reductions = as_a <loop_vec_info> (vinfo)->reductions;
- for (i = 0; reductions.iterate (i, &next); i++)
- scalar_stmts.safe_push (next);
+ vec<stmt_vec_info> reductions = as_a <loop_vec_info> (vinfo)->reductions;
+ for (i = 0; reductions.iterate (i, &next_info); i++)
+ scalar_stmts.safe_push (next_info);
}
loads.create (group_size);
@@ -2036,13 +1909,13 @@ vect_analyze_slp_instance (vec_info *vinfo,
"Build SLP failed: store group "
"size not a multiple of the vector size "
"in basic block SLP\n");
- vect_free_slp_tree (node);
+ vect_free_slp_tree (node, false);
loads.release ();
return false;
}
/* Fatal mismatch. */
matches[group_size / const_max_nunits * const_max_nunits] = false;
- vect_free_slp_tree (node);
+ vect_free_slp_tree (node, false);
loads.release ();
}
else
@@ -2061,15 +1934,15 @@ vect_analyze_slp_instance (vec_info *vinfo,
{
vec<unsigned> load_permutation;
int j;
- gimple *load, *first_stmt;
+ stmt_vec_info load_info;
bool this_load_permuted = false;
load_permutation.create (group_size);
- first_stmt = DR_GROUP_FIRST_ELEMENT
- (vinfo_for_stmt (SLP_TREE_SCALAR_STMTS (load_node)[0]));
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (load_node), j, load)
+ stmt_vec_info first_stmt_info = DR_GROUP_FIRST_ELEMENT
+ (SLP_TREE_SCALAR_STMTS (load_node)[0]);
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (load_node), j, load_info)
{
- int load_place = vect_get_place_in_interleaving_chain
- (load, first_stmt);
+ int load_place = vect_get_place_in_interleaving_chain
+ (load_info, first_stmt_info);
gcc_assert (load_place != -1);
if (load_place != j)
this_load_permuted = true;
@@ -2080,8 +1953,8 @@ vect_analyze_slp_instance (vec_info *vinfo,
a gap either because the group is larger than the SLP
group-size or because there is a gap between the groups. */
&& (known_eq (unrolling_factor, 1U)
- || (group_size == DR_GROUP_SIZE (vinfo_for_stmt (first_stmt))
- && DR_GROUP_GAP (vinfo_for_stmt (first_stmt)) == 0)))
+ || (group_size == DR_GROUP_SIZE (first_stmt_info)
+ && DR_GROUP_GAP (first_stmt_info) == 0)))
{
load_permutation.release ();
continue;
@@ -2095,14 +1968,10 @@ vect_analyze_slp_instance (vec_info *vinfo,
if (!vect_supported_load_permutation_p (new_instance))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Build SLP failed: unsupported load "
- "permutation ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION,
- TDF_SLIM, stmt, 0);
- }
- vect_free_slp_instance (new_instance);
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "Build SLP failed: unsupported load "
+ "permutation %G", stmt_info->stmt);
+ vect_free_slp_instance (new_instance, false);
return false;
}
}
@@ -2116,11 +1985,9 @@ vect_analyze_slp_instance (vec_info *vinfo,
slp_tree load_node;
FOR_EACH_VEC_ELT (loads, i, load_node)
{
- gimple *first_stmt = DR_GROUP_FIRST_ELEMENT
- (vinfo_for_stmt (SLP_TREE_SCALAR_STMTS (load_node)[0]));
- stmt_vec_info stmt_vinfo = vinfo_for_stmt (first_stmt);
- /* Use SLP for strided accesses (or if we
- can't load-lanes). */
+ stmt_vec_info stmt_vinfo = DR_GROUP_FIRST_ELEMENT
+ (SLP_TREE_SCALAR_STMTS (load_node)[0]);
+ /* Use SLP for strided accesses (or if we can't load-lanes). */
if (STMT_VINFO_STRIDED_P (stmt_vinfo)
|| ! vect_load_lanes_supported
(STMT_VINFO_VECTYPE (stmt_vinfo),
@@ -2133,7 +2000,7 @@ vect_analyze_slp_instance (vec_info *vinfo,
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"Built SLP cancelled: can use "
"load/store-lanes\n");
- vect_free_slp_instance (new_instance);
+ vect_free_slp_instance (new_instance, false);
return false;
}
}
@@ -2162,8 +2029,8 @@ vect_analyze_slp_instance (vec_info *vinfo,
vector size. */
unsigned HOST_WIDE_INT const_nunits;
if (is_a <bb_vec_info> (vinfo)
- && STMT_VINFO_GROUPED_ACCESS (vinfo_for_stmt (stmt))
- && DR_GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt))
+ && STMT_VINFO_GROUPED_ACCESS (stmt_info)
+ && DR_GROUP_FIRST_ELEMENT (stmt_info)
&& nunits.is_constant (&const_nunits))
{
/* We consider breaking the group only on VF boundaries from the existing
@@ -2177,8 +2044,10 @@ vect_analyze_slp_instance (vec_info *vinfo,
gcc_assert ((const_nunits & (const_nunits - 1)) == 0);
unsigned group1_size = i & ~(const_nunits - 1);
- gimple *rest = vect_split_slp_store_group (stmt, group1_size);
- bool res = vect_analyze_slp_instance (vinfo, stmt, max_tree_size);
+ stmt_vec_info rest = vect_split_slp_store_group (stmt_info,
+ group1_size);
+ bool res = vect_analyze_slp_instance (vinfo, stmt_info,
+ max_tree_size);
/* If the first non-match was in the middle of a vector,
skip the rest of that vector. */
if (group1_size < i)
@@ -2206,7 +2075,7 @@ bool
vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size)
{
unsigned int i;
- gimple *first_element;
+ stmt_vec_info first_element;
DUMP_VECT_SCOPE ("vect_analyze_slp");
@@ -2224,17 +2093,15 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size)
max_tree_size))
{
/* Dissolve reduction chain group. */
- gimple *next, *stmt = first_element;
- while (stmt)
+ stmt_vec_info vinfo = first_element;
+ while (vinfo)
{
- stmt_vec_info vinfo = vinfo_for_stmt (stmt);
- next = REDUC_GROUP_NEXT_ELEMENT (vinfo);
+ stmt_vec_info next = REDUC_GROUP_NEXT_ELEMENT (vinfo);
REDUC_GROUP_FIRST_ELEMENT (vinfo) = NULL;
REDUC_GROUP_NEXT_ELEMENT (vinfo) = NULL;
- stmt = next;
+ vinfo = next;
}
- STMT_VINFO_DEF_TYPE (vinfo_for_stmt (first_element))
- = vect_internal_def;
+ STMT_VINFO_DEF_TYPE (first_element) = vect_internal_def;
}
}
@@ -2300,13 +2167,12 @@ vect_make_slp_decision (loop_vec_info loop_vinfo)
static void
vect_detect_hybrid_slp_stmts (slp_tree node, unsigned i, slp_vect_type stype)
{
- gimple *stmt = SLP_TREE_SCALAR_STMTS (node)[i];
+ stmt_vec_info stmt_vinfo = SLP_TREE_SCALAR_STMTS (node)[i];
imm_use_iterator imm_iter;
gimple *use_stmt;
- stmt_vec_info use_vinfo, stmt_vinfo = vinfo_for_stmt (stmt);
+ stmt_vec_info use_vinfo;
slp_tree child;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
int j;
/* Propagate hybrid down the SLP tree. */
@@ -2320,9 +2186,7 @@ vect_detect_hybrid_slp_stmts (slp_tree node, unsigned i, slp_vect_type stype)
gcc_checking_assert (PURE_SLP_STMT (stmt_vinfo));
/* If we get a pattern stmt here we have to use the LHS of the
original stmt for immediate uses. */
- if (! STMT_VINFO_IN_PATTERN_P (stmt_vinfo)
- && STMT_VINFO_RELATED_STMT (stmt_vinfo))
- stmt = STMT_VINFO_RELATED_STMT (stmt_vinfo);
+ gimple *stmt = vect_orig_stmt (stmt_vinfo)->stmt;
tree def;
if (gimple_code (stmt) == GIMPLE_PHI)
def = gimple_phi_result (stmt);
@@ -2331,12 +2195,10 @@ vect_detect_hybrid_slp_stmts (slp_tree node, unsigned i, slp_vect_type stype)
if (def)
FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, def)
{
- if (!flow_bb_inside_loop_p (loop, gimple_bb (use_stmt)))
+ use_vinfo = loop_vinfo->lookup_stmt (use_stmt);
+ if (!use_vinfo)
continue;
- use_vinfo = vinfo_for_stmt (use_stmt);
- if (STMT_VINFO_IN_PATTERN_P (use_vinfo)
- && STMT_VINFO_RELATED_STMT (use_vinfo))
- use_vinfo = vinfo_for_stmt (STMT_VINFO_RELATED_STMT (use_vinfo));
+ use_vinfo = vect_stmt_to_vectorize (use_vinfo);
if (!STMT_SLP_TYPE (use_vinfo)
&& (STMT_VINFO_RELEVANT (use_vinfo)
|| VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (use_vinfo)))
@@ -2344,11 +2206,8 @@ vect_detect_hybrid_slp_stmts (slp_tree node, unsigned i, slp_vect_type stype)
&& STMT_VINFO_DEF_TYPE (use_vinfo) == vect_reduction_def))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "use of SLP "
- "def in non-SLP stmt: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, use_stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "use of SLP "
+ "def in non-SLP stmt: %G", use_stmt);
stype = hybrid;
}
}
@@ -2358,10 +2217,8 @@ vect_detect_hybrid_slp_stmts (slp_tree node, unsigned i, slp_vect_type stype)
&& !HYBRID_SLP_STMT (stmt_vinfo))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "marking hybrid: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "marking hybrid: %G",
+ stmt_vinfo->stmt);
STMT_SLP_TYPE (stmt_vinfo) = hybrid;
}
@@ -2376,25 +2233,18 @@ static tree
vect_detect_hybrid_slp_1 (tree *tp, int *, void *data)
{
walk_stmt_info *wi = (walk_stmt_info *)data;
- struct loop *loopp = (struct loop *)wi->info;
+ loop_vec_info loop_vinfo = (loop_vec_info) wi->info;
if (wi->is_lhs)
return NULL_TREE;
- if (TREE_CODE (*tp) == SSA_NAME
- && !SSA_NAME_IS_DEFAULT_DEF (*tp))
+ stmt_vec_info def_stmt_info = loop_vinfo->lookup_def (*tp);
+ if (def_stmt_info && PURE_SLP_STMT (def_stmt_info))
{
- gimple *def_stmt = SSA_NAME_DEF_STMT (*tp);
- if (flow_bb_inside_loop_p (loopp, gimple_bb (def_stmt))
- && PURE_SLP_STMT (vinfo_for_stmt (def_stmt)))
- {
- if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "marking hybrid: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, def_stmt, 0);
- }
- STMT_SLP_TYPE (vinfo_for_stmt (def_stmt)) = hybrid;
- }
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location, "marking hybrid: %G",
+ def_stmt_info->stmt);
+ STMT_SLP_TYPE (def_stmt_info) = hybrid;
}
return NULL_TREE;
@@ -2402,9 +2252,10 @@ vect_detect_hybrid_slp_1 (tree *tp, int *, void *data)
static tree
vect_detect_hybrid_slp_2 (gimple_stmt_iterator *gsi, bool *handled,
- walk_stmt_info *)
+ walk_stmt_info *wi)
{
- stmt_vec_info use_vinfo = vinfo_for_stmt (gsi_stmt (*gsi));
+ loop_vec_info loop_vinfo = (loop_vec_info) wi->info;
+ stmt_vec_info use_vinfo = loop_vinfo->lookup_stmt (gsi_stmt (*gsi));
/* If the stmt is in a SLP instance then this isn't a reason
to mark use definitions in other SLP instances as hybrid. */
if (! STMT_SLP_TYPE (use_vinfo)
@@ -2438,14 +2289,14 @@ vect_detect_hybrid_slp (loop_vec_info loop_vinfo)
gsi_next (&gsi))
{
gimple *stmt = gsi_stmt (gsi);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (stmt);
if (STMT_VINFO_IN_PATTERN_P (stmt_info))
{
walk_stmt_info wi;
memset (&wi, 0, sizeof (wi));
- wi.info = LOOP_VINFO_LOOP (loop_vinfo);
+ wi.info = loop_vinfo;
gimple_stmt_iterator gsi2
- = gsi_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info));
+ = gsi_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info)->stmt);
walk_gimple_stmt (&gsi2, vect_detect_hybrid_slp_2,
vect_detect_hybrid_slp_1, &wi);
walk_gimple_seq (STMT_VINFO_PATTERN_DEF_SEQ (stmt_info),
@@ -2485,7 +2336,7 @@ _bb_vec_info::_bb_vec_info (gimple_stmt_iterator region_begin_in,
{
gimple *stmt = gsi_stmt (gsi);
gimple_set_uid (stmt, 0);
- set_vinfo_for_stmt (stmt, new_stmt_vec_info (stmt, this));
+ add_stmt (stmt);
}
bb->aux = this;
@@ -2499,17 +2350,8 @@ _bb_vec_info::~_bb_vec_info ()
{
for (gimple_stmt_iterator si = region_begin;
gsi_stmt (si) != gsi_stmt (region_end); gsi_next (&si))
- {
- gimple *stmt = gsi_stmt (si);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
-
- if (stmt_info)
- /* Free stmt_vec_info. */
- free_stmt_vec_info (stmt);
-
- /* Reset region marker. */
- gimple_set_uid (stmt, -1);
- }
+ /* Reset region marker. */
+ gimple_set_uid (gsi_stmt (si), -1);
bb->aux = NULL;
}
@@ -2523,9 +2365,7 @@ vect_slp_analyze_node_operations_1 (vec_info *vinfo, slp_tree node,
slp_instance node_instance,
stmt_vector_for_cost *cost_vec)
{
- gimple *stmt = SLP_TREE_SCALAR_STMTS (node)[0];
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
- gcc_assert (stmt_info);
+ stmt_vec_info stmt_info = SLP_TREE_SCALAR_STMTS (node)[0];
gcc_assert (STMT_SLP_TYPE (stmt_info) != loop_vect);
/* For BB vectorization vector types are assigned here.
@@ -2549,10 +2389,10 @@ vect_slp_analyze_node_operations_1 (vec_info *vinfo, slp_tree node,
return false;
}
- gimple *sstmt;
+ stmt_vec_info sstmt_info;
unsigned int i;
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, sstmt)
- STMT_VINFO_VECTYPE (vinfo_for_stmt (sstmt)) = vectype;
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, sstmt_info)
+ STMT_VINFO_VECTYPE (sstmt_info) = vectype;
}
/* Calculate the number of vector statements to be created for the
@@ -2579,7 +2419,7 @@ vect_slp_analyze_node_operations_1 (vec_info *vinfo, slp_tree node,
}
bool dummy;
- return vect_analyze_stmt (stmt, &dummy, node, node_instance, cost_vec);
+ return vect_analyze_stmt (stmt_info, &dummy, node, node_instance, cost_vec);
}
/* Analyze statements contained in SLP tree NODE after recursively analyzing
@@ -2624,14 +2464,14 @@ vect_slp_analyze_node_operations (vec_info *vinfo, slp_tree node,
/* Push SLP node def-type to stmt operands. */
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), j, child)
if (SLP_TREE_DEF_TYPE (child) != vect_internal_def)
- STMT_VINFO_DEF_TYPE (vinfo_for_stmt (SLP_TREE_SCALAR_STMTS (child)[0]))
+ STMT_VINFO_DEF_TYPE (SLP_TREE_SCALAR_STMTS (child)[0])
= SLP_TREE_DEF_TYPE (child);
bool res = vect_slp_analyze_node_operations_1 (vinfo, node, node_instance,
cost_vec);
/* Restore def-types. */
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), j, child)
if (SLP_TREE_DEF_TYPE (child) != vect_internal_def)
- STMT_VINFO_DEF_TYPE (vinfo_for_stmt (SLP_TREE_SCALAR_STMTS (child)[0]))
+ STMT_VINFO_DEF_TYPE (SLP_TREE_SCALAR_STMTS (child)[0])
= vect_internal_def;
if (! res)
return false;
@@ -2663,12 +2503,12 @@ vect_slp_analyze_operations (vec_info *vinfo)
instance, visited, &lvisited,
&cost_vec))
{
+ slp_tree node = SLP_INSTANCE_TREE (instance);
+ stmt_vec_info stmt_info = SLP_TREE_SCALAR_STMTS (node)[0];
dump_printf_loc (MSG_NOTE, vect_location,
- "removing SLP instance operations starting from: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM,
- SLP_TREE_SCALAR_STMTS
- (SLP_INSTANCE_TREE (instance))[0], 0);
- vect_free_slp_instance (instance);
+ "removing SLP instance operations starting from: %G",
+ stmt_info->stmt);
+ vect_free_slp_instance (instance, false);
vinfo->slp_instances.ordered_remove (i);
cost_vec.release ();
}
@@ -2699,14 +2539,15 @@ vect_bb_slp_scalar_cost (basic_block bb,
stmt_vector_for_cost *cost_vec)
{
unsigned i;
- gimple *stmt;
+ stmt_vec_info stmt_info;
slp_tree child;
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt)
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
{
+ gimple *stmt = stmt_info->stmt;
+ vec_info *vinfo = stmt_info->vinfo;
ssa_op_iter op_iter;
def_operand_p def_p;
- stmt_vec_info stmt_info;
if ((*life)[i])
continue;
@@ -2721,13 +2562,14 @@ vect_bb_slp_scalar_cost (basic_block bb,
imm_use_iterator use_iter;
gimple *use_stmt;
FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, DEF_FROM_PTR (def_p))
- if (!is_gimple_debug (use_stmt)
- && (! vect_stmt_in_region_p (vinfo_for_stmt (stmt)->vinfo,
- use_stmt)
- || ! PURE_SLP_STMT (vinfo_for_stmt (use_stmt))))
+ if (!is_gimple_debug (use_stmt))
{
- (*life)[i] = true;
- BREAK_FROM_IMM_USE_STMT (use_iter);
+ stmt_vec_info use_stmt_info = vinfo->lookup_stmt (use_stmt);
+ if (!use_stmt_info || !PURE_SLP_STMT (use_stmt_info))
+ {
+ (*life)[i] = true;
+ BREAK_FROM_IMM_USE_STMT (use_iter);
+ }
}
}
if ((*life)[i])
@@ -2738,7 +2580,6 @@ vect_bb_slp_scalar_cost (basic_block bb,
continue;
gimple_set_visited (stmt, true);
- stmt_info = vinfo_for_stmt (stmt);
vect_cost_for_stmt kind;
if (STMT_VINFO_DATA_REF (stmt_info))
{
@@ -2942,12 +2783,12 @@ vect_slp_analyze_bb_1 (gimple_stmt_iterator region_begin,
if (! vect_slp_analyze_and_verify_instance_alignment (instance)
|| ! vect_slp_analyze_instance_dependence (instance))
{
+ slp_tree node = SLP_INSTANCE_TREE (instance);
+ stmt_vec_info stmt_info = SLP_TREE_SCALAR_STMTS (node)[0];
dump_printf_loc (MSG_NOTE, vect_location,
- "removing SLP instance operations starting from: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM,
- SLP_TREE_SCALAR_STMTS
- (SLP_INSTANCE_TREE (instance))[0], 0);
- vect_free_slp_instance (instance);
+ "removing SLP instance operations starting from: %G",
+ stmt_info->stmt);
+ vect_free_slp_instance (instance, false);
BB_VINFO_SLP_INSTANCES (bb_vinfo).ordered_remove (i);
continue;
}
@@ -3066,8 +2907,7 @@ vect_slp_bb (basic_block bb)
unsigned HOST_WIDE_INT bytes;
if (current_vector_size.is_constant (&bytes))
dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
- "basic block part vectorized using "
- HOST_WIDE_INT_PRINT_UNSIGNED " byte "
+ "basic block part vectorized using %wu byte "
"vectors\n", bytes);
else
dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
@@ -3127,13 +2967,12 @@ vect_slp_bb (basic_block bb)
/* Return 1 if vector type of boolean constant which is OPNUM
- operand in statement STMT is a boolean vector. */
+ operand in statement STMT_VINFO is a boolean vector. */
static bool
-vect_mask_constant_operand_p (gimple *stmt, int opnum)
+vect_mask_constant_operand_p (stmt_vec_info stmt_vinfo, int opnum)
{
- stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
- enum tree_code code = gimple_expr_code (stmt);
+ enum tree_code code = gimple_expr_code (stmt_vinfo->stmt);
tree op, vectype;
enum vect_def_type dt;
@@ -3141,6 +2980,7 @@ vect_mask_constant_operand_p (gimple *stmt, int opnum)
on the other comparison operand. */
if (TREE_CODE_CLASS (code) == tcc_comparison)
{
+ gassign *stmt = as_a <gassign *> (stmt_vinfo->stmt);
if (opnum)
op = gimple_assign_rhs1 (stmt);
else
@@ -3154,6 +2994,7 @@ vect_mask_constant_operand_p (gimple *stmt, int opnum)
if (code == COND_EXPR)
{
+ gassign *stmt = as_a <gassign *> (stmt_vinfo->stmt);
tree cond = gimple_assign_rhs1 (stmt);
if (TREE_CODE (cond) == SSA_NAME)
@@ -3297,9 +3138,9 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
vec<tree> *vec_oprnds,
unsigned int op_num, unsigned int number_of_vectors)
{
- vec<gimple *> stmts = SLP_TREE_SCALAR_STMTS (slp_node);
- gimple *stmt = stmts[0];
- stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
+ vec<stmt_vec_info> stmts = SLP_TREE_SCALAR_STMTS (slp_node);
+ stmt_vec_info stmt_vinfo = stmts[0];
+ gimple *stmt = stmt_vinfo->stmt;
unsigned HOST_WIDE_INT nunits;
tree vec_cst;
unsigned j, number_of_places_left_in_vector;
@@ -3318,7 +3159,7 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
/* Check if vector type is a boolean vector. */
if (VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (op))
- && vect_mask_constant_operand_p (stmt, op_num))
+ && vect_mask_constant_operand_p (stmt_vinfo, op_num))
vector_type
= build_same_sized_truth_vector_type (STMT_VINFO_VECTYPE (stmt_vinfo));
else
@@ -3364,8 +3205,9 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
bool place_after_defs = false;
for (j = 0; j < number_of_copies; j++)
{
- for (i = group_size - 1; stmts.iterate (i, &stmt); i--)
+ for (i = group_size - 1; stmts.iterate (i, &stmt_vinfo); i--)
{
+ stmt = stmt_vinfo->stmt;
if (is_store)
op = gimple_assign_rhs1 (stmt);
else
@@ -3492,12 +3334,15 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
gimple_stmt_iterator gsi;
if (place_after_defs)
{
- gsi = gsi_for_stmt
- (vect_find_last_scalar_stmt_in_slp (slp_node));
- init = vect_init_vector (stmt, vec_cst, vector_type, &gsi);
+ stmt_vec_info last_stmt_info
+ = vect_find_last_scalar_stmt_in_slp (slp_node);
+ gsi = gsi_for_stmt (last_stmt_info->stmt);
+ init = vect_init_vector (stmt_vinfo, vec_cst, vector_type,
+ &gsi);
}
else
- init = vect_init_vector (stmt, vec_cst, vector_type, NULL);
+ init = vect_init_vector (stmt_vinfo, vec_cst, vector_type,
+ NULL);
if (ctor_seq != NULL)
{
gsi = gsi_for_stmt (SSA_NAME_DEF_STMT (init));
@@ -3556,18 +3401,18 @@ static void
vect_get_slp_vect_defs (slp_tree slp_node, vec<tree> *vec_oprnds)
{
tree vec_oprnd;
- gimple *vec_def_stmt;
+ stmt_vec_info vec_def_stmt_info;
unsigned int i;
gcc_assert (SLP_TREE_VEC_STMTS (slp_node).exists ());
- FOR_EACH_VEC_ELT (SLP_TREE_VEC_STMTS (slp_node), i, vec_def_stmt)
+ FOR_EACH_VEC_ELT (SLP_TREE_VEC_STMTS (slp_node), i, vec_def_stmt_info)
{
- gcc_assert (vec_def_stmt);
- if (gimple_code (vec_def_stmt) == GIMPLE_PHI)
- vec_oprnd = gimple_phi_result (vec_def_stmt);
+ gcc_assert (vec_def_stmt_info);
+ if (gphi *vec_def_phi = dyn_cast <gphi *> (vec_def_stmt_info->stmt))
+ vec_oprnd = gimple_phi_result (vec_def_phi);
else
- vec_oprnd = gimple_get_lhs (vec_def_stmt);
+ vec_oprnd = gimple_get_lhs (vec_def_stmt_info->stmt);
vec_oprnds->quick_push (vec_oprnd);
}
}
@@ -3584,7 +3429,6 @@ void
vect_get_slp_defs (vec<tree> ops, slp_tree slp_node,
vec<vec<tree> > *vec_oprnds)
{
- gimple *first_stmt;
int number_of_vects = 0, i;
unsigned int child_index = 0;
HOST_WIDE_INT lhs_size_unit, rhs_size_unit;
@@ -3593,7 +3437,7 @@ vect_get_slp_defs (vec<tree> ops, slp_tree slp_node,
tree oprnd;
bool vectorized_defs;
- first_stmt = SLP_TREE_SCALAR_STMTS (slp_node)[0];
+ stmt_vec_info first_stmt_info = SLP_TREE_SCALAR_STMTS (slp_node)[0];
FOR_EACH_VEC_ELT (ops, i, oprnd)
{
/* For each operand we check if it has vectorized definitions in a child
@@ -3610,18 +3454,18 @@ vect_get_slp_defs (vec<tree> ops, slp_tree slp_node,
/* We have to check both pattern and original def, if available. */
if (SLP_TREE_DEF_TYPE (child) == vect_internal_def)
{
- gimple *first_def = SLP_TREE_SCALAR_STMTS (child)[0];
- gimple *related
- = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (first_def));
+ stmt_vec_info first_def_info = SLP_TREE_SCALAR_STMTS (child)[0];
+ stmt_vec_info related = STMT_VINFO_RELATED_STMT (first_def_info);
tree first_def_op;
- if (gimple_code (first_def) == GIMPLE_PHI)
+ if (gphi *first_def = dyn_cast <gphi *> (first_def_info->stmt))
first_def_op = gimple_phi_result (first_def);
else
- first_def_op = gimple_get_lhs (first_def);
+ first_def_op = gimple_get_lhs (first_def_info->stmt);
if (operand_equal_p (oprnd, first_def_op, 0)
|| (related
- && operand_equal_p (oprnd, gimple_get_lhs (related), 0)))
+ && operand_equal_p (oprnd,
+ gimple_get_lhs (related->stmt), 0)))
{
/* The number of vector defs is determined by the number of
vector statements in the node from which we get those
@@ -3644,8 +3488,8 @@ vect_get_slp_defs (vec<tree> ops, slp_tree slp_node,
vect_schedule_slp_instance (), fix it by replacing LHS with
RHS, if necessary. See vect_get_smallest_scalar_type () for
details. */
- vect_get_smallest_scalar_type (first_stmt, &lhs_size_unit,
- &rhs_size_unit);
+ vect_get_smallest_scalar_type (first_stmt_info, &lhs_size_unit,
+ &rhs_size_unit);
if (rhs_size_unit != lhs_size_unit)
{
number_of_vects *= rhs_size_unit;
@@ -3683,38 +3527,21 @@ vect_transform_slp_perm_load (slp_tree node, vec<tree> dr_chain,
slp_instance slp_node_instance, bool analyze_only,
unsigned *n_perms)
{
- gimple *stmt = SLP_TREE_SCALAR_STMTS (node)[0];
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
- tree mask_element_type = NULL_TREE, mask_type;
+ stmt_vec_info stmt_info = SLP_TREE_SCALAR_STMTS (node)[0];
+ vec_info *vinfo = stmt_info->vinfo;
int vec_index = 0;
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
- int group_size = SLP_INSTANCE_GROUP_SIZE (slp_node_instance);
+ unsigned int group_size = SLP_INSTANCE_GROUP_SIZE (slp_node_instance);
unsigned int mask_element;
machine_mode mode;
- unsigned HOST_WIDE_INT nunits, const_vf;
if (!STMT_VINFO_GROUPED_ACCESS (stmt_info))
return false;
- stmt_info = vinfo_for_stmt (DR_GROUP_FIRST_ELEMENT (stmt_info));
+ stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
mode = TYPE_MODE (vectype);
-
- /* At the moment, all permutations are represented using per-element
- indices, so we can't cope with variable vector lengths or
- vectorization factors. */
- if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant (&nunits)
- || !vf.is_constant (&const_vf))
- 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_mode
- (int_mode_for_mode (TYPE_MODE (TREE_TYPE (vectype))).require (), 1);
- mask_type = get_vectype_for_scalar_type (mask_element_type);
- vec_perm_builder mask (nunits, nunits, 1);
- mask.quick_grow (nunits);
- vec_perm_indices indices;
+ poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
/* Initialize the vect stmts of NODE to properly insert the generated
stmts later. */
@@ -3748,14 +3575,53 @@ vect_transform_slp_perm_load (slp_tree node, vec<tree> dr_chain,
bool noop_p = true;
*n_perms = 0;
- for (unsigned int j = 0; j < const_vf; j++)
+ vec_perm_builder mask;
+ unsigned int nelts_to_build;
+ unsigned int nvectors_per_build;
+ bool repeating_p = (group_size == DR_GROUP_SIZE (stmt_info)
+ && multiple_p (nunits, group_size));
+ if (repeating_p)
{
- for (int k = 0; k < group_size; k++)
+ /* A single vector contains a whole number of copies of the node, so:
+ (a) all permutes can use the same mask; and
+ (b) the permutes only need a single vector input. */
+ mask.new_vector (nunits, group_size, 3);
+ nelts_to_build = mask.encoded_nelts ();
+ nvectors_per_build = SLP_TREE_VEC_STMTS (node).length ();
+ }
+ else
+ {
+ /* We need to construct a separate mask for each vector statement. */
+ unsigned HOST_WIDE_INT const_nunits, const_vf;
+ if (!nunits.is_constant (&const_nunits)
+ || !vf.is_constant (&const_vf))
+ return false;
+ mask.new_vector (const_nunits, const_nunits, 1);
+ nelts_to_build = const_vf * group_size;
+ nvectors_per_build = 1;
+ }
+
+ unsigned int count = mask.encoded_nelts ();
+ mask.quick_grow (count);
+ vec_perm_indices indices;
+
+ for (unsigned int j = 0; j < nelts_to_build; j++)
+ {
+ unsigned int iter_num = j / group_size;
+ unsigned int stmt_num = j % group_size;
+ unsigned int i = (iter_num * DR_GROUP_SIZE (stmt_info)
+ + SLP_TREE_LOAD_PERMUTATION (node)[stmt_num]);
+ if (repeating_p)
+ {
+ first_vec_index = 0;
+ mask_element = i;
+ }
+ else
{
- unsigned int i = (SLP_TREE_LOAD_PERMUTATION (node)[k]
- + j * DR_GROUP_SIZE (stmt_info));
- vec_index = i / nunits;
- mask_element = i % nunits;
+ /* Enforced before the loop when !repeating_p. */
+ unsigned int const_nunits = nunits.to_constant ();
+ vec_index = i / const_nunits;
+ mask_element = i % const_nunits;
if (vec_index == first_vec_index
|| first_vec_index == -1)
{
@@ -3765,93 +3631,98 @@ vect_transform_slp_perm_load (slp_tree node, vec<tree> dr_chain,
|| second_vec_index == -1)
{
second_vec_index = vec_index;
- mask_element += nunits;
+ mask_element += const_nunits;
}
else
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "permutation requires at "
- "least three vectors ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "permutation requires at "
+ "least three vectors %G",
+ stmt_info->stmt);
gcc_assert (analyze_only);
return false;
}
- gcc_assert (mask_element < 2 * nunits);
- if (mask_element != index)
- noop_p = false;
- mask[index++] = mask_element;
+ gcc_assert (mask_element < 2 * const_nunits);
+ }
+
+ if (mask_element != index)
+ noop_p = false;
+ mask[index++] = mask_element;
- if (index == nunits && !noop_p)
+ if (index == count && !noop_p)
+ {
+ indices.new_vector (mask, second_vec_index == -1 ? 1 : 2, nunits);
+ if (!can_vec_perm_const_p (mode, indices))
{
- indices.new_vector (mask, 2, nunits);
- if (!can_vec_perm_const_p (mode, indices))
+ if (dump_enabled_p ())
{
- if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION,
+ vect_location,
+ "unsupported vect permute { ");
+ for (i = 0; i < count; ++i)
{
- dump_printf_loc (MSG_MISSED_OPTIMIZATION,
- vect_location,
- "unsupported vect permute { ");
- for (i = 0; i < nunits; ++i)
- {
- dump_dec (MSG_MISSED_OPTIMIZATION, mask[i]);
- dump_printf (MSG_MISSED_OPTIMIZATION, " ");
- }
- dump_printf (MSG_MISSED_OPTIMIZATION, "}\n");
+ dump_dec (MSG_MISSED_OPTIMIZATION, mask[i]);
+ dump_printf (MSG_MISSED_OPTIMIZATION, " ");
}
- gcc_assert (analyze_only);
- return false;
+ dump_printf (MSG_MISSED_OPTIMIZATION, "}\n");
}
-
- ++*n_perms;
+ gcc_assert (analyze_only);
+ return false;
}
- if (index == nunits)
+ ++*n_perms;
+ }
+
+ if (index == count)
+ {
+ if (!analyze_only)
{
- if (!analyze_only)
- {
- tree mask_vec = NULL_TREE;
+ tree mask_vec = NULL_TREE;
- if (! noop_p)
- mask_vec = vec_perm_indices_to_tree (mask_type, indices);
+ if (! noop_p)
+ mask_vec = vect_gen_perm_mask_checked (vectype, indices);
- if (second_vec_index == -1)
- second_vec_index = first_vec_index;
+ if (second_vec_index == -1)
+ second_vec_index = first_vec_index;
+ for (unsigned int ri = 0; ri < nvectors_per_build; ++ri)
+ {
/* Generate the permute statement if necessary. */
- tree first_vec = dr_chain[first_vec_index];
- tree second_vec = dr_chain[second_vec_index];
- gimple *perm_stmt;
+ tree first_vec = dr_chain[first_vec_index + ri];
+ tree second_vec = dr_chain[second_vec_index + ri];
+ stmt_vec_info perm_stmt_info;
if (! noop_p)
{
+ gassign *stmt = as_a <gassign *> (stmt_info->stmt);
tree perm_dest
= vect_create_destination_var (gimple_assign_lhs (stmt),
vectype);
perm_dest = make_ssa_name (perm_dest);
- perm_stmt = gimple_build_assign (perm_dest,
- VEC_PERM_EXPR,
- first_vec, second_vec,
- mask_vec);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ gassign *perm_stmt
+ = gimple_build_assign (perm_dest, VEC_PERM_EXPR,
+ first_vec, second_vec,
+ mask_vec);
+ perm_stmt_info
+ = vect_finish_stmt_generation (stmt_info, perm_stmt,
+ gsi);
}
else
/* If mask was NULL_TREE generate the requested
identity transform. */
- perm_stmt = SSA_NAME_DEF_STMT (first_vec);
+ perm_stmt_info = vinfo->lookup_def (first_vec);
/* Store the vector statement in NODE. */
- SLP_TREE_VEC_STMTS (node)[vect_stmts_counter++] = perm_stmt;
+ SLP_TREE_VEC_STMTS (node)[vect_stmts_counter++]
+ = perm_stmt_info;
}
-
- index = 0;
- first_vec_index = -1;
- second_vec_index = -1;
- noop_p = true;
}
+
+ index = 0;
+ first_vec_index = -1;
+ second_vec_index = -1;
+ noop_p = true;
}
}
@@ -3860,12 +3731,10 @@ vect_transform_slp_perm_load (slp_tree node, vec<tree> dr_chain,
/* Vectorize SLP instance tree in postorder. */
-static bool
+static void
vect_schedule_slp_instance (slp_tree node, slp_instance instance,
scalar_stmts_to_slp_tree_map_t *bst_map)
{
- gimple *stmt;
- bool grouped_store, is_store;
gimple_stmt_iterator si;
stmt_vec_info stmt_info;
unsigned int group_size;
@@ -3874,14 +3743,14 @@ vect_schedule_slp_instance (slp_tree node, slp_instance instance,
slp_tree child;
if (SLP_TREE_DEF_TYPE (node) != vect_internal_def)
- return false;
+ return;
/* See if we have already vectorized the same set of stmts and reuse their
vectorized stmts. */
if (slp_tree *leader = bst_map->get (SLP_TREE_SCALAR_STMTS (node)))
{
SLP_TREE_VEC_STMTS (node).safe_splice (SLP_TREE_VEC_STMTS (*leader));
- return false;
+ return;
}
bst_map->put (SLP_TREE_SCALAR_STMTS (node).copy (), node);
@@ -3891,11 +3760,13 @@ vect_schedule_slp_instance (slp_tree node, slp_instance instance,
/* Push SLP node def-type to stmts. */
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
if (SLP_TREE_DEF_TYPE (child) != vect_internal_def)
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (child), j, stmt)
- STMT_VINFO_DEF_TYPE (vinfo_for_stmt (stmt)) = SLP_TREE_DEF_TYPE (child);
+ {
+ stmt_vec_info child_stmt_info;
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (child), j, child_stmt_info)
+ STMT_VINFO_DEF_TYPE (child_stmt_info) = SLP_TREE_DEF_TYPE (child);
+ }
- stmt = SLP_TREE_SCALAR_STMTS (node)[0];
- stmt_info = vinfo_for_stmt (stmt);
+ stmt_info = SLP_TREE_SCALAR_STMTS (node)[0];
/* VECTYPE is the type of the destination. */
vectype = STMT_VINFO_VECTYPE (stmt_info);
@@ -3907,22 +3778,21 @@ vect_schedule_slp_instance (slp_tree node, slp_instance instance,
SLP_TREE_VEC_STMTS (node).create (SLP_TREE_NUMBER_OF_VEC_STMTS (node));
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE,vect_location,
- "------>vectorizing SLP node starting from: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "------>vectorizing SLP node starting from: %G",
+ stmt_info->stmt);
/* Vectorized stmts go before the last scalar stmt which is where
all uses are ready. */
- si = gsi_for_stmt (vect_find_last_scalar_stmt_in_slp (node));
+ stmt_vec_info last_stmt_info = vect_find_last_scalar_stmt_in_slp (node);
+ si = gsi_for_stmt (last_stmt_info->stmt);
/* Mark the first element of the reduction chain as reduction to properly
transform the node. In the analysis phase only the last element of the
chain is marked as reduction. */
if (!STMT_VINFO_GROUPED_ACCESS (stmt_info)
&& REDUC_GROUP_FIRST_ELEMENT (stmt_info)
- && REDUC_GROUP_FIRST_ELEMENT (stmt_info) == stmt)
+ && REDUC_GROUP_FIRST_ELEMENT (stmt_info) == stmt_info)
{
STMT_VINFO_DEF_TYPE (stmt_info) = vect_reduction_def;
STMT_VINFO_TYPE (stmt_info) = reduc_vec_info_type;
@@ -3932,29 +3802,33 @@ vect_schedule_slp_instance (slp_tree node, slp_instance instance,
both operations and then performing a merge. */
if (SLP_TREE_TWO_OPERATORS (node))
{
+ gassign *stmt = as_a <gassign *> (stmt_info->stmt);
enum tree_code code0 = gimple_assign_rhs_code (stmt);
enum tree_code ocode = ERROR_MARK;
- gimple *ostmt;
+ stmt_vec_info ostmt_info;
vec_perm_builder mask (group_size, group_size, 1);
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, ostmt)
- if (gimple_assign_rhs_code (ostmt) != code0)
- {
- mask.quick_push (1);
- ocode = gimple_assign_rhs_code (ostmt);
- }
- else
- mask.quick_push (0);
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, ostmt_info)
+ {
+ gassign *ostmt = as_a <gassign *> (ostmt_info->stmt);
+ if (gimple_assign_rhs_code (ostmt) != code0)
+ {
+ mask.quick_push (1);
+ ocode = gimple_assign_rhs_code (ostmt);
+ }
+ else
+ mask.quick_push (0);
+ }
if (ocode != ERROR_MARK)
{
- vec<gimple *> v0;
- vec<gimple *> v1;
+ vec<stmt_vec_info> v0;
+ vec<stmt_vec_info> v1;
unsigned j;
tree tmask = NULL_TREE;
- vect_transform_stmt (stmt, &si, &grouped_store, node, instance);
+ vect_transform_stmt (stmt_info, &si, node, instance);
v0 = SLP_TREE_VEC_STMTS (node).copy ();
SLP_TREE_VEC_STMTS (node).truncate (0);
gimple_assign_set_rhs_code (stmt, ocode);
- vect_transform_stmt (stmt, &si, &grouped_store, node, instance);
+ vect_transform_stmt (stmt_info, &si, node, instance);
gimple_assign_set_rhs_code (stmt, code0);
v1 = SLP_TREE_VEC_STMTS (node).copy ();
SLP_TREE_VEC_STMTS (node).truncate (0);
@@ -3988,25 +3862,27 @@ vect_schedule_slp_instance (slp_tree node, slp_instance instance,
gimple *vstmt;
vstmt = gimple_build_assign (make_ssa_name (vectype),
VEC_PERM_EXPR,
- gimple_assign_lhs (v0[j]),
- gimple_assign_lhs (v1[j]), tmask);
- vect_finish_stmt_generation (stmt, vstmt, &si);
- SLP_TREE_VEC_STMTS (node).quick_push (vstmt);
+ gimple_assign_lhs (v0[j]->stmt),
+ gimple_assign_lhs (v1[j]->stmt),
+ tmask);
+ SLP_TREE_VEC_STMTS (node).quick_push
+ (vect_finish_stmt_generation (stmt_info, vstmt, &si));
}
v0.release ();
v1.release ();
- return false;
+ return;
}
}
- is_store = vect_transform_stmt (stmt, &si, &grouped_store, node, instance);
+ vect_transform_stmt (stmt_info, &si, node, instance);
/* Restore stmt def-types. */
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
if (SLP_TREE_DEF_TYPE (child) != vect_internal_def)
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (child), j, stmt)
- STMT_VINFO_DEF_TYPE (vinfo_for_stmt (stmt)) = vect_internal_def;
-
- return is_store;
+ {
+ stmt_vec_info child_stmt_info;
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (child), j, child_stmt_info)
+ STMT_VINFO_DEF_TYPE (child_stmt_info) = vect_internal_def;
+ }
}
/* Replace scalar calls from SLP node NODE with setting of their lhs to zero.
@@ -4017,7 +3893,7 @@ vect_schedule_slp_instance (slp_tree node, slp_instance instance,
static void
vect_remove_slp_scalar_calls (slp_tree node)
{
- gimple *stmt, *new_stmt;
+ gimple *new_stmt;
gimple_stmt_iterator gsi;
int i;
slp_tree child;
@@ -4030,36 +3906,30 @@ vect_remove_slp_scalar_calls (slp_tree node)
FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
vect_remove_slp_scalar_calls (child);
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt)
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
{
- if (!is_gimple_call (stmt) || gimple_bb (stmt) == NULL)
+ gcall *stmt = dyn_cast <gcall *> (stmt_info->stmt);
+ if (!stmt || gimple_bb (stmt) == NULL)
continue;
- stmt_info = vinfo_for_stmt (stmt);
- if (stmt_info == NULL
- || is_pattern_stmt_p (stmt_info)
+ if (is_pattern_stmt_p (stmt_info)
|| !PURE_SLP_STMT (stmt_info))
continue;
lhs = gimple_call_lhs (stmt);
new_stmt = gimple_build_assign (lhs, build_zero_cst (TREE_TYPE (lhs)));
- set_vinfo_for_stmt (new_stmt, stmt_info);
- set_vinfo_for_stmt (stmt, NULL);
- STMT_VINFO_STMT (stmt_info) = new_stmt;
gsi = gsi_for_stmt (stmt);
- gsi_replace (&gsi, new_stmt, false);
+ stmt_info->vinfo->replace_stmt (&gsi, stmt_info, new_stmt);
SSA_NAME_DEF_STMT (gimple_assign_lhs (new_stmt)) = new_stmt;
}
}
/* Generate vector code for all SLP instances in the loop/basic block. */
-bool
+void
vect_schedule_slp (vec_info *vinfo)
{
vec<slp_instance> slp_instances;
slp_instance instance;
unsigned int i;
- bool is_store = false;
-
scalar_stmts_to_slp_tree_map_t *bst_map
= new scalar_stmts_to_slp_tree_map_t ();
@@ -4067,8 +3937,8 @@ vect_schedule_slp (vec_info *vinfo)
FOR_EACH_VEC_ELT (slp_instances, i, instance)
{
/* Schedule the tree of INSTANCE. */
- is_store = vect_schedule_slp_instance (SLP_INSTANCE_TREE (instance),
- instance, bst_map);
+ vect_schedule_slp_instance (SLP_INSTANCE_TREE (instance),
+ instance, bst_map);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"vectorizing stmts using SLP.\n");
@@ -4078,9 +3948,8 @@ vect_schedule_slp (vec_info *vinfo)
FOR_EACH_VEC_ELT (slp_instances, i, instance)
{
slp_tree root = SLP_INSTANCE_TREE (instance);
- gimple *store;
+ stmt_vec_info store_info;
unsigned int j;
- gimple_stmt_iterator gsi;
/* Remove scalar call stmts. Do not do this for basic-block
vectorization as not all uses may be vectorized.
@@ -4092,22 +3961,15 @@ vect_schedule_slp (vec_info *vinfo)
if (is_a <loop_vec_info> (vinfo))
vect_remove_slp_scalar_calls (root);
- for (j = 0; SLP_TREE_SCALAR_STMTS (root).iterate (j, &store)
+ for (j = 0; SLP_TREE_SCALAR_STMTS (root).iterate (j, &store_info)
&& j < SLP_INSTANCE_GROUP_SIZE (instance); j++)
{
- if (!STMT_VINFO_DATA_REF (vinfo_for_stmt (store)))
- break;
-
- if (is_pattern_stmt_p (vinfo_for_stmt (store)))
- store = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (store));
- /* Free the attached stmt_vec_info and remove the stmt. */
- gsi = gsi_for_stmt (store);
- unlink_stmt_vdef (store);
- gsi_remove (&gsi, true);
- release_defs (store);
- free_stmt_vec_info (store);
+ if (!STMT_VINFO_DATA_REF (store_info))
+ break;
+
+ store_info = vect_orig_stmt (store_info);
+ /* Free the attached stmt_vec_info and remove the stmt. */
+ vinfo->remove_stmt (store_info);
}
}
-
- return is_store;
}
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index f420a42..7a6efdb 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -98,9 +98,7 @@ record_stmt_cost (stmt_vector_for_cost *body_cost_vec, int count,
&& STMT_VINFO_GATHER_SCATTER_P (stmt_info))
kind = vector_scatter_store;
- stmt_info_for_cost si = { count, kind, where,
- stmt_info ? STMT_VINFO_STMT (stmt_info) : NULL,
- misalign };
+ stmt_info_for_cost si = { count, kind, where, stmt_info, misalign };
body_cost_vec->safe_push (si);
tree vectype = stmt_info ? stmt_vectype (stmt_info) : NULL_TREE;
@@ -119,12 +117,12 @@ create_vector_array (tree elem_type, unsigned HOST_WIDE_INT nelems)
/* ARRAY is an array of vectors created by create_vector_array.
Return an SSA_NAME for the vector in index N. The reference
- is part of the vectorization of STMT and the vector is associated
+ is part of the vectorization of STMT_INFO and the vector is associated
with scalar destination SCALAR_DEST. */
static tree
-read_vector_array (gimple *stmt, gimple_stmt_iterator *gsi, tree scalar_dest,
- tree array, unsigned HOST_WIDE_INT n)
+read_vector_array (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ tree scalar_dest, tree array, unsigned HOST_WIDE_INT n)
{
tree vect_type, vect, vect_name, array_ref;
gimple *new_stmt;
@@ -139,18 +137,18 @@ read_vector_array (gimple *stmt, gimple_stmt_iterator *gsi, tree scalar_dest,
new_stmt = gimple_build_assign (vect, array_ref);
vect_name = make_ssa_name (vect, new_stmt);
gimple_assign_set_lhs (new_stmt, vect_name);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
return vect_name;
}
/* ARRAY is an array of vectors created by create_vector_array.
Emit code to store SSA_NAME VECT in index N of the array.
- The store is part of the vectorization of STMT. */
+ The store is part of the vectorization of STMT_INFO. */
static void
-write_vector_array (gimple *stmt, gimple_stmt_iterator *gsi, tree vect,
- tree array, unsigned HOST_WIDE_INT n)
+write_vector_array (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ tree vect, tree array, unsigned HOST_WIDE_INT n)
{
tree array_ref;
gimple *new_stmt;
@@ -160,7 +158,7 @@ write_vector_array (gimple *stmt, gimple_stmt_iterator *gsi, tree vect,
NULL_TREE, NULL_TREE);
new_stmt = gimple_build_assign (array_ref, vect);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
}
/* PTR is a pointer to an array of type TYPE. Return a representation
@@ -178,38 +176,35 @@ create_array_ref (tree type, tree ptr, tree alias_ptr_type)
return mem_ref;
}
-/* Add a clobber of variable VAR to the vectorization of STMT.
+/* Add a clobber of variable VAR to the vectorization of STMT_INFO.
Emit the clobber before *GSI. */
static void
-vect_clobber_variable (gimple *stmt, gimple_stmt_iterator *gsi, tree var)
+vect_clobber_variable (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ tree var)
{
tree clobber = build_clobber (TREE_TYPE (var));
gimple *new_stmt = gimple_build_assign (var, clobber);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
}
/* Utility functions used by vect_mark_stmts_to_be_vectorized. */
/* Function vect_mark_relevant.
- Mark STMT as "relevant for vectorization" and add it to WORKLIST. */
+ Mark STMT_INFO as "relevant for vectorization" and add it to WORKLIST. */
static void
-vect_mark_relevant (vec<gimple *> *worklist, gimple *stmt,
+vect_mark_relevant (vec<stmt_vec_info> *worklist, stmt_vec_info stmt_info,
enum vect_relevant relevant, bool live_p)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
enum vect_relevant save_relevant = STMT_VINFO_RELEVANT (stmt_info);
bool save_live_p = STMT_VINFO_LIVE_P (stmt_info);
- gimple *pattern_stmt;
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "mark relevant %d, live %d: ", relevant, live_p);
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "mark relevant %d, live %d: %G", relevant, live_p,
+ stmt_info->stmt);
/* If this stmt is an original stmt in a pattern, we might need to mark its
related pattern stmt instead of the original stmt. However, such stmts
@@ -222,17 +217,15 @@ vect_mark_relevant (vec<gimple *> *worklist, gimple *stmt,
as relevant/live because it's not going to be vectorized.
Instead mark the pattern-stmt that replaces it. */
- pattern_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
-
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"last stmt in pattern. don't mark"
" relevant/live.\n");
- stmt_info = vinfo_for_stmt (pattern_stmt);
- gcc_assert (STMT_VINFO_RELATED_STMT (stmt_info) == stmt);
+ stmt_vec_info old_stmt_info = stmt_info;
+ stmt_info = STMT_VINFO_RELATED_STMT (stmt_info);
+ gcc_assert (STMT_VINFO_RELATED_STMT (stmt_info) == old_stmt_info);
save_relevant = STMT_VINFO_RELEVANT (stmt_info);
save_live_p = STMT_VINFO_LIVE_P (stmt_info);
- stmt = pattern_stmt;
}
STMT_VINFO_LIVE_P (stmt_info) |= live_p;
@@ -248,21 +241,23 @@ vect_mark_relevant (vec<gimple *> *worklist, gimple *stmt,
return;
}
- worklist->safe_push (stmt);
+ worklist->safe_push (stmt_info);
}
/* Function is_simple_and_all_uses_invariant
- Return true if STMT is simple and all uses of it are invariant. */
+ Return true if STMT_INFO is simple and all uses of it are invariant. */
bool
-is_simple_and_all_uses_invariant (gimple *stmt, loop_vec_info loop_vinfo)
+is_simple_and_all_uses_invariant (stmt_vec_info stmt_info,
+ loop_vec_info loop_vinfo)
{
tree op;
ssa_op_iter iter;
- if (!is_gimple_assign (stmt))
+ gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt);
+ if (!stmt)
return false;
FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
@@ -285,8 +280,8 @@ is_simple_and_all_uses_invariant (gimple *stmt, loop_vec_info loop_vinfo)
/* Function vect_stmt_relevant_p.
- Return true if STMT in loop that is represented by LOOP_VINFO is
- "relevant for vectorization".
+ Return true if STMT_INFO, in the loop that is represented by LOOP_VINFO,
+ is "relevant for vectorization".
A stmt is considered "relevant for vectorization" if:
- it has uses outside the loop.
@@ -296,7 +291,7 @@ is_simple_and_all_uses_invariant (gimple *stmt, loop_vec_info loop_vinfo)
CHECKME: what other side effects would the vectorizer allow? */
static bool
-vect_stmt_relevant_p (gimple *stmt, loop_vec_info loop_vinfo,
+vect_stmt_relevant_p (stmt_vec_info stmt_info, loop_vec_info loop_vinfo,
enum vect_relevant *relevant, bool *live_p)
{
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
@@ -309,15 +304,14 @@ vect_stmt_relevant_p (gimple *stmt, loop_vec_info loop_vinfo,
*live_p = false;
/* cond stmt other than loop exit cond. */
- if (is_ctrl_stmt (stmt)
- && STMT_VINFO_TYPE (vinfo_for_stmt (stmt))
- != loop_exit_ctrl_vec_info_type)
+ if (is_ctrl_stmt (stmt_info->stmt)
+ && STMT_VINFO_TYPE (stmt_info) != loop_exit_ctrl_vec_info_type)
*relevant = vect_used_in_scope;
/* changing memory. */
- if (gimple_code (stmt) != GIMPLE_PHI)
- if (gimple_vdef (stmt)
- && !gimple_clobber_p (stmt))
+ if (gimple_code (stmt_info->stmt) != GIMPLE_PHI)
+ if (gimple_vdef (stmt_info->stmt)
+ && !gimple_clobber_p (stmt_info->stmt))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
@@ -326,7 +320,7 @@ vect_stmt_relevant_p (gimple *stmt, loop_vec_info loop_vinfo,
}
/* uses outside the loop. */
- FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt, op_iter, SSA_OP_DEF)
+ FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt_info->stmt, op_iter, SSA_OP_DEF)
{
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, DEF_FROM_PTR (def_p))
{
@@ -351,7 +345,7 @@ vect_stmt_relevant_p (gimple *stmt, loop_vec_info loop_vinfo,
}
if (*live_p && *relevant == vect_unused_in_scope
- && !is_simple_and_all_uses_invariant (stmt, loop_vinfo))
+ && !is_simple_and_all_uses_invariant (stmt_info, loop_vinfo))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
@@ -365,14 +359,13 @@ vect_stmt_relevant_p (gimple *stmt, loop_vec_info loop_vinfo,
/* Function exist_non_indexing_operands_for_use_p
- USE is one of the uses attached to STMT. Check if USE is
- used in STMT for anything other than indexing an array. */
+ USE is one of the uses attached to STMT_INFO. Check if USE is
+ used in STMT_INFO for anything other than indexing an array. */
static bool
-exist_non_indexing_operands_for_use_p (tree use, gimple *stmt)
+exist_non_indexing_operands_for_use_p (tree use, stmt_vec_info stmt_info)
{
tree operand;
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
/* USE corresponds to some operand in STMT. If there is no data
reference in STMT, then any operand that corresponds to USE
@@ -393,30 +386,31 @@ exist_non_indexing_operands_for_use_p (tree use, gimple *stmt)
Therefore, all we need to check is if STMT falls into the
first case, and whether var corresponds to USE. */
- if (!gimple_assign_copy_p (stmt))
+ gassign *assign = dyn_cast <gassign *> (stmt_info->stmt);
+ if (!assign || !gimple_assign_copy_p (assign))
{
- if (is_gimple_call (stmt)
- && gimple_call_internal_p (stmt))
+ gcall *call = dyn_cast <gcall *> (stmt_info->stmt);
+ if (call && gimple_call_internal_p (call))
{
- internal_fn ifn = gimple_call_internal_fn (stmt);
+ internal_fn ifn = gimple_call_internal_fn (call);
int mask_index = internal_fn_mask_index (ifn);
if (mask_index >= 0
- && use == gimple_call_arg (stmt, mask_index))
+ && use == gimple_call_arg (call, mask_index))
return true;
int stored_value_index = internal_fn_stored_value_index (ifn);
if (stored_value_index >= 0
- && use == gimple_call_arg (stmt, stored_value_index))
+ && use == gimple_call_arg (call, stored_value_index))
return true;
if (internal_gather_scatter_fn_p (ifn)
- && use == gimple_call_arg (stmt, 1))
+ && use == gimple_call_arg (call, 1))
return true;
}
return false;
}
- if (TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME)
+ if (TREE_CODE (gimple_assign_lhs (assign)) == SSA_NAME)
return false;
- operand = gimple_assign_rhs1 (stmt);
+ operand = gimple_assign_rhs1 (assign);
if (TREE_CODE (operand) != SSA_NAME)
return false;
@@ -431,7 +425,7 @@ exist_non_indexing_operands_for_use_p (tree use, gimple *stmt)
Function process_use.
Inputs:
- - a USE in STMT in a loop represented by LOOP_VINFO
+ - a USE in STMT_VINFO in a loop represented by LOOP_VINFO
- RELEVANT - enum value to be set in the STMT_VINFO of the stmt
that defined USE. This is done by calling mark_relevant and passing it
the WORKLIST (to add DEF_STMT to the WORKLIST in case it is relevant).
@@ -441,37 +435,34 @@ exist_non_indexing_operands_for_use_p (tree use, gimple *stmt)
Outputs:
Generally, LIVE_P and RELEVANT are used to define the liveness and
relevance info of the DEF_STMT of this USE:
- STMT_VINFO_LIVE_P (DEF_STMT_info) <-- live_p
- STMT_VINFO_RELEVANT (DEF_STMT_info) <-- relevant
+ STMT_VINFO_LIVE_P (DEF_stmt_vinfo) <-- live_p
+ STMT_VINFO_RELEVANT (DEF_stmt_vinfo) <-- relevant
Exceptions:
- case 1: If USE is used only for address computations (e.g. array indexing),
which does not need to be directly vectorized, then the liveness/relevance
of the respective DEF_STMT is left unchanged.
- - case 2: If STMT is a reduction phi and DEF_STMT is a reduction stmt, we
- skip DEF_STMT cause it had already been processed.
- - case 3: If DEF_STMT and STMT are in different nests, then "relevant" will
- be modified accordingly.
+ - case 2: If STMT_VINFO is a reduction phi and DEF_STMT is a reduction stmt,
+ we skip DEF_STMT cause it had already been processed.
+ - case 3: If DEF_STMT and STMT_VINFO are in different nests, then
+ "relevant" will be modified accordingly.
Return true if everything is as expected. Return false otherwise. */
static bool
-process_use (gimple *stmt, tree use, loop_vec_info loop_vinfo,
- enum vect_relevant relevant, vec<gimple *> *worklist,
+process_use (stmt_vec_info stmt_vinfo, tree use, loop_vec_info loop_vinfo,
+ enum vect_relevant relevant, vec<stmt_vec_info> *worklist,
bool force)
{
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
- stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
stmt_vec_info dstmt_vinfo;
basic_block bb, def_bb;
- gimple *def_stmt;
enum vect_def_type dt;
/* case 1: we are only interested in uses that need to be vectorized. Uses
that are used for address computation are not considered relevant. */
- if (!force && !exist_non_indexing_operands_for_use_p (use, stmt))
+ if (!force && !exist_non_indexing_operands_for_use_p (use, stmt_vinfo))
return true;
- if (!vect_is_simple_use (use, loop_vinfo, &dt, &def_stmt))
+ if (!vect_is_simple_use (use, loop_vinfo, &dt, &dstmt_vinfo))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -479,27 +470,20 @@ process_use (gimple *stmt, tree use, loop_vec_info loop_vinfo,
return false;
}
- if (!def_stmt || gimple_nop_p (def_stmt))
+ if (!dstmt_vinfo)
return true;
- def_bb = gimple_bb (def_stmt);
- if (!flow_bb_inside_loop_p (loop, def_bb))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location, "def_stmt is out of loop.\n");
- return true;
- }
+ def_bb = gimple_bb (dstmt_vinfo->stmt);
- /* case 2: A reduction phi (STMT) defined by a reduction stmt (DEF_STMT).
- DEF_STMT must have already been processed, because this should be the
+ /* case 2: A reduction phi (STMT) defined by a reduction stmt (DSTMT_VINFO).
+ DSTMT_VINFO must have already been processed, because this should be the
only way that STMT, which is a reduction-phi, was put in the worklist,
- as there should be no other uses for DEF_STMT in the loop. So we just
+ as there should be no other uses for DSTMT_VINFO in the loop. So we just
check that everything is as expected, and we are done. */
- dstmt_vinfo = vinfo_for_stmt (def_stmt);
- bb = gimple_bb (stmt);
- if (gimple_code (stmt) == GIMPLE_PHI
+ bb = gimple_bb (stmt_vinfo->stmt);
+ if (gimple_code (stmt_vinfo->stmt) == GIMPLE_PHI
&& STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def
- && gimple_code (def_stmt) != GIMPLE_PHI
+ && gimple_code (dstmt_vinfo->stmt) != GIMPLE_PHI
&& STMT_VINFO_DEF_TYPE (dstmt_vinfo) == vect_reduction_def
&& bb->loop_father == def_bb->loop_father)
{
@@ -514,7 +498,7 @@ process_use (gimple *stmt, tree use, loop_vec_info loop_vinfo,
/* case 3a: outer-loop stmt defining an inner-loop stmt:
outer-loop-header-bb:
- d = def_stmt
+ d = dstmt_vinfo
inner-loop:
stmt # use (d)
outer-loop-tail-bb:
@@ -554,7 +538,7 @@ process_use (gimple *stmt, tree use, loop_vec_info loop_vinfo,
outer-loop-header-bb:
...
inner-loop:
- d = def_stmt
+ d = dstmt_vinfo
outer-loop-tail-bb (or outer-loop-exit-bb in double reduction):
stmt # use (d) */
else if (flow_loop_nested_p (bb->loop_father, def_bb->loop_father))
@@ -588,10 +572,11 @@ process_use (gimple *stmt, tree use, loop_vec_info loop_vinfo,
inductions. Otherwise we'll needlessly vectorize the IV increment
and cause hybrid SLP for SLP inductions. Unless the PHI is live
of course. */
- else if (gimple_code (stmt) == GIMPLE_PHI
+ else if (gimple_code (stmt_vinfo->stmt) == GIMPLE_PHI
&& STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_induction_def
&& ! STMT_VINFO_LIVE_P (stmt_vinfo)
- && (PHI_ARG_DEF_FROM_EDGE (stmt, loop_latch_edge (bb->loop_father))
+ && (PHI_ARG_DEF_FROM_EDGE (stmt_vinfo->stmt,
+ loop_latch_edge (bb->loop_father))
== use))
{
if (dump_enabled_p ())
@@ -601,7 +586,7 @@ process_use (gimple *stmt, tree use, loop_vec_info loop_vinfo,
}
- vect_mark_relevant (worklist, def_stmt, relevant, false);
+ vect_mark_relevant (worklist, dstmt_vinfo, relevant, false);
return true;
}
@@ -629,17 +614,14 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
unsigned int nbbs = loop->num_nodes;
gimple_stmt_iterator si;
- gimple *stmt;
unsigned int i;
- stmt_vec_info stmt_vinfo;
basic_block bb;
- gimple *phi;
bool live_p;
enum vect_relevant relevant;
DUMP_VECT_SCOPE ("vect_mark_stmts_to_be_vectorized");
- auto_vec<gimple *, 64> worklist;
+ auto_vec<stmt_vec_info, 64> worklist;
/* 1. Init worklist. */
for (i = 0; i < nbbs; i++)
@@ -647,27 +629,23 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
bb = bbs[i];
for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
{
- phi = gsi_stmt (si);
+ stmt_vec_info phi_info = loop_vinfo->lookup_stmt (gsi_stmt (si));
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "init: phi relevant? ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, phi, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "init: phi relevant? %G",
+ phi_info->stmt);
- if (vect_stmt_relevant_p (phi, loop_vinfo, &relevant, &live_p))
- vect_mark_relevant (&worklist, phi, relevant, live_p);
+ if (vect_stmt_relevant_p (phi_info, loop_vinfo, &relevant, &live_p))
+ vect_mark_relevant (&worklist, phi_info, relevant, live_p);
}
for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
{
- stmt = gsi_stmt (si);
+ stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si));
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "init: stmt relevant? ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "init: stmt relevant? %G", stmt_info->stmt);
- if (vect_stmt_relevant_p (stmt, loop_vinfo, &relevant, &live_p))
- vect_mark_relevant (&worklist, stmt, relevant, live_p);
+ if (vect_stmt_relevant_p (stmt_info, loop_vinfo, &relevant, &live_p))
+ vect_mark_relevant (&worklist, stmt_info, relevant, live_p);
}
}
@@ -677,17 +655,14 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
use_operand_p use_p;
ssa_op_iter iter;
- stmt = worklist.pop ();
+ stmt_vec_info stmt_vinfo = worklist.pop ();
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "worklist: examine stmt: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "worklist: examine stmt: %G", stmt_vinfo->stmt);
/* Examine the USEs of STMT. For each USE, mark the stmt that defines it
(DEF_STMT) as relevant/irrelevant according to the relevance property
of STMT. */
- stmt_vinfo = vinfo_for_stmt (stmt);
relevant = STMT_VINFO_RELEVANT (stmt_vinfo);
/* Generally, the relevance property of STMT (in STMT_VINFO_RELEVANT) is
@@ -752,46 +727,46 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
/* Pattern statements are not inserted into the code, so
FOR_EACH_PHI_OR_STMT_USE optimizes their operands out, and we
have to scan the RHS or function arguments instead. */
- if (is_gimple_assign (stmt))
- {
- enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
- tree op = gimple_assign_rhs1 (stmt);
+ if (gassign *assign = dyn_cast <gassign *> (stmt_vinfo->stmt))
+ {
+ enum tree_code rhs_code = gimple_assign_rhs_code (assign);
+ tree op = gimple_assign_rhs1 (assign);
i = 1;
if (rhs_code == COND_EXPR && COMPARISON_CLASS_P (op))
{
- if (!process_use (stmt, TREE_OPERAND (op, 0), loop_vinfo,
- relevant, &worklist, false)
- || !process_use (stmt, TREE_OPERAND (op, 1), loop_vinfo,
- relevant, &worklist, false))
+ if (!process_use (stmt_vinfo, TREE_OPERAND (op, 0),
+ loop_vinfo, relevant, &worklist, false)
+ || !process_use (stmt_vinfo, TREE_OPERAND (op, 1),
+ loop_vinfo, relevant, &worklist, false))
return false;
i = 2;
}
- for (; i < gimple_num_ops (stmt); i++)
- {
- op = gimple_op (stmt, i);
+ for (; i < gimple_num_ops (assign); i++)
+ {
+ op = gimple_op (assign, i);
if (TREE_CODE (op) == SSA_NAME
- && !process_use (stmt, op, loop_vinfo, relevant,
+ && !process_use (stmt_vinfo, op, loop_vinfo, relevant,
&worklist, false))
return false;
}
}
- else if (is_gimple_call (stmt))
- {
- for (i = 0; i < gimple_call_num_args (stmt); i++)
- {
- tree arg = gimple_call_arg (stmt, i);
- if (!process_use (stmt, arg, loop_vinfo, relevant,
+ else if (gcall *call = dyn_cast <gcall *> (stmt_vinfo->stmt))
+ {
+ for (i = 0; i < gimple_call_num_args (call); i++)
+ {
+ tree arg = gimple_call_arg (call, i);
+ if (!process_use (stmt_vinfo, arg, loop_vinfo, relevant,
&worklist, false))
return false;
- }
- }
+ }
+ }
}
else
- FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
+ FOR_EACH_PHI_OR_STMT_USE (use_p, stmt_vinfo->stmt, iter, SSA_OP_USE)
{
tree op = USE_FROM_PTR (use_p);
- if (!process_use (stmt, op, loop_vinfo, relevant,
+ if (!process_use (stmt_vinfo, op, loop_vinfo, relevant,
&worklist, false))
return false;
}
@@ -799,9 +774,9 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
if (STMT_VINFO_GATHER_SCATTER_P (stmt_vinfo))
{
gather_scatter_info gs_info;
- if (!vect_check_gather_scatter (stmt, loop_vinfo, &gs_info))
+ if (!vect_check_gather_scatter (stmt_vinfo, loop_vinfo, &gs_info))
gcc_unreachable ();
- if (!process_use (stmt, gs_info.offset, loop_vinfo, relevant,
+ if (!process_use (stmt_vinfo, gs_info.offset, loop_vinfo, relevant,
&worklist, true))
return false;
}
@@ -817,7 +792,7 @@ vect_prologue_cost_for_slp_op (slp_tree node, stmt_vec_info stmt_info,
unsigned opno, enum vect_def_type dt,
stmt_vector_for_cost *cost_vec)
{
- gimple *stmt = SLP_TREE_SCALAR_STMTS (node)[0];
+ gimple *stmt = SLP_TREE_SCALAR_STMTS (node)[0]->stmt;
tree op = gimple_op (stmt, opno);
unsigned prologue_cost = 0;
@@ -849,11 +824,11 @@ vect_prologue_cost_for_slp_op (slp_tree node, stmt_vec_info stmt_info,
{
unsigned si = j % group_size;
if (nelt == 0)
- elt = gimple_op (SLP_TREE_SCALAR_STMTS (node)[si], opno);
+ elt = gimple_op (SLP_TREE_SCALAR_STMTS (node)[si]->stmt, opno);
/* ??? We're just tracking whether all operands of a single
vector initializer are the same, ideally we'd check if
we emitted the same one already. */
- else if (elt != gimple_op (SLP_TREE_SCALAR_STMTS (node)[si],
+ else if (elt != gimple_op (SLP_TREE_SCALAR_STMTS (node)[si]->stmt,
opno))
elt = NULL_TREE;
nelt++;
@@ -900,7 +875,7 @@ vect_model_simple_cost (stmt_vec_info stmt_info, int ncopies,
/* Scan operands and account for prologue cost of constants/externals.
??? This over-estimates cost for multiple uses and should be
re-engineered. */
- gimple *stmt = SLP_TREE_SCALAR_STMTS (node)[0];
+ gimple *stmt = SLP_TREE_SCALAR_STMTS (node)[0]->stmt;
tree lhs = gimple_get_lhs (stmt);
for (unsigned i = 0; i < gimple_num_ops (stmt); ++i)
{
@@ -989,7 +964,7 @@ vect_model_store_cost (stmt_vec_info stmt_info, int ncopies,
stmt_vector_for_cost *cost_vec)
{
unsigned int inside_cost = 0, prologue_cost = 0;
- gimple *first_stmt = STMT_VINFO_STMT (stmt_info);
+ stmt_vec_info first_stmt_info = stmt_info;
bool grouped_access_p = STMT_VINFO_GROUPED_ACCESS (stmt_info);
/* ??? Somehow we need to fix this at the callers. */
@@ -1009,12 +984,12 @@ vect_model_store_cost (stmt_vec_info stmt_info, int ncopies,
/* Grouped stores update all elements in the group at once,
so we want the DR for the first statement. */
if (!slp_node && grouped_access_p)
- first_stmt = DR_GROUP_FIRST_ELEMENT (stmt_info);
+ first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
/* True if we should include any once-per-group costs as well as
the cost of the statement itself. For SLP we only get called
once per group anyhow. */
- bool first_stmt_p = (first_stmt == STMT_VINFO_STMT (stmt_info));
+ bool first_stmt_p = (first_stmt_info == stmt_info);
/* We assume that the cost of a single store-lanes instruction is
equivalent to the cost of DR_GROUP_SIZE separate stores. If a grouped
@@ -1025,7 +1000,7 @@ vect_model_store_cost (stmt_vec_info stmt_info, int ncopies,
{
/* Uses a high and low interleave or shuffle operations for each
needed permute. */
- int group_size = DR_GROUP_SIZE (vinfo_for_stmt (first_stmt));
+ int group_size = DR_GROUP_SIZE (first_stmt_info);
int nstmts = ncopies * ceil_log2 (group_size) * group_size;
inside_cost = record_stmt_cost (cost_vec, nstmts, vec_perm,
stmt_info, 0, vect_body);
@@ -1073,8 +1048,9 @@ vect_get_store_cost (stmt_vec_info stmt_info, int ncopies,
unsigned int *inside_cost,
stmt_vector_for_cost *body_cost_vec)
{
- struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
- int alignment_support_scheme = vect_supportable_dr_alignment (dr, false);
+ dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
+ int alignment_support_scheme
+ = vect_supportable_dr_alignment (dr_info, false);
switch (alignment_support_scheme)
{
@@ -1095,7 +1071,8 @@ vect_get_store_cost (stmt_vec_info stmt_info, int ncopies,
/* Here, we assign an additional cost for the unaligned store. */
*inside_cost += record_stmt_cost (body_cost_vec, ncopies,
unaligned_store, stmt_info,
- DR_MISALIGNMENT (dr), vect_body);
+ DR_MISALIGNMENT (dr_info),
+ vect_body);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"vect_model_store_cost: unaligned supported by "
@@ -1133,7 +1110,6 @@ vect_model_load_cost (stmt_vec_info stmt_info, unsigned ncopies,
slp_tree slp_node,
stmt_vector_for_cost *cost_vec)
{
- gimple *first_stmt = STMT_VINFO_STMT (stmt_info);
unsigned int inside_cost = 0, prologue_cost = 0;
bool grouped_access_p = STMT_VINFO_GROUPED_ACCESS (stmt_info);
@@ -1147,28 +1123,27 @@ vect_model_load_cost (stmt_vec_info stmt_info, unsigned ncopies,
{
/* If the load is permuted then the alignment is determined by
the first group element not by the first scalar stmt DR. */
- gimple *stmt = DR_GROUP_FIRST_ELEMENT (stmt_info);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ stmt_vec_info first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
/* Record the cost for the permutation. */
unsigned n_perms;
unsigned assumed_nunits
- = vect_nunits_for_cost (STMT_VINFO_VECTYPE (stmt_info));
+ = vect_nunits_for_cost (STMT_VINFO_VECTYPE (first_stmt_info));
unsigned slp_vf = (ncopies * assumed_nunits) / instance->group_size;
vect_transform_slp_perm_load (slp_node, vNULL, NULL,
slp_vf, instance, true,
&n_perms);
inside_cost += record_stmt_cost (cost_vec, n_perms, vec_perm,
- stmt_info, 0, vect_body);
+ first_stmt_info, 0, vect_body);
/* And adjust the number of loads performed. This handles
redundancies as well as loads that are later dead. */
- auto_sbitmap perm (DR_GROUP_SIZE (stmt_info));
+ auto_sbitmap perm (DR_GROUP_SIZE (first_stmt_info));
bitmap_clear (perm);
for (unsigned i = 0;
i < SLP_TREE_LOAD_PERMUTATION (slp_node).length (); ++i)
bitmap_set_bit (perm, SLP_TREE_LOAD_PERMUTATION (slp_node)[i]);
ncopies = 0;
bool load_seen = false;
- for (unsigned i = 0; i < DR_GROUP_SIZE (stmt_info); ++i)
+ for (unsigned i = 0; i < DR_GROUP_SIZE (first_stmt_info); ++i)
{
if (i % assumed_nunits == 0)
{
@@ -1182,19 +1157,21 @@ vect_model_load_cost (stmt_vec_info stmt_info, unsigned ncopies,
if (load_seen)
ncopies++;
gcc_assert (ncopies
- <= (DR_GROUP_SIZE (stmt_info) - DR_GROUP_GAP (stmt_info)
+ <= (DR_GROUP_SIZE (first_stmt_info)
+ - DR_GROUP_GAP (first_stmt_info)
+ assumed_nunits - 1) / assumed_nunits);
}
/* Grouped loads read all elements in the group at once,
so we want the DR for the first statement. */
+ stmt_vec_info first_stmt_info = stmt_info;
if (!slp_node && grouped_access_p)
- first_stmt = DR_GROUP_FIRST_ELEMENT (stmt_info);
+ first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
/* True if we should include any once-per-group costs as well as
the cost of the statement itself. For SLP we only get called
once per group anyhow. */
- bool first_stmt_p = (first_stmt == STMT_VINFO_STMT (stmt_info));
+ bool first_stmt_p = (first_stmt_info == stmt_info);
/* We assume that the cost of a single load-lanes instruction is
equivalent to the cost of DR_GROUP_SIZE separate loads. If a grouped
@@ -1205,7 +1182,7 @@ vect_model_load_cost (stmt_vec_info stmt_info, unsigned ncopies,
{
/* Uses an even and odd extract operations or shuffle operations
for each needed permute. */
- int group_size = DR_GROUP_SIZE (vinfo_for_stmt (first_stmt));
+ int group_size = DR_GROUP_SIZE (first_stmt_info);
int nstmts = ncopies * ceil_log2 (group_size) * group_size;
inside_cost += record_stmt_cost (cost_vec, nstmts, vec_perm,
stmt_info, 0, vect_body);
@@ -1252,8 +1229,9 @@ vect_get_load_cost (stmt_vec_info stmt_info, int ncopies,
stmt_vector_for_cost *body_cost_vec,
bool record_prologue_costs)
{
- data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
- int alignment_support_scheme = vect_supportable_dr_alignment (dr, false);
+ dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
+ int alignment_support_scheme
+ = vect_supportable_dr_alignment (dr_info, false);
switch (alignment_support_scheme)
{
@@ -1273,7 +1251,8 @@ vect_get_load_cost (stmt_vec_info stmt_info, int ncopies,
/* Here, we assign an additional cost for the unaligned load. */
*inside_cost += record_stmt_cost (body_cost_vec, ncopies,
unaligned_load, stmt_info,
- DR_MISALIGNMENT (dr), vect_body);
+ DR_MISALIGNMENT (dr_info),
+ vect_body);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
@@ -1356,16 +1335,16 @@ vect_get_load_cost (stmt_vec_info stmt_info, int ncopies,
}
/* Insert the new stmt NEW_STMT at *GSI or at the appropriate place in
- the loop preheader for the vectorized stmt STMT. */
+ the loop preheader for the vectorized stmt STMT_VINFO. */
static void
-vect_init_vector_1 (gimple *stmt, gimple *new_stmt, gimple_stmt_iterator *gsi)
+vect_init_vector_1 (stmt_vec_info stmt_vinfo, gimple *new_stmt,
+ gimple_stmt_iterator *gsi)
{
if (gsi)
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ vect_finish_stmt_generation (stmt_vinfo, new_stmt, gsi);
else
{
- stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
if (loop_vinfo)
@@ -1374,8 +1353,8 @@ vect_init_vector_1 (gimple *stmt, gimple *new_stmt, gimple_stmt_iterator *gsi)
basic_block new_bb;
edge pe;
- if (nested_in_vect_loop_p (loop, stmt))
- loop = loop->inner;
+ if (nested_in_vect_loop_p (loop, stmt_vinfo))
+ loop = loop->inner;
pe = loop_preheader_edge (loop);
new_bb = gsi_insert_on_edge_immediate (pe, new_stmt);
@@ -1395,11 +1374,8 @@ vect_init_vector_1 (gimple *stmt, gimple *new_stmt, gimple_stmt_iterator *gsi)
}
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "created new init_stmt: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, new_stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "created new init_stmt: %G", new_stmt);
}
/* Function vect_init_vector.
@@ -1410,10 +1386,11 @@ vect_init_vector_1 (gimple *stmt, gimple *new_stmt, gimple_stmt_iterator *gsi)
Place the initialization at BSI if it is not NULL. Otherwise, place the
initialization at the loop preheader.
Return the DEF of INIT_STMT.
- It will be used in the vectorization of STMT. */
+ It will be used in the vectorization of STMT_INFO. */
tree
-vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
+vect_init_vector (stmt_vec_info stmt_info, tree val, tree type,
+ gimple_stmt_iterator *gsi)
{
gimple *init_stmt;
tree new_temp;
@@ -1438,7 +1415,7 @@ vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
new_temp = make_ssa_name (TREE_TYPE (type));
init_stmt = gimple_build_assign (new_temp, COND_EXPR,
val, true_val, false_val);
- vect_init_vector_1 (stmt, init_stmt, gsi);
+ vect_init_vector_1 (stmt_info, init_stmt, gsi);
val = new_temp;
}
}
@@ -1454,7 +1431,7 @@ vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
val));
else
init_stmt = gimple_build_assign (new_temp, NOP_EXPR, val);
- vect_init_vector_1 (stmt, init_stmt, gsi);
+ vect_init_vector_1 (stmt_info, init_stmt, gsi);
val = new_temp;
}
}
@@ -1463,21 +1440,21 @@ vect_init_vector (gimple *stmt, tree val, tree type, gimple_stmt_iterator *gsi)
new_temp = vect_get_new_ssa_name (type, vect_simple_var, "cst_");
init_stmt = gimple_build_assign (new_temp, val);
- vect_init_vector_1 (stmt, init_stmt, gsi);
+ vect_init_vector_1 (stmt_info, init_stmt, gsi);
return new_temp;
}
/* Function vect_get_vec_def_for_operand_1.
- For a defining stmt DEF_STMT of a scalar stmt, return a vector def with type
- DT that will be used in the vectorized stmt. */
+ For a defining stmt DEF_STMT_INFO of a scalar stmt, return a vector def
+ with type DT that will be used in the vectorized stmt. */
tree
-vect_get_vec_def_for_operand_1 (gimple *def_stmt, enum vect_def_type dt)
+vect_get_vec_def_for_operand_1 (stmt_vec_info def_stmt_info,
+ enum vect_def_type dt)
{
tree vec_oprnd;
- gimple *vec_stmt;
- stmt_vec_info def_stmt_info = NULL;
+ stmt_vec_info vec_stmt_info;
switch (dt)
{
@@ -1491,23 +1468,19 @@ vect_get_vec_def_for_operand_1 (gimple *def_stmt, enum vect_def_type dt)
case vect_internal_def:
{
/* Get the def from the vectorized stmt. */
- def_stmt_info = vinfo_for_stmt (def_stmt);
-
- vec_stmt = STMT_VINFO_VEC_STMT (def_stmt_info);
- /* Get vectorized pattern statement. */
- if (!vec_stmt
- && STMT_VINFO_IN_PATTERN_P (def_stmt_info)
- && !STMT_VINFO_RELEVANT (def_stmt_info))
- vec_stmt = STMT_VINFO_VEC_STMT (vinfo_for_stmt (
- STMT_VINFO_RELATED_STMT (def_stmt_info)));
- gcc_assert (vec_stmt);
- if (gimple_code (vec_stmt) == GIMPLE_PHI)
- vec_oprnd = PHI_RESULT (vec_stmt);
- else if (is_gimple_call (vec_stmt))
- vec_oprnd = gimple_call_lhs (vec_stmt);
+ vec_stmt_info = STMT_VINFO_VEC_STMT (def_stmt_info);
+ /* Get vectorized pattern statement. */
+ if (!vec_stmt_info
+ && STMT_VINFO_IN_PATTERN_P (def_stmt_info)
+ && !STMT_VINFO_RELEVANT (def_stmt_info))
+ vec_stmt_info = (STMT_VINFO_VEC_STMT
+ (STMT_VINFO_RELATED_STMT (def_stmt_info)));
+ gcc_assert (vec_stmt_info);
+ if (gphi *phi = dyn_cast <gphi *> (vec_stmt_info->stmt))
+ vec_oprnd = PHI_RESULT (phi);
else
- vec_oprnd = gimple_assign_lhs (vec_stmt);
- return vec_oprnd;
+ vec_oprnd = gimple_get_lhs (vec_stmt_info->stmt);
+ return vec_oprnd;
}
/* operand is defined by a loop header phi. */
@@ -1516,16 +1489,15 @@ vect_get_vec_def_for_operand_1 (gimple *def_stmt, enum vect_def_type dt)
case vect_nested_cycle:
case vect_induction_def:
{
- gcc_assert (gimple_code (def_stmt) == GIMPLE_PHI);
+ gcc_assert (gimple_code (def_stmt_info->stmt) == GIMPLE_PHI);
- /* Get the def from the vectorized stmt. */
- def_stmt_info = vinfo_for_stmt (def_stmt);
- vec_stmt = STMT_VINFO_VEC_STMT (def_stmt_info);
- if (gimple_code (vec_stmt) == GIMPLE_PHI)
- vec_oprnd = PHI_RESULT (vec_stmt);
+ /* Get the def from the vectorized stmt. */
+ vec_stmt_info = STMT_VINFO_VEC_STMT (def_stmt_info);
+ if (gphi *phi = dyn_cast <gphi *> (vec_stmt_info->stmt))
+ vec_oprnd = PHI_RESULT (phi);
else
- vec_oprnd = gimple_get_lhs (vec_stmt);
- return vec_oprnd;
+ vec_oprnd = gimple_get_lhs (vec_stmt_info->stmt);
+ return vec_oprnd;
}
default:
@@ -1536,8 +1508,8 @@ vect_get_vec_def_for_operand_1 (gimple *def_stmt, enum vect_def_type dt)
/* Function vect_get_vec_def_for_operand.
- OP is an operand in STMT. This function returns a (vector) def that will be
- used in the vectorized stmt for STMT.
+ OP is an operand in STMT_VINFO. This function returns a (vector) def
+ that will be used in the vectorized stmt for STMT_VINFO.
In the case that OP is an SSA_NAME which is defined in the loop, then
STMT_VINFO_VEC_STMT of the defining stmt holds the relevant def.
@@ -1547,29 +1519,23 @@ vect_get_vec_def_for_operand_1 (gimple *def_stmt, enum vect_def_type dt)
vector invariant. */
tree
-vect_get_vec_def_for_operand (tree op, gimple *stmt, tree vectype)
+vect_get_vec_def_for_operand (tree op, stmt_vec_info stmt_vinfo, tree vectype)
{
gimple *def_stmt;
enum vect_def_type dt;
bool is_simple_use;
- stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "vect_get_vec_def_for_operand: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, op);
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "vect_get_vec_def_for_operand: %T\n", op);
- is_simple_use = vect_is_simple_use (op, loop_vinfo, &dt, &def_stmt);
+ stmt_vec_info def_stmt_info;
+ is_simple_use = vect_is_simple_use (op, loop_vinfo, &dt,
+ &def_stmt_info, &def_stmt);
gcc_assert (is_simple_use);
if (def_stmt && dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, " def_stmt = ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, def_stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location, " def_stmt = %G", def_stmt);
if (dt == vect_constant_def || dt == vect_external_def)
{
@@ -1585,10 +1551,10 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt, tree vectype)
vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
gcc_assert (vector_type);
- return vect_init_vector (stmt, op, vector_type, NULL);
+ return vect_init_vector (stmt_vinfo, op, vector_type, NULL);
}
else
- return vect_get_vec_def_for_operand_1 (def_stmt, dt);
+ return vect_get_vec_def_for_operand_1 (def_stmt_info, dt);
}
@@ -1599,8 +1565,7 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt, tree vectype)
created in case the vectorized result cannot fit in one vector, and several
copies of the vector-stmt are required. In this case the vector-def is
retrieved from the vector stmt recorded in the STMT_VINFO_RELATED_STMT field
- of the stmt that defines VEC_OPRND.
- DT is the type of the vector def VEC_OPRND.
+ of the stmt that defines VEC_OPRND. VINFO describes the vectorization.
Context:
In case the vectorization factor (VF) is bigger than the number
@@ -1644,29 +1609,24 @@ vect_get_vec_def_for_operand (tree op, gimple *stmt, tree vectype)
STMT_VINFO_RELATED_STMT field of 'VS1.0' we obtain the next copy - 'VS1.1',
and return its def ('vx.1').
Overall, to create the above sequence this function will be called 3 times:
- vx.1 = vect_get_vec_def_for_stmt_copy (dt, vx.0);
- vx.2 = vect_get_vec_def_for_stmt_copy (dt, vx.1);
- vx.3 = vect_get_vec_def_for_stmt_copy (dt, vx.2); */
+ vx.1 = vect_get_vec_def_for_stmt_copy (vinfo, vx.0);
+ vx.2 = vect_get_vec_def_for_stmt_copy (vinfo, vx.1);
+ vx.3 = vect_get_vec_def_for_stmt_copy (vinfo, vx.2); */
tree
-vect_get_vec_def_for_stmt_copy (enum vect_def_type dt, tree vec_oprnd)
+vect_get_vec_def_for_stmt_copy (vec_info *vinfo, tree vec_oprnd)
{
- gimple *vec_stmt_for_operand;
- stmt_vec_info def_stmt_info;
-
- /* Do nothing; can reuse same def. */
- if (dt == vect_external_def || dt == vect_constant_def )
+ stmt_vec_info def_stmt_info = vinfo->lookup_def (vec_oprnd);
+ if (!def_stmt_info)
+ /* Do nothing; can reuse same def. */
return vec_oprnd;
- vec_stmt_for_operand = SSA_NAME_DEF_STMT (vec_oprnd);
- def_stmt_info = vinfo_for_stmt (vec_stmt_for_operand);
+ def_stmt_info = STMT_VINFO_RELATED_STMT (def_stmt_info);
gcc_assert (def_stmt_info);
- vec_stmt_for_operand = STMT_VINFO_RELATED_STMT (def_stmt_info);
- gcc_assert (vec_stmt_for_operand);
- if (gimple_code (vec_stmt_for_operand) == GIMPLE_PHI)
- vec_oprnd = PHI_RESULT (vec_stmt_for_operand);
+ if (gphi *phi = dyn_cast <gphi *> (def_stmt_info->stmt))
+ vec_oprnd = PHI_RESULT (phi);
else
- vec_oprnd = gimple_get_lhs (vec_stmt_for_operand);
+ vec_oprnd = gimple_get_lhs (def_stmt_info->stmt);
return vec_oprnd;
}
@@ -1675,19 +1635,19 @@ vect_get_vec_def_for_stmt_copy (enum vect_def_type dt, tree vec_oprnd)
stmt. See vect_get_vec_def_for_stmt_copy () for details. */
void
-vect_get_vec_defs_for_stmt_copy (enum vect_def_type *dt,
+vect_get_vec_defs_for_stmt_copy (vec_info *vinfo,
vec<tree> *vec_oprnds0,
vec<tree> *vec_oprnds1)
{
tree vec_oprnd = vec_oprnds0->pop ();
- vec_oprnd = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd);
+ vec_oprnd = vect_get_vec_def_for_stmt_copy (vinfo, vec_oprnd);
vec_oprnds0->quick_push (vec_oprnd);
if (vec_oprnds1 && vec_oprnds1->length ())
{
vec_oprnd = vec_oprnds1->pop ();
- vec_oprnd = vect_get_vec_def_for_stmt_copy (dt[1], vec_oprnd);
+ vec_oprnd = vect_get_vec_def_for_stmt_copy (vinfo, vec_oprnd);
vec_oprnds1->quick_push (vec_oprnd);
}
}
@@ -1696,7 +1656,7 @@ vect_get_vec_defs_for_stmt_copy (enum vect_def_type *dt,
/* Get vectorized definitions for OP0 and OP1. */
void
-vect_get_vec_defs (tree op0, tree op1, gimple *stmt,
+vect_get_vec_defs (tree op0, tree op1, stmt_vec_info stmt_info,
vec<tree> *vec_oprnds0,
vec<tree> *vec_oprnds1,
slp_tree slp_node)
@@ -1722,13 +1682,13 @@ vect_get_vec_defs (tree op0, tree op1, gimple *stmt,
tree vec_oprnd;
vec_oprnds0->create (1);
- vec_oprnd = vect_get_vec_def_for_operand (op0, stmt);
+ vec_oprnd = vect_get_vec_def_for_operand (op0, stmt_info);
vec_oprnds0->quick_push (vec_oprnd);
if (op1)
{
vec_oprnds1->create (1);
- vec_oprnd = vect_get_vec_def_for_operand (op1, stmt);
+ vec_oprnd = vect_get_vec_def_for_operand (op1, stmt_info);
vec_oprnds1->quick_push (vec_oprnd);
}
}
@@ -1736,55 +1696,53 @@ vect_get_vec_defs (tree op0, tree op1, gimple *stmt,
/* Helper function called by vect_finish_replace_stmt and
vect_finish_stmt_generation. Set the location of the new
- statement and create a stmt_vec_info for it. */
+ statement and create and return a stmt_vec_info for it. */
-static void
-vect_finish_stmt_generation_1 (gimple *stmt, gimple *vec_stmt)
+static stmt_vec_info
+vect_finish_stmt_generation_1 (stmt_vec_info stmt_info, gimple *vec_stmt)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
vec_info *vinfo = stmt_info->vinfo;
- set_vinfo_for_stmt (vec_stmt, new_stmt_vec_info (vec_stmt, vinfo));
+ stmt_vec_info vec_stmt_info = vinfo->add_stmt (vec_stmt);
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "add new stmt: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, vec_stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "add new stmt: %G", vec_stmt);
- gimple_set_location (vec_stmt, gimple_location (stmt));
+ gimple_set_location (vec_stmt, gimple_location (stmt_info->stmt));
/* While EH edges will generally prevent vectorization, stmt might
e.g. be in a must-not-throw region. Ensure newly created stmts
that could throw are part of the same region. */
- int lp_nr = lookup_stmt_eh_lp (stmt);
+ int lp_nr = lookup_stmt_eh_lp (stmt_info->stmt);
if (lp_nr != 0 && stmt_could_throw_p (vec_stmt))
add_stmt_to_eh_lp (vec_stmt, lp_nr);
+
+ return vec_stmt_info;
}
-/* Replace the scalar statement STMT with a new vector statement VEC_STMT,
- which sets the same scalar result as STMT did. */
+/* Replace the scalar statement STMT_INFO with a new vector statement VEC_STMT,
+ which sets the same scalar result as STMT_INFO did. Create and return a
+ stmt_vec_info for VEC_STMT. */
-void
-vect_finish_replace_stmt (gimple *stmt, gimple *vec_stmt)
+stmt_vec_info
+vect_finish_replace_stmt (stmt_vec_info stmt_info, gimple *vec_stmt)
{
- gcc_assert (gimple_get_lhs (stmt) == gimple_get_lhs (vec_stmt));
+ gcc_assert (gimple_get_lhs (stmt_info->stmt) == gimple_get_lhs (vec_stmt));
- gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+ gimple_stmt_iterator gsi = gsi_for_stmt (stmt_info->stmt);
gsi_replace (&gsi, vec_stmt, false);
- vect_finish_stmt_generation_1 (stmt, vec_stmt);
+ return vect_finish_stmt_generation_1 (stmt_info, vec_stmt);
}
-/* Function vect_finish_stmt_generation.
-
- Insert a new stmt. */
+/* Add VEC_STMT to the vectorized implementation of STMT_INFO and insert it
+ before *GSI. Create and return a stmt_vec_info for VEC_STMT. */
-void
-vect_finish_stmt_generation (gimple *stmt, gimple *vec_stmt,
+stmt_vec_info
+vect_finish_stmt_generation (stmt_vec_info stmt_info, gimple *vec_stmt,
gimple_stmt_iterator *gsi)
{
- gcc_assert (gimple_code (stmt) != GIMPLE_LABEL);
+ gcc_assert (gimple_code (stmt_info->stmt) != GIMPLE_LABEL);
if (!gsi_end_p (*gsi)
&& gimple_has_mem_ops (vec_stmt))
@@ -1813,7 +1771,7 @@ vect_finish_stmt_generation (gimple *stmt, gimple *vec_stmt,
}
}
gsi_insert_before (gsi, vec_stmt, GSI_SAME_STMT);
- vect_finish_stmt_generation_1 (stmt, vec_stmt);
+ return vect_finish_stmt_generation_1 (stmt_info, vec_stmt);
}
/* We want to vectorize a call to combined function CFN with function
@@ -1846,7 +1804,7 @@ vectorizable_internal_function (combined_fn cfn, tree fndecl,
}
-static tree permute_vec_elements (tree, tree, tree, gimple *,
+static tree permute_vec_elements (tree, tree, tree, stmt_vec_info,
gimple_stmt_iterator *);
/* Check whether a load or store statement in the loop described by
@@ -1984,23 +1942,23 @@ prepare_load_store_mask (tree mask_type, tree loop_mask, tree vec_mask,
}
/* Determine whether we can use a gather load or scatter store to vectorize
- strided load or store STMT by truncating the current offset to a smaller
- width. We need to be able to construct an offset vector:
+ strided load or store STMT_INFO by truncating the current offset to a
+ smaller width. We need to be able to construct an offset vector:
{ 0, X, X*2, X*3, ... }
- without loss of precision, where X is STMT's DR_STEP.
+ without loss of precision, where X is STMT_INFO's DR_STEP.
Return true if this is possible, describing the gather load or scatter
store in GS_INFO. MASKED_P is true if the load or store is conditional. */
static bool
-vect_truncate_gather_scatter_offset (gimple *stmt, loop_vec_info loop_vinfo,
- bool masked_p,
+vect_truncate_gather_scatter_offset (stmt_vec_info stmt_info,
+ loop_vec_info loop_vinfo, bool masked_p,
gather_scatter_info *gs_info)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
- data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
+ dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
+ data_reference *dr = dr_info->dr;
tree step = DR_STEP (dr);
if (TREE_CODE (step) != INTEGER_CST)
{
@@ -2028,7 +1986,7 @@ vect_truncate_gather_scatter_offset (gimple *stmt, loop_vec_info loop_vinfo,
count = max_iters.to_shwi ();
/* Try scales of 1 and the element size. */
- int scales[] = { 1, vect_get_scalar_dr_size (dr) };
+ int scales[] = { 1, vect_get_scalar_dr_size (dr_info) };
wi::overflow_type overflow = wi::OVF_NONE;
for (int i = 0; i < 2; ++i)
{
@@ -2080,19 +2038,19 @@ vect_truncate_gather_scatter_offset (gimple *stmt, loop_vec_info loop_vinfo,
}
/* Return true if we can use gather/scatter internal functions to
- vectorize STMT, which is a grouped or strided load or store.
+ vectorize STMT_INFO, which is a grouped or strided load or store.
MASKED_P is true if load or store is conditional. When returning
true, fill in GS_INFO with the information required to perform the
operation. */
static bool
-vect_use_strided_gather_scatters_p (gimple *stmt, loop_vec_info loop_vinfo,
- bool masked_p,
+vect_use_strided_gather_scatters_p (stmt_vec_info stmt_info,
+ loop_vec_info loop_vinfo, bool masked_p,
gather_scatter_info *gs_info)
{
- if (!vect_check_gather_scatter (stmt, loop_vinfo, gs_info)
+ if (!vect_check_gather_scatter (stmt_info, loop_vinfo, gs_info)
|| gs_info->decl)
- return vect_truncate_gather_scatter_offset (stmt, loop_vinfo,
+ return vect_truncate_gather_scatter_offset (stmt_info, loop_vinfo,
masked_p, gs_info);
scalar_mode element_mode = SCALAR_TYPE_MODE (gs_info->element_type);
@@ -2120,16 +2078,15 @@ vect_use_strided_gather_scatters_p (gimple *stmt, loop_vec_info loop_vinfo,
return true;
}
-/* STMT is a non-strided load or store, meaning that it accesses
+/* STMT_INFO is a non-strided load or store, meaning that it accesses
elements with a known constant step. Return -1 if that step
is negative, 0 if it is zero, and 1 if it is greater than zero. */
static int
-compare_step_with_zero (gimple *stmt)
+compare_step_with_zero (stmt_vec_info stmt_info)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
- data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
- return tree_int_cst_compare (vect_dr_behavior (dr)->step,
+ dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
+ return tree_int_cst_compare (vect_dr_behavior (dr_info)->step,
size_zero_node);
}
@@ -2152,29 +2109,29 @@ perm_mask_for_reverse (tree vectype)
return vect_gen_perm_mask_checked (vectype, indices);
}
-/* STMT is either a masked or unconditional store. Return the value
+/* STMT_INFO is either a masked or unconditional store. Return the value
being stored. */
tree
-vect_get_store_rhs (gimple *stmt)
+vect_get_store_rhs (stmt_vec_info stmt_info)
{
- if (gassign *assign = dyn_cast <gassign *> (stmt))
+ if (gassign *assign = dyn_cast <gassign *> (stmt_info->stmt))
{
gcc_assert (gimple_assign_single_p (assign));
return gimple_assign_rhs1 (assign);
}
- if (gcall *call = dyn_cast <gcall *> (stmt))
+ if (gcall *call = dyn_cast <gcall *> (stmt_info->stmt))
{
internal_fn ifn = gimple_call_internal_fn (call);
int index = internal_fn_stored_value_index (ifn);
gcc_assert (index >= 0);
- return gimple_call_arg (stmt, index);
+ return gimple_call_arg (call, index);
}
gcc_unreachable ();
}
/* A subroutine of get_load_store_type, with a subset of the same
- arguments. Handle the case where STMT is part of a grouped load
+ arguments. Handle the case where STMT_INFO is part of a grouped load
or store.
For stores, the statements in the group are all consecutive
@@ -2183,21 +2140,20 @@ vect_get_store_rhs (gimple *stmt)
as well as at the end. */
static bool
-get_group_load_store_type (gimple *stmt, tree vectype, bool slp,
+get_group_load_store_type (stmt_vec_info stmt_info, tree vectype, bool slp,
bool masked_p, vec_load_store_type vls_type,
vect_memory_access_type *memory_access_type,
gather_scatter_info *gs_info)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
vec_info *vinfo = stmt_info->vinfo;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
struct loop *loop = loop_vinfo ? LOOP_VINFO_LOOP (loop_vinfo) : NULL;
- gimple *first_stmt = DR_GROUP_FIRST_ELEMENT (stmt_info);
- data_reference *first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
- unsigned int group_size = DR_GROUP_SIZE (vinfo_for_stmt (first_stmt));
- bool single_element_p = (stmt == first_stmt
+ stmt_vec_info first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
+ dr_vec_info *first_dr_info = STMT_VINFO_DR_INFO (first_stmt_info);
+ unsigned int group_size = DR_GROUP_SIZE (first_stmt_info);
+ bool single_element_p = (stmt_info == first_stmt_info
&& !DR_GROUP_NEXT_ELEMENT (stmt_info));
- unsigned HOST_WIDE_INT gap = DR_GROUP_GAP (vinfo_for_stmt (first_stmt));
+ unsigned HOST_WIDE_INT gap = DR_GROUP_GAP (first_stmt_info);
poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
/* True if the vectorized statements would access beyond the last
@@ -2213,14 +2169,14 @@ get_group_load_store_type (gimple *stmt, tree vectype, bool slp,
/* There can only be a gap at the end of the group if the stride is
known at compile time. */
- gcc_assert (!STMT_VINFO_STRIDED_P (stmt_info) || gap == 0);
+ gcc_assert (!STMT_VINFO_STRIDED_P (first_stmt_info) || gap == 0);
/* Stores can't yet have gaps. */
gcc_assert (slp || vls_type == VLS_LOAD || gap == 0);
if (slp)
{
- if (STMT_VINFO_STRIDED_P (stmt_info))
+ if (STMT_VINFO_STRIDED_P (first_stmt_info))
{
/* Try to use consecutive accesses of DR_GROUP_SIZE elements,
separated by the stride, until we have a complete vector.
@@ -2245,8 +2201,8 @@ get_group_load_store_type (gimple *stmt, tree vectype, bool slp,
be a multiple of B and so we are guaranteed to access a
non-gap element in the same B-sized block. */
if (overrun_p
- && gap < (vect_known_alignment_in_bytes (first_dr)
- / vect_get_scalar_dr_size (first_dr)))
+ && gap < (vect_known_alignment_in_bytes (first_dr_info)
+ / vect_get_scalar_dr_size (first_dr_info)))
overrun_p = false;
if (overrun_p && !can_overrun_p)
{
@@ -2273,13 +2229,13 @@ get_group_load_store_type (gimple *stmt, tree vectype, bool slp,
same B-sized block. */
if (would_overrun_p
&& !masked_p
- && gap < (vect_known_alignment_in_bytes (first_dr)
- / vect_get_scalar_dr_size (first_dr)))
+ && gap < (vect_known_alignment_in_bytes (first_dr_info)
+ / vect_get_scalar_dr_size (first_dr_info)))
would_overrun_p = false;
- if (!STMT_VINFO_STRIDED_P (stmt_info)
+ if (!STMT_VINFO_STRIDED_P (first_stmt_info)
&& (can_overrun_p || !would_overrun_p)
- && compare_step_with_zero (stmt) > 0)
+ && compare_step_with_zero (stmt_info) > 0)
{
/* First cope with the degenerate case of a single-element
vector. */
@@ -2319,19 +2275,19 @@ get_group_load_store_type (gimple *stmt, tree vectype, bool slp,
if (*memory_access_type == VMAT_ELEMENTWISE
&& single_element_p
&& loop_vinfo
- && vect_use_strided_gather_scatters_p (stmt, loop_vinfo,
+ && vect_use_strided_gather_scatters_p (stmt_info, loop_vinfo,
masked_p, gs_info))
*memory_access_type = VMAT_GATHER_SCATTER;
}
- if (vls_type != VLS_LOAD && first_stmt == stmt)
+ if (vls_type != VLS_LOAD && first_stmt_info == stmt_info)
{
/* STMT is the leader of the group. Check the operands of all the
stmts of the group. */
- gimple *next_stmt = DR_GROUP_NEXT_ELEMENT (stmt_info);
- while (next_stmt)
+ stmt_vec_info next_stmt_info = DR_GROUP_NEXT_ELEMENT (stmt_info);
+ while (next_stmt_info)
{
- tree op = vect_get_store_rhs (next_stmt);
+ tree op = vect_get_store_rhs (next_stmt_info);
enum vect_def_type dt;
if (!vect_is_simple_use (op, vinfo, &dt))
{
@@ -2340,7 +2296,7 @@ get_group_load_store_type (gimple *stmt, tree vectype, bool slp,
"use not simple.\n");
return false;
}
- next_stmt = DR_GROUP_NEXT_ELEMENT (vinfo_for_stmt (next_stmt));
+ next_stmt_info = DR_GROUP_NEXT_ELEMENT (next_stmt_info);
}
}
@@ -2358,16 +2314,15 @@ get_group_load_store_type (gimple *stmt, tree vectype, bool slp,
}
/* A subroutine of get_load_store_type, with a subset of the same
- arguments. Handle the case where STMT is a load or store that
+ arguments. Handle the case where STMT_INFO is a load or store that
accesses consecutive elements with a negative step. */
static vect_memory_access_type
-get_negative_load_store_type (gimple *stmt, tree vectype,
+get_negative_load_store_type (stmt_vec_info stmt_info, tree vectype,
vec_load_store_type vls_type,
unsigned int ncopies)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
- struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
+ dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
dr_alignment_support alignment_support_scheme;
if (ncopies > 1)
@@ -2378,7 +2333,7 @@ get_negative_load_store_type (gimple *stmt, tree vectype,
return VMAT_ELEMENTWISE;
}
- alignment_support_scheme = vect_supportable_dr_alignment (dr, false);
+ alignment_support_scheme = vect_supportable_dr_alignment (dr_info, false);
if (alignment_support_scheme != dr_aligned
&& alignment_support_scheme != dr_unaligned_supported)
{
@@ -2408,7 +2363,7 @@ get_negative_load_store_type (gimple *stmt, tree vectype,
return VMAT_CONTIGUOUS_REVERSE;
}
-/* Analyze load or store statement STMT of type VLS_TYPE. Return true
+/* Analyze load or store statement STMT_INFO of type VLS_TYPE. Return true
if there is a memory access type that the vectorized form can use,
storing it in *MEMORY_ACCESS_TYPE if so. If we decide to use gathers
or scatters, fill in GS_INFO accordingly.
@@ -2419,19 +2374,19 @@ get_negative_load_store_type (gimple *stmt, tree vectype,
NCOPIES is the number of vector statements that will be needed. */
static bool
-get_load_store_type (gimple *stmt, tree vectype, bool slp, bool masked_p,
- vec_load_store_type vls_type, unsigned int ncopies,
+get_load_store_type (stmt_vec_info stmt_info, tree vectype, bool slp,
+ bool masked_p, vec_load_store_type vls_type,
+ unsigned int ncopies,
vect_memory_access_type *memory_access_type,
gather_scatter_info *gs_info)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
vec_info *vinfo = stmt_info->vinfo;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
{
*memory_access_type = VMAT_GATHER_SCATTER;
- if (!vect_check_gather_scatter (stmt, loop_vinfo, gs_info))
+ if (!vect_check_gather_scatter (stmt_info, loop_vinfo, gs_info))
gcc_unreachable ();
else if (!vect_is_simple_use (gs_info->offset, vinfo,
&gs_info->offset_dt,
@@ -2446,15 +2401,15 @@ get_load_store_type (gimple *stmt, tree vectype, bool slp, bool masked_p,
}
else if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
{
- if (!get_group_load_store_type (stmt, vectype, slp, masked_p, vls_type,
- memory_access_type, gs_info))
+ if (!get_group_load_store_type (stmt_info, vectype, slp, masked_p,
+ vls_type, memory_access_type, gs_info))
return false;
}
else if (STMT_VINFO_STRIDED_P (stmt_info))
{
gcc_assert (!slp);
if (loop_vinfo
- && vect_use_strided_gather_scatters_p (stmt, loop_vinfo,
+ && vect_use_strided_gather_scatters_p (stmt_info, loop_vinfo,
masked_p, gs_info))
*memory_access_type = VMAT_GATHER_SCATTER;
else
@@ -2462,10 +2417,10 @@ get_load_store_type (gimple *stmt, tree vectype, bool slp, bool masked_p,
}
else
{
- int cmp = compare_step_with_zero (stmt);
+ int cmp = compare_step_with_zero (stmt_info);
if (cmp < 0)
*memory_access_type = get_negative_load_store_type
- (stmt, vectype, vls_type, ncopies);
+ (stmt_info, vectype, vls_type, ncopies);
else if (cmp == 0)
{
gcc_assert (vls_type == VLS_LOAD);
@@ -2489,9 +2444,12 @@ get_load_store_type (gimple *stmt, tree vectype, bool slp, bool masked_p,
/* FIXME: At the moment the cost model seems to underestimate the
cost of using elementwise accesses. This check preserves the
traditional behavior until that can be fixed. */
+ stmt_vec_info first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
+ if (!first_stmt_info)
+ first_stmt_info = stmt_info;
if (*memory_access_type == VMAT_ELEMENTWISE
- && !STMT_VINFO_STRIDED_P (stmt_info)
- && !(stmt == DR_GROUP_FIRST_ELEMENT (stmt_info)
+ && !STMT_VINFO_STRIDED_P (first_stmt_info)
+ && !(stmt_info == DR_GROUP_FIRST_ELEMENT (stmt_info)
&& !DR_GROUP_NEXT_ELEMENT (stmt_info)
&& !pow2p_hwi (DR_GROUP_SIZE (stmt_info))))
{
@@ -2504,12 +2462,12 @@ get_load_store_type (gimple *stmt, tree vectype, bool slp, bool masked_p,
}
/* Return true if boolean argument MASK is suitable for vectorizing
- conditional load or store STMT. When returning true, store the type
+ conditional load or store STMT_INFO. When returning true, store the type
of the definition in *MASK_DT_OUT and the type of the vectorized mask
in *MASK_VECTYPE_OUT. */
static bool
-vect_check_load_store_mask (gimple *stmt, tree mask,
+vect_check_load_store_mask (stmt_vec_info stmt_info, tree mask,
vect_def_type *mask_dt_out,
tree *mask_vectype_out)
{
@@ -2529,7 +2487,6 @@ vect_check_load_store_mask (gimple *stmt, tree mask,
return false;
}
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
enum vect_def_type mask_dt;
tree mask_vectype;
if (!vect_is_simple_use (mask, stmt_info->vinfo, &mask_dt, &mask_vectype))
@@ -2556,15 +2513,11 @@ vect_check_load_store_mask (gimple *stmt, tree mask,
TYPE_VECTOR_SUBPARTS (vectype)))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "vector mask type ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, mask_vectype);
- dump_printf (MSG_MISSED_OPTIMIZATION,
- " does not match vector data type ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, vectype);
- dump_printf (MSG_MISSED_OPTIMIZATION, ".\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "vector mask type %T",
+ " does not match vector data type %T.\n",
+ mask_vectype, vectype);
+
return false;
}
@@ -2574,13 +2527,14 @@ vect_check_load_store_mask (gimple *stmt, tree mask,
}
/* Return true if stored value RHS is suitable for vectorizing store
- statement STMT. When returning true, store the type of the
+ statement STMT_INFO. When returning true, store the type of the
definition in *RHS_DT_OUT, the type of the vectorized store value in
*RHS_VECTYPE_OUT and the type of the store in *VLS_TYPE_OUT. */
static bool
-vect_check_store_rhs (gimple *stmt, tree rhs, vect_def_type *rhs_dt_out,
- tree *rhs_vectype_out, vec_load_store_type *vls_type_out)
+vect_check_store_rhs (stmt_vec_info stmt_info, tree rhs,
+ vect_def_type *rhs_dt_out, tree *rhs_vectype_out,
+ vec_load_store_type *vls_type_out)
{
/* In the case this is a store from a constant make sure
native_encode_expr can handle it. */
@@ -2592,7 +2546,6 @@ vect_check_store_rhs (gimple *stmt, tree rhs, vect_def_type *rhs_dt_out,
return false;
}
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
enum vect_def_type rhs_dt;
tree rhs_vectype;
if (!vect_is_simple_use (rhs, stmt_info->vinfo, &rhs_dt, &rhs_vectype))
@@ -2621,12 +2574,12 @@ vect_check_store_rhs (gimple *stmt, tree rhs, vect_def_type *rhs_dt_out,
return true;
}
-/* Build an all-ones vector mask of type MASKTYPE while vectorizing STMT.
+/* Build an all-ones vector mask of type MASKTYPE while vectorizing STMT_INFO.
Note that we support masks with floating-point type, in which case the
floats are interpreted as a bitmask. */
static tree
-vect_build_all_ones_mask (gimple *stmt, tree masktype)
+vect_build_all_ones_mask (stmt_vec_info stmt_info, tree masktype)
{
if (TREE_CODE (masktype) == INTEGER_TYPE)
return build_int_cst (masktype, -1);
@@ -2634,7 +2587,7 @@ vect_build_all_ones_mask (gimple *stmt, tree masktype)
{
tree mask = build_int_cst (TREE_TYPE (masktype), -1);
mask = build_vector_from_val (masktype, mask);
- return vect_init_vector (stmt, mask, masktype, NULL);
+ return vect_init_vector (stmt_info, mask, masktype, NULL);
}
else if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (masktype)))
{
@@ -2645,16 +2598,16 @@ vect_build_all_ones_mask (gimple *stmt, tree masktype)
real_from_target (&r, tmp, TYPE_MODE (TREE_TYPE (masktype)));
tree mask = build_real (TREE_TYPE (masktype), r);
mask = build_vector_from_val (masktype, mask);
- return vect_init_vector (stmt, mask, masktype, NULL);
+ return vect_init_vector (stmt_info, mask, masktype, NULL);
}
gcc_unreachable ();
}
/* Build an all-zero merge value of type VECTYPE while vectorizing
- STMT as a gather load. */
+ STMT_INFO as a gather load. */
static tree
-vect_build_zero_merge_argument (gimple *stmt, tree vectype)
+vect_build_zero_merge_argument (stmt_vec_info stmt_info, tree vectype)
{
tree merge;
if (TREE_CODE (TREE_TYPE (vectype)) == INTEGER_TYPE)
@@ -2671,20 +2624,22 @@ vect_build_zero_merge_argument (gimple *stmt, tree vectype)
else
gcc_unreachable ();
merge = build_vector_from_val (vectype, merge);
- return vect_init_vector (stmt, merge, vectype, NULL);
+ return vect_init_vector (stmt_info, merge, vectype, NULL);
}
-/* Build a gather load call while vectorizing STMT. Insert new instructions
- before GSI and add them to VEC_STMT. GS_INFO describes the gather load
- operation. If the load is conditional, MASK is the unvectorized
- condition and MASK_DT is its definition type, otherwise MASK is null. */
+/* Build a gather load call while vectorizing STMT_INFO. Insert new
+ instructions before GSI and add them to VEC_STMT. GS_INFO describes
+ the gather load operation. If the load is conditional, MASK is the
+ unvectorized condition and MASK_DT is its definition type, otherwise
+ MASK is null. */
static void
-vect_build_gather_load_calls (gimple *stmt, gimple_stmt_iterator *gsi,
- gimple **vec_stmt, gather_scatter_info *gs_info,
- tree mask, vect_def_type mask_dt)
+vect_build_gather_load_calls (stmt_vec_info stmt_info,
+ gimple_stmt_iterator *gsi,
+ stmt_vec_info *vec_stmt,
+ gather_scatter_info *gs_info,
+ tree mask)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
@@ -2751,8 +2706,8 @@ vect_build_gather_load_calls (gimple *stmt, gimple_stmt_iterator *gsi,
else
gcc_unreachable ();
- tree vec_dest = vect_create_destination_var (gimple_get_lhs (stmt),
- vectype);
+ tree scalar_dest = gimple_get_lhs (stmt_info->stmt);
+ tree vec_dest = vect_create_destination_var (scalar_dest, vectype);
tree ptr = fold_convert (ptrtype, gs_info->base);
if (!is_gimple_min_invariant (ptr))
@@ -2774,23 +2729,22 @@ vect_build_gather_load_calls (gimple *stmt, gimple_stmt_iterator *gsi,
if (!mask)
{
- src_op = vect_build_zero_merge_argument (stmt, rettype);
- mask_op = vect_build_all_ones_mask (stmt, masktype);
+ src_op = vect_build_zero_merge_argument (stmt_info, rettype);
+ mask_op = vect_build_all_ones_mask (stmt_info, masktype);
}
for (int j = 0; j < ncopies; ++j)
{
tree op, var;
- gimple *new_stmt;
if (modifier == WIDEN && (j & 1))
op = permute_vec_elements (vec_oprnd0, vec_oprnd0,
- perm_mask, stmt, gsi);
+ perm_mask, stmt_info, gsi);
else if (j == 0)
op = vec_oprnd0
- = vect_get_vec_def_for_operand (gs_info->offset, stmt);
+ = vect_get_vec_def_for_operand (gs_info->offset, stmt_info);
else
- op = vec_oprnd0
- = vect_get_vec_def_for_stmt_copy (gs_info->offset_dt, vec_oprnd0);
+ op = vec_oprnd0 = vect_get_vec_def_for_stmt_copy (loop_vinfo,
+ vec_oprnd0);
if (!useless_type_conversion_p (idxtype, TREE_TYPE (op)))
{
@@ -2798,8 +2752,8 @@ vect_build_gather_load_calls (gimple *stmt, gimple_stmt_iterator *gsi,
TYPE_VECTOR_SUBPARTS (idxtype)));
var = vect_get_new_ssa_name (idxtype, vect_simple_var);
op = build1 (VIEW_CONVERT_EXPR, idxtype, op);
- new_stmt = gimple_build_assign (var, VIEW_CONVERT_EXPR, op);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ gassign *new_stmt = gimple_build_assign (var, VIEW_CONVERT_EXPR, op);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
op = var;
}
@@ -2807,13 +2761,14 @@ vect_build_gather_load_calls (gimple *stmt, gimple_stmt_iterator *gsi,
{
if (mask_perm_mask && (j & 1))
mask_op = permute_vec_elements (mask_op, mask_op,
- mask_perm_mask, stmt, gsi);
+ mask_perm_mask, stmt_info, gsi);
else
{
if (j == 0)
- vec_mask = vect_get_vec_def_for_operand (mask, stmt);
+ vec_mask = vect_get_vec_def_for_operand (mask, stmt_info);
else
- vec_mask = vect_get_vec_def_for_stmt_copy (mask_dt, vec_mask);
+ vec_mask = vect_get_vec_def_for_stmt_copy (loop_vinfo,
+ vec_mask);
mask_op = vec_mask;
if (!useless_type_conversion_p (masktype, TREE_TYPE (vec_mask)))
@@ -2823,37 +2778,40 @@ vect_build_gather_load_calls (gimple *stmt, gimple_stmt_iterator *gsi,
TYPE_VECTOR_SUBPARTS (masktype)));
var = vect_get_new_ssa_name (masktype, vect_simple_var);
mask_op = build1 (VIEW_CONVERT_EXPR, masktype, mask_op);
- new_stmt = gimple_build_assign (var, VIEW_CONVERT_EXPR,
- mask_op);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ gassign *new_stmt
+ = gimple_build_assign (var, VIEW_CONVERT_EXPR, mask_op);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
mask_op = var;
}
}
src_op = mask_op;
}
- new_stmt = gimple_build_call (gs_info->decl, 5, src_op, ptr, op,
- mask_op, scale);
+ gcall *new_call = gimple_build_call (gs_info->decl, 5, src_op, ptr, op,
+ mask_op, scale);
+ stmt_vec_info new_stmt_info;
if (!useless_type_conversion_p (vectype, rettype))
{
gcc_assert (known_eq (TYPE_VECTOR_SUBPARTS (vectype),
TYPE_VECTOR_SUBPARTS (rettype)));
op = vect_get_new_ssa_name (rettype, vect_simple_var);
- gimple_call_set_lhs (new_stmt, op);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ gimple_call_set_lhs (new_call, op);
+ vect_finish_stmt_generation (stmt_info, new_call, gsi);
var = make_ssa_name (vec_dest);
op = build1 (VIEW_CONVERT_EXPR, vectype, op);
- new_stmt = gimple_build_assign (var, VIEW_CONVERT_EXPR, op);
+ gassign *new_stmt = gimple_build_assign (var, VIEW_CONVERT_EXPR, op);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
}
else
{
- var = make_ssa_name (vec_dest, new_stmt);
- gimple_call_set_lhs (new_stmt, var);
+ var = make_ssa_name (vec_dest, new_call);
+ gimple_call_set_lhs (new_call, var);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_call, gsi);
}
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
-
if (modifier == NARROW)
{
if ((j & 1) == 0)
@@ -2861,25 +2819,27 @@ vect_build_gather_load_calls (gimple *stmt, gimple_stmt_iterator *gsi,
prev_res = var;
continue;
}
- var = permute_vec_elements (prev_res, var, perm_mask, stmt, gsi);
- new_stmt = SSA_NAME_DEF_STMT (var);
+ var = permute_vec_elements (prev_res, var, perm_mask,
+ stmt_info, gsi);
+ new_stmt_info = loop_vinfo->lookup_def (var);
}
if (prev_stmt_info == NULL)
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info;
else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
- prev_stmt_info = vinfo_for_stmt (new_stmt);
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
+ prev_stmt_info = new_stmt_info;
}
}
/* Prepare the base and offset in GS_INFO for vectorization.
Set *DATAREF_PTR to the loop-invariant base address and *VEC_OFFSET
- to the vectorized offset argument for the first copy of STMT. STMT
- is the statement described by GS_INFO and LOOP is the containing loop. */
+ to the vectorized offset argument for the first copy of STMT_INFO.
+ STMT_INFO is the statement described by GS_INFO and LOOP is the
+ containing loop. */
static void
-vect_get_gather_scatter_ops (struct loop *loop, gimple *stmt,
+vect_get_gather_scatter_ops (struct loop *loop, stmt_vec_info stmt_info,
gather_scatter_info *gs_info,
tree *dataref_ptr, tree *vec_offset)
{
@@ -2894,13 +2854,13 @@ vect_get_gather_scatter_ops (struct loop *loop, gimple *stmt,
}
tree offset_type = TREE_TYPE (gs_info->offset);
tree offset_vectype = get_vectype_for_scalar_type (offset_type);
- *vec_offset = vect_get_vec_def_for_operand (gs_info->offset, stmt,
+ *vec_offset = vect_get_vec_def_for_operand (gs_info->offset, stmt_info,
offset_vectype);
}
/* Prepare to implement a grouped or strided load or store using
the gather load or scatter store operation described by GS_INFO.
- STMT is the load or store statement.
+ STMT_INFO is the load or store statement.
Set *DATAREF_BUMP to the amount that should be added to the base
address after each copy of the vectorized statement. Set *VEC_OFFSET
@@ -2908,11 +2868,11 @@ vect_get_gather_scatter_ops (struct loop *loop, gimple *stmt,
I * DR_STEP / SCALE. */
static void
-vect_get_strided_load_store_ops (gimple *stmt, loop_vec_info loop_vinfo,
+vect_get_strided_load_store_ops (stmt_vec_info stmt_info,
+ loop_vec_info loop_vinfo,
gather_scatter_info *gs_info,
tree *dataref_bump, tree *vec_offset)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
@@ -2945,19 +2905,19 @@ vect_get_strided_load_store_ops (gimple *stmt, loop_vec_info loop_vinfo,
}
/* Return the amount that should be added to a vector pointer to move
- to the next or previous copy of AGGR_TYPE. DR is the data reference
+ to the next or previous copy of AGGR_TYPE. DR_INFO is the data reference
being vectorized and MEMORY_ACCESS_TYPE describes the type of
vectorization. */
static tree
-vect_get_data_ptr_increment (data_reference *dr, tree aggr_type,
+vect_get_data_ptr_increment (dr_vec_info *dr_info, tree aggr_type,
vect_memory_access_type memory_access_type)
{
if (memory_access_type == VMAT_INVARIANT)
return size_zero_node;
tree iv_step = TYPE_SIZE_UNIT (aggr_type);
- tree step = vect_dr_behavior (dr)->step;
+ tree step = vect_dr_behavior (dr_info)->step;
if (tree_int_cst_sgn (step) == -1)
iv_step = fold_build1 (NEGATE_EXPR, TREE_TYPE (iv_step), iv_step);
return iv_step;
@@ -2966,22 +2926,19 @@ vect_get_data_ptr_increment (data_reference *dr, tree aggr_type,
/* Check and perform vectorization of BUILT_IN_BSWAP{16,32,64}. */
static bool
-vectorizable_bswap (gimple *stmt, gimple_stmt_iterator *gsi,
- gimple **vec_stmt, slp_tree slp_node,
- tree vectype_in, enum vect_def_type *dt,
- stmt_vector_for_cost *cost_vec)
+vectorizable_bswap (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ stmt_vec_info *vec_stmt, slp_tree slp_node,
+ tree vectype_in, stmt_vector_for_cost *cost_vec)
{
tree op, vectype;
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ gcall *stmt = as_a <gcall *> (stmt_info->stmt);
+ vec_info *vinfo = stmt_info->vinfo;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
unsigned ncopies;
- unsigned HOST_WIDE_INT nunits, num_bytes;
op = gimple_call_arg (stmt, 0);
vectype = STMT_VINFO_VECTYPE (stmt_info);
-
- if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant (&nunits))
- return false;
+ poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
/* Multiple types in SLP are handled by creating the appropriate number of
vectorized stmts for each SLP node. Hence, NCOPIES is always 1 in
@@ -2997,11 +2954,11 @@ vectorizable_bswap (gimple *stmt, gimple_stmt_iterator *gsi,
if (! char_vectype)
return false;
- if (!TYPE_VECTOR_SUBPARTS (char_vectype).is_constant (&num_bytes))
+ poly_uint64 num_bytes = TYPE_VECTOR_SUBPARTS (char_vectype);
+ unsigned word_bytes;
+ if (!constant_multiple_p (num_bytes, nunits, &word_bytes))
return false;
- unsigned word_bytes = num_bytes / nunits;
-
/* The encoding uses one stepped pattern for each byte in the word. */
vec_perm_builder elts (num_bytes, word_bytes, 3);
for (unsigned i = 0; i < 3; ++i)
@@ -3030,46 +2987,48 @@ vectorizable_bswap (gimple *stmt, gimple_stmt_iterator *gsi,
/* Transform. */
vec<tree> vec_oprnds = vNULL;
- gimple *new_stmt = NULL;
+ stmt_vec_info new_stmt_info = NULL;
stmt_vec_info prev_stmt_info = NULL;
for (unsigned j = 0; j < ncopies; j++)
{
/* Handle uses. */
if (j == 0)
- vect_get_vec_defs (op, NULL, stmt, &vec_oprnds, NULL, slp_node);
+ vect_get_vec_defs (op, NULL, stmt_info, &vec_oprnds, NULL, slp_node);
else
- vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds, NULL);
+ vect_get_vec_defs_for_stmt_copy (vinfo, &vec_oprnds, NULL);
/* Arguments are ready. create the new vector stmt. */
unsigned i;
tree vop;
FOR_EACH_VEC_ELT (vec_oprnds, i, vop)
{
+ gimple *new_stmt;
tree tem = make_ssa_name (char_vectype);
new_stmt = gimple_build_assign (tem, build1 (VIEW_CONVERT_EXPR,
char_vectype, vop));
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
tree tem2 = make_ssa_name (char_vectype);
new_stmt = gimple_build_assign (tem2, VEC_PERM_EXPR,
tem, tem, bswap_vconst);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
tem = make_ssa_name (vectype);
new_stmt = gimple_build_assign (tem, build1 (VIEW_CONVERT_EXPR,
vectype, tem2));
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
if (slp_node)
- SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info);
}
if (slp_node)
continue;
if (j == 0)
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info;
else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
- prev_stmt_info = vinfo_for_stmt (new_stmt);
+ prev_stmt_info = new_stmt_info;
}
vec_oprnds.release ();
@@ -3104,21 +3063,22 @@ simple_integer_narrowing (tree vectype_out, tree vectype_in,
/* Function vectorizable_call.
- Check if GS performs a function call that can be vectorized.
- If VEC_STMT is also passed, vectorize the STMT: create a vectorized
- stmt to replace it, put it in VEC_STMT, and insert it at BSI.
- Return FALSE if not a vectorizable STMT, TRUE otherwise. */
+ Check if STMT_INFO performs a function call that can be vectorized.
+ If VEC_STMT is also passed, vectorize STMT_INFO: create a vectorized
+ stmt to replace it, put it in VEC_STMT, and insert it at GSI.
+ Return true if STMT_INFO is vectorizable in this way. */
static bool
-vectorizable_call (gimple *gs, gimple_stmt_iterator *gsi, gimple **vec_stmt,
- slp_tree slp_node, stmt_vector_for_cost *cost_vec)
+vectorizable_call (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ stmt_vec_info *vec_stmt, slp_tree slp_node,
+ stmt_vector_for_cost *cost_vec)
{
gcall *stmt;
tree vec_dest;
tree scalar_dest;
tree op;
tree vec_oprnd0 = NULL_TREE, vec_oprnd1 = NULL_TREE;
- stmt_vec_info stmt_info = vinfo_for_stmt (gs), prev_stmt_info;
+ stmt_vec_info prev_stmt_info;
tree vectype_out, vectype_in;
poly_uint64 nunits_in;
poly_uint64 nunits_out;
@@ -3130,7 +3090,6 @@ vectorizable_call (gimple *gs, gimple_stmt_iterator *gsi, gimple **vec_stmt,
= { vect_unknown_def_type, vect_unknown_def_type, vect_unknown_def_type,
vect_unknown_def_type };
int ndts = ARRAY_SIZE (dt);
- gimple *new_stmt = NULL;
int ncopies, j;
auto_vec<tree, 8> vargs;
auto_vec<tree, 8> orig_vargs;
@@ -3145,8 +3104,8 @@ vectorizable_call (gimple *gs, gimple_stmt_iterator *gsi, gimple **vec_stmt,
&& ! vec_stmt)
return false;
- /* Is GS a vectorizable call? */
- stmt = dyn_cast <gcall *> (gs);
+ /* Is STMT_INFO a vectorizable call? */
+ stmt = dyn_cast <gcall *> (stmt_info->stmt);
if (!stmt)
return false;
@@ -3237,12 +3196,8 @@ vectorizable_call (gimple *gs, gimple_stmt_iterator *gsi, gimple **vec_stmt,
if (!vectype_in)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "no vectype for scalar type ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, rhs_type);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "no vectype for scalar type %T\n", rhs_type);
return false;
}
@@ -3315,8 +3270,8 @@ vectorizable_call (gimple *gs, gimple_stmt_iterator *gsi, gimple **vec_stmt,
&& (gimple_call_builtin_p (stmt, BUILT_IN_BSWAP16)
|| gimple_call_builtin_p (stmt, BUILT_IN_BSWAP32)
|| gimple_call_builtin_p (stmt, BUILT_IN_BSWAP64)))
- return vectorizable_bswap (stmt, gsi, vec_stmt, slp_node,
- vectype_in, dt, cost_vec);
+ return vectorizable_bswap (stmt_info, gsi, vec_stmt, slp_node,
+ vectype_in, cost_vec);
else
{
if (dump_enabled_p ())
@@ -3368,6 +3323,7 @@ vectorizable_call (gimple *gs, gimple_stmt_iterator *gsi, gimple **vec_stmt,
bool masked_loop_p = loop_vinfo && LOOP_VINFO_FULLY_MASKED_P (loop_vinfo);
+ stmt_vec_info new_stmt_info = NULL;
prev_stmt_info = NULL;
if (modifier == NONE || ifn != IFN_LAST)
{
@@ -3406,16 +3362,20 @@ vectorizable_call (gimple *gs, gimple_stmt_iterator *gsi, gimple **vec_stmt,
= gimple_build_call_internal_vec (ifn, vargs);
gimple_call_set_lhs (call, half_res);
gimple_call_set_nothrow (call, true);
- new_stmt = call;
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, call, gsi);
if ((i & 1) == 0)
{
prev_res = half_res;
continue;
}
new_temp = make_ssa_name (vec_dest);
- new_stmt = gimple_build_assign (new_temp, convert_code,
- prev_res, half_res);
+ gimple *new_stmt
+ = gimple_build_assign (new_temp, convert_code,
+ prev_res, half_res);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt,
+ gsi);
}
else
{
@@ -3438,10 +3398,10 @@ vectorizable_call (gimple *gs, gimple_stmt_iterator *gsi, gimple **vec_stmt,
new_temp = make_ssa_name (vec_dest, call);
gimple_call_set_lhs (call, new_temp);
gimple_call_set_nothrow (call, true);
- new_stmt = call;
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, call, gsi);
}
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
- SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info);
}
for (i = 0; i < nargs; i++)
@@ -3457,10 +3417,10 @@ vectorizable_call (gimple *gs, gimple_stmt_iterator *gsi, gimple **vec_stmt,
op = gimple_call_arg (stmt, i);
if (j == 0)
vec_oprnd0
- = vect_get_vec_def_for_operand (op, stmt);
+ = vect_get_vec_def_for_operand (op, stmt_info);
else
vec_oprnd0
- = vect_get_vec_def_for_stmt_copy (dt[i], orig_vargs[i]);
+ = vect_get_vec_def_for_stmt_copy (vinfo, orig_vargs[i]);
orig_vargs[i] = vargs[i] = vec_oprnd0;
}
@@ -3480,9 +3440,11 @@ vectorizable_call (gimple *gs, gimple_stmt_iterator *gsi, gimple **vec_stmt,
tree new_var
= vect_get_new_ssa_name (vectype_out, vect_simple_var, "cst_");
gimple *init_stmt = gimple_build_assign (new_var, cst);
- vect_init_vector_1 (stmt, init_stmt, NULL);
+ vect_init_vector_1 (stmt_info, init_stmt, NULL);
new_temp = make_ssa_name (vec_dest);
- new_stmt = gimple_build_assign (new_temp, new_var);
+ gimple *new_stmt = gimple_build_assign (new_temp, new_var);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
}
else if (modifier == NARROW)
{
@@ -3493,16 +3455,18 @@ vectorizable_call (gimple *gs, gimple_stmt_iterator *gsi, gimple **vec_stmt,
gcall *call = gimple_build_call_internal_vec (ifn, vargs);
gimple_call_set_lhs (call, half_res);
gimple_call_set_nothrow (call, true);
- new_stmt = call;
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, call, gsi);
if ((j & 1) == 0)
{
prev_res = half_res;
continue;
}
new_temp = make_ssa_name (vec_dest);
- new_stmt = gimple_build_assign (new_temp, convert_code,
- prev_res, half_res);
+ gassign *new_stmt = gimple_build_assign (new_temp, convert_code,
+ prev_res, half_res);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
}
else
{
@@ -3511,19 +3475,19 @@ vectorizable_call (gimple *gs, gimple_stmt_iterator *gsi, gimple **vec_stmt,
call = gimple_build_call_internal_vec (ifn, vargs);
else
call = gimple_build_call_vec (fndecl, vargs);
- new_temp = make_ssa_name (vec_dest, new_stmt);
+ new_temp = make_ssa_name (vec_dest, call);
gimple_call_set_lhs (call, new_temp);
gimple_call_set_nothrow (call, true);
- new_stmt = call;
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, call, gsi);
}
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
if (j == (modifier == NARROW ? 1 : 0))
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info;
else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
- prev_stmt_info = vinfo_for_stmt (new_stmt);
+ prev_stmt_info = new_stmt_info;
}
}
else if (modifier == NARROW)
@@ -3567,9 +3531,9 @@ vectorizable_call (gimple *gs, gimple_stmt_iterator *gsi, gimple **vec_stmt,
new_temp = make_ssa_name (vec_dest, call);
gimple_call_set_lhs (call, new_temp);
gimple_call_set_nothrow (call, true);
- new_stmt = call;
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
- SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, call, gsi);
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info);
}
for (i = 0; i < nargs; i++)
@@ -3586,34 +3550,36 @@ vectorizable_call (gimple *gs, gimple_stmt_iterator *gsi, gimple **vec_stmt,
if (j == 0)
{
vec_oprnd0
- = vect_get_vec_def_for_operand (op, stmt);
+ = vect_get_vec_def_for_operand (op, stmt_info);
vec_oprnd1
- = vect_get_vec_def_for_stmt_copy (dt[i], vec_oprnd0);
+ = vect_get_vec_def_for_stmt_copy (vinfo, vec_oprnd0);
}
else
{
- vec_oprnd1 = gimple_call_arg (new_stmt, 2*i + 1);
+ vec_oprnd1 = gimple_call_arg (new_stmt_info->stmt,
+ 2 * i + 1);
vec_oprnd0
- = vect_get_vec_def_for_stmt_copy (dt[i], vec_oprnd1);
+ = vect_get_vec_def_for_stmt_copy (vinfo, vec_oprnd1);
vec_oprnd1
- = vect_get_vec_def_for_stmt_copy (dt[i], vec_oprnd0);
+ = vect_get_vec_def_for_stmt_copy (vinfo, vec_oprnd0);
}
vargs.quick_push (vec_oprnd0);
vargs.quick_push (vec_oprnd1);
}
- new_stmt = gimple_build_call_vec (fndecl, vargs);
+ gcall *new_stmt = gimple_build_call_vec (fndecl, vargs);
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_call_set_lhs (new_stmt, new_temp);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
if (j == 0)
- STMT_VINFO_VEC_STMT (stmt_info) = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info) = new_stmt_info;
else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
- prev_stmt_info = vinfo_for_stmt (new_stmt);
+ prev_stmt_info = new_stmt_info;
}
*vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
@@ -3632,15 +3598,12 @@ vectorizable_call (gimple *gs, gimple_stmt_iterator *gsi, gimple **vec_stmt,
if (slp_node)
return true;
- if (is_pattern_stmt_p (stmt_info))
- stmt_info = vinfo_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info));
+ stmt_info = vect_orig_stmt (stmt_info);
lhs = gimple_get_lhs (stmt_info->stmt);
- new_stmt = gimple_build_assign (lhs, build_zero_cst (TREE_TYPE (lhs)));
- set_vinfo_for_stmt (new_stmt, stmt_info);
- set_vinfo_for_stmt (stmt_info->stmt, NULL);
- STMT_VINFO_STMT (stmt_info) = new_stmt;
- gsi_replace (gsi, new_stmt, false);
+ gassign *new_stmt
+ = gimple_build_assign (lhs, build_zero_cst (TREE_TYPE (lhs)));
+ vinfo->replace_stmt (gsi, stmt_info, new_stmt);
return true;
}
@@ -3736,22 +3699,23 @@ simd_clone_subparts (tree vectype)
/* Function vectorizable_simd_clone_call.
- Check if STMT performs a function call that can be vectorized
+ Check if STMT_INFO performs a function call that can be vectorized
by calling a simd clone of the function.
- If VEC_STMT is also passed, vectorize the STMT: create a vectorized
- stmt to replace it, put it in VEC_STMT, and insert it at BSI.
- Return FALSE if not a vectorizable STMT, TRUE otherwise. */
+ If VEC_STMT is also passed, vectorize STMT_INFO: create a vectorized
+ stmt to replace it, put it in VEC_STMT, and insert it at GSI.
+ Return true if STMT_INFO is vectorizable in this way. */
static bool
-vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
- gimple **vec_stmt, slp_tree slp_node,
+vectorizable_simd_clone_call (stmt_vec_info stmt_info,
+ gimple_stmt_iterator *gsi,
+ stmt_vec_info *vec_stmt, slp_tree slp_node,
stmt_vector_for_cost *)
{
tree vec_dest;
tree scalar_dest;
tree op, type;
tree vec_oprnd0 = NULL_TREE;
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt), prev_stmt_info;
+ stmt_vec_info prev_stmt_info;
tree vectype;
unsigned int nunits;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
@@ -3759,7 +3723,6 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
vec_info *vinfo = stmt_info->vinfo;
struct loop *loop = loop_vinfo ? LOOP_VINFO_LOOP (loop_vinfo) : NULL;
tree fndecl, new_temp;
- gimple *new_stmt = NULL;
int ncopies, j;
auto_vec<simd_call_arg_info> arginfo;
vec<tree> vargs = vNULL;
@@ -3768,7 +3731,8 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
vec<constructor_elt, va_gc> *ret_ctor_elts = NULL;
/* Is STMT a vectorizable call? */
- if (!is_gimple_call (stmt))
+ gcall *stmt = dyn_cast <gcall *> (stmt_info->stmt);
+ if (!stmt)
return false;
fndecl = gimple_call_fndecl (stmt);
@@ -3794,7 +3758,7 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
vectype = STMT_VINFO_VECTYPE (stmt_info);
- if (loop_vinfo && nested_in_vect_loop_p (loop, stmt))
+ if (loop_vinfo && nested_in_vect_loop_p (loop, stmt_info))
return false;
/* FORNOW */
@@ -3904,7 +3868,7 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"not considering SIMD clones; not yet supported"
" for variable-width vectors.\n");
- return NULL;
+ return false;
}
unsigned int badness = 0;
@@ -4099,13 +4063,13 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
gcc_assert ((k & (k - 1)) == 0);
if (m == 0)
vec_oprnd0
- = vect_get_vec_def_for_operand (op, stmt);
+ = vect_get_vec_def_for_operand (op, stmt_info);
else
{
vec_oprnd0 = arginfo[i].op;
if ((m & (k - 1)) == 0)
vec_oprnd0
- = vect_get_vec_def_for_stmt_copy (arginfo[i].dt,
+ = vect_get_vec_def_for_stmt_copy (vinfo,
vec_oprnd0);
}
arginfo[i].op = vec_oprnd0;
@@ -4113,10 +4077,10 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
= build3 (BIT_FIELD_REF, atype, vec_oprnd0,
bitsize_int (prec),
bitsize_int ((m & (k - 1)) * prec));
- new_stmt
+ gassign *new_stmt
= gimple_build_assign (make_ssa_name (atype),
vec_oprnd0);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
vargs.safe_push (gimple_assign_lhs (new_stmt));
}
else
@@ -4133,10 +4097,10 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
{
if (m == 0 && l == 0)
vec_oprnd0
- = vect_get_vec_def_for_operand (op, stmt);
+ = vect_get_vec_def_for_operand (op, stmt_info);
else
vec_oprnd0
- = vect_get_vec_def_for_stmt_copy (arginfo[i].dt,
+ = vect_get_vec_def_for_stmt_copy (vinfo,
arginfo[i].op);
arginfo[i].op = vec_oprnd0;
if (k == 1)
@@ -4149,10 +4113,11 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
else
{
vec_oprnd0 = build_constructor (atype, ctor_elts);
- new_stmt
+ gassign *new_stmt
= gimple_build_assign (make_ssa_name (atype),
vec_oprnd0);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, new_stmt,
+ gsi);
vargs.safe_push (gimple_assign_lhs (new_stmt));
}
}
@@ -4183,8 +4148,7 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
}
tree phi_res = copy_ssa_name (op);
gphi *new_phi = create_phi_node (phi_res, loop->header);
- set_vinfo_for_stmt (new_phi,
- new_stmt_vec_info (new_phi, loop_vinfo));
+ loop_vinfo->add_stmt (new_phi);
add_phi_arg (new_phi, arginfo[i].op,
loop_preheader_edge (loop), UNKNOWN_LOCATION);
enum tree_code code
@@ -4197,12 +4161,11 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
ncopies * nunits);
tree tcst = wide_int_to_tree (type, cst);
tree phi_arg = copy_ssa_name (op);
- new_stmt
+ gassign *new_stmt
= gimple_build_assign (phi_arg, code, phi_res, tcst);
gimple_stmt_iterator si = gsi_after_labels (loop->header);
gsi_insert_after (&si, new_stmt, GSI_NEW_STMT);
- set_vinfo_for_stmt (new_stmt,
- new_stmt_vec_info (new_stmt, loop_vinfo));
+ loop_vinfo->add_stmt (new_stmt);
add_phi_arg (new_phi, phi_arg, loop_latch_edge (loop),
UNKNOWN_LOCATION);
arginfo[i].op = phi_res;
@@ -4220,9 +4183,10 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
j * nunits);
tree tcst = wide_int_to_tree (type, cst);
new_temp = make_ssa_name (TREE_TYPE (op));
- new_stmt = gimple_build_assign (new_temp, code,
- arginfo[i].op, tcst);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ gassign *new_stmt
+ = gimple_build_assign (new_temp, code,
+ arginfo[i].op, tcst);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
vargs.safe_push (new_temp);
}
break;
@@ -4237,7 +4201,7 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
}
}
- new_stmt = gimple_build_call_vec (fndecl, vargs);
+ gcall *new_call = gimple_build_call_vec (fndecl, vargs);
if (vec_dest)
{
gcc_assert (ratype || simd_clone_subparts (rtype) == nunits);
@@ -4245,12 +4209,13 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
new_temp = create_tmp_var (ratype);
else if (simd_clone_subparts (vectype)
== simd_clone_subparts (rtype))
- new_temp = make_ssa_name (vec_dest, new_stmt);
+ new_temp = make_ssa_name (vec_dest, new_call);
else
- new_temp = make_ssa_name (rtype, new_stmt);
- gimple_call_set_lhs (new_stmt, new_temp);
+ new_temp = make_ssa_name (rtype, new_call);
+ gimple_call_set_lhs (new_call, new_temp);
}
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ stmt_vec_info new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_call, gsi);
if (vec_dest)
{
@@ -4273,19 +4238,22 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
else
t = build3 (BIT_FIELD_REF, vectype, new_temp,
bitsize_int (prec), bitsize_int (l * prec));
- new_stmt
+ gimple *new_stmt
= gimple_build_assign (make_ssa_name (vectype), t);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
+
if (j == 0 && l == 0)
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info)
+ = *vec_stmt = new_stmt_info;
else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
- prev_stmt_info = vinfo_for_stmt (new_stmt);
+ prev_stmt_info = new_stmt_info;
}
if (ratype)
- vect_clobber_variable (stmt, gsi, new_temp);
+ vect_clobber_variable (stmt_info, gsi, new_temp);
continue;
}
else if (simd_clone_subparts (vectype) > nunits)
@@ -4302,29 +4270,32 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
{
tree tem = build4 (ARRAY_REF, rtype, new_temp,
size_int (m), NULL_TREE, NULL_TREE);
- new_stmt
+ gimple *new_stmt
= gimple_build_assign (make_ssa_name (rtype), tem);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt,
+ gsi);
CONSTRUCTOR_APPEND_ELT (ret_ctor_elts, NULL_TREE,
gimple_assign_lhs (new_stmt));
}
- vect_clobber_variable (stmt, gsi, new_temp);
+ vect_clobber_variable (stmt_info, gsi, new_temp);
}
else
CONSTRUCTOR_APPEND_ELT (ret_ctor_elts, NULL_TREE, new_temp);
if ((j & (k - 1)) != k - 1)
continue;
vec_oprnd0 = build_constructor (vectype, ret_ctor_elts);
- new_stmt
+ gimple *new_stmt
= gimple_build_assign (make_ssa_name (vec_dest), vec_oprnd0);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
if ((unsigned) j == k - 1)
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info;
else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
- prev_stmt_info = vinfo_for_stmt (new_stmt);
+ prev_stmt_info = new_stmt_info;
continue;
}
else if (ratype)
@@ -4332,19 +4303,20 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
tree t = build_fold_addr_expr (new_temp);
t = build2 (MEM_REF, vectype, t,
build_int_cst (TREE_TYPE (t), 0));
- new_stmt
+ gimple *new_stmt
= gimple_build_assign (make_ssa_name (vec_dest), t);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
- vect_clobber_variable (stmt, gsi, new_temp);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
+ vect_clobber_variable (stmt_info, gsi, new_temp);
}
}
if (j == 0)
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info;
else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
- prev_stmt_info = vinfo_for_stmt (new_stmt);
+ prev_stmt_info = new_stmt_info;
}
vargs.release ();
@@ -4357,21 +4329,16 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
if (slp_node)
return true;
+ gimple *new_stmt;
if (scalar_dest)
{
type = TREE_TYPE (scalar_dest);
- if (is_pattern_stmt_p (stmt_info))
- lhs = gimple_call_lhs (STMT_VINFO_RELATED_STMT (stmt_info));
- else
- lhs = gimple_call_lhs (stmt);
+ lhs = gimple_call_lhs (vect_orig_stmt (stmt_info)->stmt);
new_stmt = gimple_build_assign (lhs, build_zero_cst (type));
}
else
new_stmt = gimple_build_nop ();
- set_vinfo_for_stmt (new_stmt, stmt_info);
- set_vinfo_for_stmt (stmt, NULL);
- STMT_VINFO_STMT (stmt_info) = new_stmt;
- gsi_replace (gsi, new_stmt, true);
+ vinfo->replace_stmt (gsi, vect_orig_stmt (stmt_info), new_stmt);
unlink_stmt_vdef (stmt);
return true;
@@ -4385,14 +4352,14 @@ vectorizable_simd_clone_call (gimple *stmt, gimple_stmt_iterator *gsi,
VEC_OPRND0 and VEC_OPRND1. The new vector stmt is to be inserted at BSI.
In the case that CODE is a CALL_EXPR, this means that a call to DECL
needs to be created (DECL is a function-decl of a target-builtin).
- STMT is the original scalar stmt that we are vectorizing. */
+ STMT_INFO is the original scalar stmt that we are vectorizing. */
static gimple *
vect_gen_widened_results_half (enum tree_code code,
tree decl,
tree vec_oprnd0, tree vec_oprnd1, int op_type,
tree vec_dest, gimple_stmt_iterator *gsi,
- gimple *stmt)
+ stmt_vec_info stmt_info)
{
gimple *new_stmt;
tree new_temp;
@@ -4418,37 +4385,38 @@ vect_gen_widened_results_half (enum tree_code code,
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_assign_set_lhs (new_stmt, new_temp);
}
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
return new_stmt;
}
-/* Get vectorized definitions for loop-based vectorization. For the first
- operand we call vect_get_vec_def_for_operand() (with OPRND containing
- scalar operand), and for the rest we get a copy with
+/* Get vectorized definitions for loop-based vectorization of STMT_INFO.
+ For the first operand we call vect_get_vec_def_for_operand (with OPRND
+ containing scalar operand), and for the rest we get a copy with
vect_get_vec_def_for_stmt_copy() using the previous vector definition
(stored in OPRND). See vect_get_vec_def_for_stmt_copy() for details.
The vectors are collected into VEC_OPRNDS. */
static void
-vect_get_loop_based_defs (tree *oprnd, gimple *stmt, enum vect_def_type dt,
+vect_get_loop_based_defs (tree *oprnd, stmt_vec_info stmt_info,
vec<tree> *vec_oprnds, int multi_step_cvt)
{
+ vec_info *vinfo = stmt_info->vinfo;
tree vec_oprnd;
/* Get first vector operand. */
/* All the vector operands except the very first one (that is scalar oprnd)
are stmt copies. */
if (TREE_CODE (TREE_TYPE (*oprnd)) != VECTOR_TYPE)
- vec_oprnd = vect_get_vec_def_for_operand (*oprnd, stmt);
+ vec_oprnd = vect_get_vec_def_for_operand (*oprnd, stmt_info);
else
- vec_oprnd = vect_get_vec_def_for_stmt_copy (dt, *oprnd);
+ vec_oprnd = vect_get_vec_def_for_stmt_copy (vinfo, *oprnd);
vec_oprnds->quick_push (vec_oprnd);
/* Get second vector operand. */
- vec_oprnd = vect_get_vec_def_for_stmt_copy (dt, vec_oprnd);
+ vec_oprnd = vect_get_vec_def_for_stmt_copy (vinfo, vec_oprnd);
vec_oprnds->quick_push (vec_oprnd);
*oprnd = vec_oprnd;
@@ -4456,7 +4424,8 @@ vect_get_loop_based_defs (tree *oprnd, gimple *stmt, enum vect_def_type dt,
/* For conversion in multiple steps, continue to get operands
recursively. */
if (multi_step_cvt)
- vect_get_loop_based_defs (oprnd, stmt, dt, vec_oprnds, multi_step_cvt - 1);
+ vect_get_loop_based_defs (oprnd, stmt_info, vec_oprnds,
+ multi_step_cvt - 1);
}
@@ -4466,7 +4435,8 @@ vect_get_loop_based_defs (tree *oprnd, gimple *stmt, enum vect_def_type dt,
static void
vect_create_vectorized_demotion_stmts (vec<tree> *vec_oprnds,
- int multi_step_cvt, gimple *stmt,
+ int multi_step_cvt,
+ stmt_vec_info stmt_info,
vec<tree> vec_dsts,
gimple_stmt_iterator *gsi,
slp_tree slp_node, enum tree_code code,
@@ -4474,8 +4444,6 @@ vect_create_vectorized_demotion_stmts (vec<tree> *vec_oprnds,
{
unsigned int i;
tree vop0, vop1, new_tmp, vec_dest;
- gimple *new_stmt;
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
vec_dest = vec_dsts.pop ();
@@ -4484,10 +4452,11 @@ vect_create_vectorized_demotion_stmts (vec<tree> *vec_oprnds,
/* Create demotion operation. */
vop0 = (*vec_oprnds)[i];
vop1 = (*vec_oprnds)[i + 1];
- new_stmt = gimple_build_assign (vec_dest, code, vop0, vop1);
+ gassign *new_stmt = gimple_build_assign (vec_dest, code, vop0, vop1);
new_tmp = make_ssa_name (vec_dest, new_stmt);
gimple_assign_set_lhs (new_stmt, new_tmp);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ stmt_vec_info new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
if (multi_step_cvt)
/* Store the resulting vector for next recursive call. */
@@ -4498,15 +4467,15 @@ vect_create_vectorized_demotion_stmts (vec<tree> *vec_oprnds,
vectors in SLP_NODE or in vector info of the scalar statement
(or in STMT_VINFO_RELATED_STMT chain). */
if (slp_node)
- SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info);
else
{
if (!*prev_stmt_info)
- STMT_VINFO_VEC_STMT (stmt_info) = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info) = new_stmt_info;
else
- STMT_VINFO_RELATED_STMT (*prev_stmt_info) = new_stmt;
+ STMT_VINFO_RELATED_STMT (*prev_stmt_info) = new_stmt_info;
- *prev_stmt_info = vinfo_for_stmt (new_stmt);
+ *prev_stmt_info = new_stmt_info;
}
}
}
@@ -4521,8 +4490,8 @@ vect_create_vectorized_demotion_stmts (vec<tree> *vec_oprnds,
previous level. */
vec_oprnds->truncate ((i+1)/2);
vect_create_vectorized_demotion_stmts (vec_oprnds, multi_step_cvt - 1,
- stmt, vec_dsts, gsi, slp_node,
- VEC_PACK_TRUNC_EXPR,
+ stmt_info, vec_dsts, gsi,
+ slp_node, VEC_PACK_TRUNC_EXPR,
prev_stmt_info);
}
@@ -4531,13 +4500,14 @@ vect_create_vectorized_demotion_stmts (vec<tree> *vec_oprnds,
/* Create vectorized promotion statements for vector operands from VEC_OPRNDS0
- and VEC_OPRNDS1 (for binary operations). For multi-step conversions store
- the resulting vectors and call the function recursively. */
+ and VEC_OPRNDS1, for a binary operation associated with scalar statement
+ STMT_INFO. For multi-step conversions store the resulting vectors and
+ call the function recursively. */
static void
vect_create_vectorized_promotion_stmts (vec<tree> *vec_oprnds0,
vec<tree> *vec_oprnds1,
- gimple *stmt, tree vec_dest,
+ stmt_vec_info stmt_info, tree vec_dest,
gimple_stmt_iterator *gsi,
enum tree_code code1,
enum tree_code code2, tree decl1,
@@ -4558,9 +4528,11 @@ vect_create_vectorized_promotion_stmts (vec<tree> *vec_oprnds0,
/* Generate the two halves of promotion operation. */
new_stmt1 = vect_gen_widened_results_half (code1, decl1, vop0, vop1,
- op_type, vec_dest, gsi, stmt);
+ op_type, vec_dest, gsi,
+ stmt_info);
new_stmt2 = vect_gen_widened_results_half (code2, decl2, vop0, vop1,
- op_type, vec_dest, gsi, stmt);
+ op_type, vec_dest, gsi,
+ stmt_info);
if (is_gimple_call (new_stmt1))
{
new_tmp1 = gimple_call_lhs (new_stmt1);
@@ -4582,21 +4554,20 @@ vect_create_vectorized_promotion_stmts (vec<tree> *vec_oprnds0,
}
-/* Check if STMT performs a conversion operation, that can be vectorized.
- If VEC_STMT is also passed, vectorize the STMT: create a vectorized
+/* Check if STMT_INFO performs a conversion operation that can be vectorized.
+ If VEC_STMT is also passed, vectorize STMT_INFO: create a vectorized
stmt to replace it, put it in VEC_STMT, and insert it at GSI.
- Return FALSE if not a vectorizable STMT, TRUE otherwise. */
+ Return true if STMT_INFO is vectorizable in this way. */
static bool
-vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
- gimple **vec_stmt, slp_tree slp_node,
+vectorizable_conversion (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ stmt_vec_info *vec_stmt, slp_tree slp_node,
stmt_vector_for_cost *cost_vec)
{
tree vec_dest;
tree scalar_dest;
tree op0, op1 = NULL_TREE;
tree vec_oprnd0 = NULL_TREE, vec_oprnd1 = NULL_TREE;
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
enum tree_code code, code1 = ERROR_MARK, code2 = ERROR_MARK;
enum tree_code codecvt1 = ERROR_MARK, codecvt2 = ERROR_MARK;
@@ -4604,7 +4575,6 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
tree new_temp;
enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
int ndts = 2;
- gimple *new_stmt = NULL;
stmt_vec_info prev_stmt_info;
poly_uint64 nunits_in;
poly_uint64 nunits_out;
@@ -4632,7 +4602,8 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
&& ! vec_stmt)
return false;
- if (!is_gimple_assign (stmt))
+ gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt);
+ if (!stmt)
return false;
if (TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
@@ -4715,12 +4686,8 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
if (!vectype_in)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "no vectype for scalar type ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, rhs_type);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "no vectype for scalar type %T\n", rhs_type);
return false;
}
@@ -4729,13 +4696,9 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
&& !VECTOR_BOOLEAN_TYPE_P (vectype_in))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "can't convert between boolean and non "
- "boolean vectors");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, rhs_type);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "can't convert between boolean and non "
+ "boolean vectors %T\n", rhs_type);
return false;
}
@@ -4788,9 +4751,9 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
return false;
case WIDEN:
- if (supportable_widening_operation (code, stmt, vectype_out, vectype_in,
- &code1, &code2, &multi_step_cvt,
- &interm_types))
+ if (supportable_widening_operation (code, stmt_info, vectype_out,
+ vectype_in, &code1, &code2,
+ &multi_step_cvt, &interm_types))
{
/* Binary widening operation can only be supported directly by the
architecture. */
@@ -4821,15 +4784,16 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
cvt_type, &decl1, &codecvt1))
goto unsupported;
}
- else if (!supportable_widening_operation (code, stmt, vectype_out,
- cvt_type, &codecvt1,
- &codecvt2, &multi_step_cvt,
+ else if (!supportable_widening_operation (code, stmt_info,
+ vectype_out, cvt_type,
+ &codecvt1, &codecvt2,
+ &multi_step_cvt,
&interm_types))
continue;
else
gcc_assert (multi_step_cvt == 0);
- if (supportable_widening_operation (NOP_EXPR, stmt, cvt_type,
+ if (supportable_widening_operation (NOP_EXPR, stmt_info, cvt_type,
vectype_in, &code1, &code2,
&multi_step_cvt, &interm_types))
{
@@ -4968,37 +4932,44 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
for (j = 0; j < ncopies; j++)
{
if (j == 0)
- vect_get_vec_defs (op0, NULL, stmt, &vec_oprnds0, NULL, slp_node);
+ vect_get_vec_defs (op0, NULL, stmt_info, &vec_oprnds0,
+ NULL, slp_node);
else
- vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds0, NULL);
+ vect_get_vec_defs_for_stmt_copy (vinfo, &vec_oprnds0, NULL);
FOR_EACH_VEC_ELT (vec_oprnds0, i, vop0)
{
+ stmt_vec_info new_stmt_info;
/* Arguments are ready, create the new vector stmt. */
if (code1 == CALL_EXPR)
{
- new_stmt = gimple_build_call (decl1, 1, vop0);
+ gcall *new_stmt = gimple_build_call (decl1, 1, vop0);
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_call_set_lhs (new_stmt, new_temp);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
}
else
{
gcc_assert (TREE_CODE_LENGTH (code1) == unary_op);
- new_stmt = gimple_build_assign (vec_dest, code1, vop0);
+ gassign *new_stmt
+ = gimple_build_assign (vec_dest, code1, vop0);
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_assign_set_lhs (new_stmt, new_temp);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
}
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
if (slp_node)
- SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info);
else
{
if (!prev_stmt_info)
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info)
+ = *vec_stmt = new_stmt_info;
else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
- prev_stmt_info = vinfo_for_stmt (new_stmt);
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
+ prev_stmt_info = new_stmt_info;
}
}
}
@@ -5027,30 +4998,31 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
for (k = 0; k < slp_node->vec_stmts_size - 1; k++)
vec_oprnds1.quick_push (vec_oprnd1);
- vect_get_vec_defs (op0, NULL_TREE, stmt, &vec_oprnds0, NULL,
- slp_node);
+ vect_get_vec_defs (op0, NULL_TREE, stmt_info,
+ &vec_oprnds0, NULL, slp_node);
}
else
- vect_get_vec_defs (op0, op1, stmt, &vec_oprnds0,
+ vect_get_vec_defs (op0, op1, stmt_info, &vec_oprnds0,
&vec_oprnds1, slp_node);
}
else
{
- vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt);
+ vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt_info);
vec_oprnds0.quick_push (vec_oprnd0);
if (op_type == binary_op)
{
if (code == WIDEN_LSHIFT_EXPR)
vec_oprnd1 = op1;
else
- vec_oprnd1 = vect_get_vec_def_for_operand (op1, stmt);
+ vec_oprnd1
+ = vect_get_vec_def_for_operand (op1, stmt_info);
vec_oprnds1.quick_push (vec_oprnd1);
}
}
}
else
{
- vec_oprnd0 = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd0);
+ vec_oprnd0 = vect_get_vec_def_for_stmt_copy (vinfo, vec_oprnd0);
vec_oprnds0.truncate (0);
vec_oprnds0.quick_push (vec_oprnd0);
if (op_type == binary_op)
@@ -5058,7 +5030,7 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
if (code == WIDEN_LSHIFT_EXPR)
vec_oprnd1 = op1;
else
- vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt[1],
+ vec_oprnd1 = vect_get_vec_def_for_stmt_copy (vinfo,
vec_oprnd1);
vec_oprnds1.truncate (0);
vec_oprnds1.quick_push (vec_oprnd1);
@@ -5076,44 +5048,49 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
c2 = codecvt2;
}
vect_create_vectorized_promotion_stmts (&vec_oprnds0,
- &vec_oprnds1,
- stmt, this_dest, gsi,
+ &vec_oprnds1, stmt_info,
+ this_dest, gsi,
c1, c2, decl1, decl2,
op_type);
}
FOR_EACH_VEC_ELT (vec_oprnds0, i, vop0)
{
+ stmt_vec_info new_stmt_info;
if (cvt_type)
{
if (codecvt1 == CALL_EXPR)
{
- new_stmt = gimple_build_call (decl1, 1, vop0);
+ gcall *new_stmt = gimple_build_call (decl1, 1, vop0);
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_call_set_lhs (new_stmt, new_temp);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt,
+ gsi);
}
else
{
gcc_assert (TREE_CODE_LENGTH (codecvt1) == unary_op);
new_temp = make_ssa_name (vec_dest);
- new_stmt = gimple_build_assign (new_temp, codecvt1,
- vop0);
+ gassign *new_stmt
+ = gimple_build_assign (new_temp, codecvt1, vop0);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt,
+ gsi);
}
-
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
}
else
- new_stmt = SSA_NAME_DEF_STMT (vop0);
+ new_stmt_info = vinfo->lookup_def (vop0);
if (slp_node)
- SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info);
else
{
if (!prev_stmt_info)
- STMT_VINFO_VEC_STMT (stmt_info) = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info) = new_stmt_info;
else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
- prev_stmt_info = vinfo_for_stmt (new_stmt);
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
+ prev_stmt_info = new_stmt_info;
}
}
}
@@ -5130,12 +5107,12 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
{
/* Handle uses. */
if (slp_node)
- vect_get_vec_defs (op0, NULL_TREE, stmt, &vec_oprnds0, NULL,
+ vect_get_vec_defs (op0, NULL_TREE, stmt_info, &vec_oprnds0, NULL,
slp_node);
else
{
vec_oprnds0.truncate (0);
- vect_get_loop_based_defs (&last_oprnd, stmt, dt[0], &vec_oprnds0,
+ vect_get_loop_based_defs (&last_oprnd, stmt_info, &vec_oprnds0,
vect_pow2 (multi_step_cvt) - 1);
}
@@ -5145,24 +5122,25 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
{
if (codecvt1 == CALL_EXPR)
{
- new_stmt = gimple_build_call (decl1, 1, vop0);
+ gcall *new_stmt = gimple_build_call (decl1, 1, vop0);
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_call_set_lhs (new_stmt, new_temp);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
}
else
{
gcc_assert (TREE_CODE_LENGTH (codecvt1) == unary_op);
new_temp = make_ssa_name (vec_dest);
- new_stmt = gimple_build_assign (new_temp, codecvt1,
- vop0);
+ gassign *new_stmt
+ = gimple_build_assign (new_temp, codecvt1, vop0);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
}
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
vec_oprnds0[i] = new_temp;
}
vect_create_vectorized_demotion_stmts (&vec_oprnds0, multi_step_cvt,
- stmt, vec_dsts, gsi,
+ stmt_info, vec_dsts, gsi,
slp_node, code1,
&prev_stmt_info);
}
@@ -5181,20 +5159,19 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
/* Function vectorizable_assignment.
- Check if STMT performs an assignment (copy) that can be vectorized.
- If VEC_STMT is also passed, vectorize the STMT: create a vectorized
- stmt to replace it, put it in VEC_STMT, and insert it at BSI.
- Return FALSE if not a vectorizable STMT, TRUE otherwise. */
+ Check if STMT_INFO performs an assignment (copy) that can be vectorized.
+ If VEC_STMT is also passed, vectorize the STMT_INFO: create a vectorized
+ stmt to replace it, put it in VEC_STMT, and insert it at GSI.
+ Return true if STMT_INFO is vectorizable in this way. */
static bool
-vectorizable_assignment (gimple *stmt, gimple_stmt_iterator *gsi,
- gimple **vec_stmt, slp_tree slp_node,
+vectorizable_assignment (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ stmt_vec_info *vec_stmt, slp_tree slp_node,
stmt_vector_for_cost *cost_vec)
{
tree vec_dest;
tree scalar_dest;
tree op;
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
tree new_temp;
enum vect_def_type dt[1] = {vect_unknown_def_type};
@@ -5205,7 +5182,6 @@ vectorizable_assignment (gimple *stmt, gimple_stmt_iterator *gsi,
tree vop;
bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
vec_info *vinfo = stmt_info->vinfo;
- gimple *new_stmt = NULL;
stmt_vec_info prev_stmt_info = NULL;
enum tree_code code;
tree vectype_in;
@@ -5218,7 +5194,8 @@ vectorizable_assignment (gimple *stmt, gimple_stmt_iterator *gsi,
return false;
/* Is vectorizable assignment? */
- if (!is_gimple_assign (stmt))
+ gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt);
+ if (!stmt)
return false;
scalar_dest = gimple_assign_lhs (stmt);
@@ -5310,33 +5287,35 @@ vectorizable_assignment (gimple *stmt, gimple_stmt_iterator *gsi,
{
/* Handle uses. */
if (j == 0)
- vect_get_vec_defs (op, NULL, stmt, &vec_oprnds, NULL, slp_node);
+ vect_get_vec_defs (op, NULL, stmt_info, &vec_oprnds, NULL, slp_node);
else
- vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds, NULL);
+ vect_get_vec_defs_for_stmt_copy (vinfo, &vec_oprnds, NULL);
/* Arguments are ready. create the new vector stmt. */
+ stmt_vec_info new_stmt_info = NULL;
FOR_EACH_VEC_ELT (vec_oprnds, i, vop)
{
if (CONVERT_EXPR_CODE_P (code)
|| code == VIEW_CONVERT_EXPR)
vop = build1 (VIEW_CONVERT_EXPR, vectype, vop);
- new_stmt = gimple_build_assign (vec_dest, vop);
+ gassign *new_stmt = gimple_build_assign (vec_dest, vop);
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_assign_set_lhs (new_stmt, new_temp);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
if (slp_node)
- SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info);
}
if (slp_node)
continue;
if (j == 0)
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info;
else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
- prev_stmt_info = vinfo_for_stmt (new_stmt);
+ prev_stmt_info = new_stmt_info;
}
vec_oprnds.release ();
@@ -5382,21 +5361,20 @@ vect_supportable_shift (enum tree_code code, tree scalar_type)
/* Function vectorizable_shift.
- Check if STMT performs a shift operation that can be vectorized.
- If VEC_STMT is also passed, vectorize the STMT: create a vectorized
- stmt to replace it, put it in VEC_STMT, and insert it at BSI.
- Return FALSE if not a vectorizable STMT, TRUE otherwise. */
+ Check if STMT_INFO performs a shift operation that can be vectorized.
+ If VEC_STMT is also passed, vectorize the STMT_INFO: create a vectorized
+ stmt to replace it, put it in VEC_STMT, and insert it at GSI.
+ Return true if STMT_INFO is vectorizable in this way. */
static bool
-vectorizable_shift (gimple *stmt, gimple_stmt_iterator *gsi,
- gimple **vec_stmt, slp_tree slp_node,
+vectorizable_shift (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ stmt_vec_info *vec_stmt, slp_tree slp_node,
stmt_vector_for_cost *cost_vec)
{
tree vec_dest;
tree scalar_dest;
tree op0, op1 = NULL;
tree vec_oprnd1 = NULL_TREE;
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
tree vectype;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
enum tree_code code;
@@ -5407,7 +5385,6 @@ vectorizable_shift (gimple *stmt, gimple_stmt_iterator *gsi,
machine_mode optab_op2_mode;
enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
int ndts = 2;
- gimple *new_stmt = NULL;
stmt_vec_info prev_stmt_info;
poly_uint64 nunits_in;
poly_uint64 nunits_out;
@@ -5431,7 +5408,8 @@ vectorizable_shift (gimple *stmt, gimple_stmt_iterator *gsi,
return false;
/* Is STMT a vectorizable binary/unary operation? */
- if (!is_gimple_assign (stmt))
+ gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt);
+ if (!stmt)
return false;
if (TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
@@ -5481,7 +5459,9 @@ vectorizable_shift (gimple *stmt, gimple_stmt_iterator *gsi,
return false;
op1 = gimple_assign_rhs2 (stmt);
- if (!vect_is_simple_use (op1, vinfo, &dt[1], &op1_vectype))
+ stmt_vec_info op1_def_stmt_info;
+ if (!vect_is_simple_use (op1, vinfo, &dt[1], &op1_vectype,
+ &op1_def_stmt_info))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -5515,23 +5495,22 @@ vectorizable_shift (gimple *stmt, gimple_stmt_iterator *gsi,
a scalar shift. */
if (slp_node)
{
- vec<gimple *> stmts = SLP_TREE_SCALAR_STMTS (slp_node);
- gimple *slpstmt;
+ vec<stmt_vec_info> stmts = SLP_TREE_SCALAR_STMTS (slp_node);
+ stmt_vec_info slpstmt_info;
- FOR_EACH_VEC_ELT (stmts, k, slpstmt)
- if (!operand_equal_p (gimple_assign_rhs2 (slpstmt), op1, 0))
- scalar_shift_arg = false;
+ FOR_EACH_VEC_ELT (stmts, k, slpstmt_info)
+ {
+ gassign *slpstmt = as_a <gassign *> (slpstmt_info->stmt);
+ if (!operand_equal_p (gimple_assign_rhs2 (slpstmt), op1, 0))
+ scalar_shift_arg = false;
+ }
}
/* If the shift amount is computed by a pattern stmt we cannot
use the scalar amount directly thus give up and use a vector
shift. */
- if (dt[1] == vect_internal_def)
- {
- gimple *def = SSA_NAME_DEF_STMT (op1);
- if (is_pattern_stmt_p (vinfo_for_stmt (def)))
- scalar_shift_arg = false;
- }
+ if (op1_def_stmt_info && is_pattern_stmt_p (op1_def_stmt_info))
+ scalar_shift_arg = false;
}
else
{
@@ -5608,7 +5587,7 @@ vectorizable_shift (gimple *stmt, gimple_stmt_iterator *gsi,
if (vec_stmt && !slp_node)
{
op1 = fold_convert (TREE_TYPE (vectype), op1);
- op1 = vect_init_vector (stmt, op1,
+ op1 = vect_init_vector (stmt_info, op1,
TREE_TYPE (vectype), NULL);
}
}
@@ -5707,35 +5686,37 @@ vectorizable_shift (gimple *stmt, gimple_stmt_iterator *gsi,
(a special case for certain kind of vector shifts); otherwise,
operand 1 should be of a vector type (the usual case). */
if (vec_oprnd1)
- vect_get_vec_defs (op0, NULL_TREE, stmt, &vec_oprnds0, NULL,
- slp_node);
+ vect_get_vec_defs (op0, NULL_TREE, stmt_info, &vec_oprnds0, NULL,
+ slp_node);
else
- vect_get_vec_defs (op0, op1, stmt, &vec_oprnds0, &vec_oprnds1,
- slp_node);
+ vect_get_vec_defs (op0, op1, stmt_info, &vec_oprnds0, &vec_oprnds1,
+ slp_node);
}
else
- vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds0, &vec_oprnds1);
+ vect_get_vec_defs_for_stmt_copy (vinfo, &vec_oprnds0, &vec_oprnds1);
/* Arguments are ready. Create the new vector stmt. */
+ stmt_vec_info new_stmt_info = NULL;
FOR_EACH_VEC_ELT (vec_oprnds0, i, vop0)
{
vop1 = vec_oprnds1[i];
- new_stmt = gimple_build_assign (vec_dest, code, vop0, vop1);
+ gassign *new_stmt = gimple_build_assign (vec_dest, code, vop0, vop1);
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_assign_set_lhs (new_stmt, new_temp);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
if (slp_node)
- SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info);
}
if (slp_node)
continue;
if (j == 0)
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info;
else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
- prev_stmt_info = vinfo_for_stmt (new_stmt);
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
+ prev_stmt_info = new_stmt_info;
}
vec_oprnds0.release ();
@@ -5747,21 +5728,20 @@ vectorizable_shift (gimple *stmt, gimple_stmt_iterator *gsi,
/* Function vectorizable_operation.
- Check if STMT performs a binary, unary or ternary operation that can
+ Check if STMT_INFO performs a binary, unary or ternary operation that can
be vectorized.
- If VEC_STMT is also passed, vectorize the STMT: create a vectorized
- stmt to replace it, put it in VEC_STMT, and insert it at BSI.
- Return FALSE if not a vectorizable STMT, TRUE otherwise. */
+ If VEC_STMT is also passed, vectorize STMT_INFO: create a vectorized
+ stmt to replace it, put it in VEC_STMT, and insert it at GSI.
+ Return true if STMT_INFO is vectorizable in this way. */
static bool
-vectorizable_operation (gimple *stmt, gimple_stmt_iterator *gsi,
- gimple **vec_stmt, slp_tree slp_node,
+vectorizable_operation (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ stmt_vec_info *vec_stmt, slp_tree slp_node,
stmt_vector_for_cost *cost_vec)
{
tree vec_dest;
tree scalar_dest;
tree op0, op1 = NULL_TREE, op2 = NULL_TREE;
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
tree vectype;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
enum tree_code code, orig_code;
@@ -5773,7 +5753,6 @@ vectorizable_operation (gimple *stmt, gimple_stmt_iterator *gsi,
enum vect_def_type dt[3]
= {vect_unknown_def_type, vect_unknown_def_type, vect_unknown_def_type};
int ndts = 3;
- gimple *new_stmt = NULL;
stmt_vec_info prev_stmt_info;
poly_uint64 nunits_in;
poly_uint64 nunits_out;
@@ -5795,7 +5774,8 @@ vectorizable_operation (gimple *stmt, gimple_stmt_iterator *gsi,
return false;
/* Is STMT a vectorizable binary/unary operation? */
- if (!is_gimple_assign (stmt))
+ gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt);
+ if (!stmt)
return false;
if (TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
@@ -5875,13 +5855,9 @@ vectorizable_operation (gimple *stmt, gimple_stmt_iterator *gsi,
if (!vectype)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "no vectype for scalar type ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- TREE_TYPE (op0));
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "no vectype for scalar type %T\n",
+ TREE_TYPE (op0));
return false;
}
@@ -6061,7 +6037,7 @@ vectorizable_operation (gimple *stmt, gimple_stmt_iterator *gsi,
if (j == 0)
{
if (op_type == binary_op)
- vect_get_vec_defs (op0, op1, stmt, &vec_oprnds0, &vec_oprnds1,
+ vect_get_vec_defs (op0, op1, stmt_info, &vec_oprnds0, &vec_oprnds1,
slp_node);
else if (op_type == ternary_op)
{
@@ -6079,59 +6055,64 @@ vectorizable_operation (gimple *stmt, gimple_stmt_iterator *gsi,
}
else
{
- vect_get_vec_defs (op0, op1, stmt, &vec_oprnds0, &vec_oprnds1,
- NULL);
- vect_get_vec_defs (op2, NULL_TREE, stmt, &vec_oprnds2, NULL,
- NULL);
+ vect_get_vec_defs (op0, op1, stmt_info, &vec_oprnds0,
+ &vec_oprnds1, NULL);
+ vect_get_vec_defs (op2, NULL_TREE, stmt_info, &vec_oprnds2,
+ NULL, NULL);
}
}
else
- vect_get_vec_defs (op0, NULL_TREE, stmt, &vec_oprnds0, NULL,
+ vect_get_vec_defs (op0, NULL_TREE, stmt_info, &vec_oprnds0, NULL,
slp_node);
}
else
{
- vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds0, &vec_oprnds1);
+ vect_get_vec_defs_for_stmt_copy (vinfo, &vec_oprnds0, &vec_oprnds1);
if (op_type == ternary_op)
{
tree vec_oprnd = vec_oprnds2.pop ();
- vec_oprnds2.quick_push (vect_get_vec_def_for_stmt_copy (dt[2],
+ vec_oprnds2.quick_push (vect_get_vec_def_for_stmt_copy (vinfo,
vec_oprnd));
}
}
/* Arguments are ready. Create the new vector stmt. */
+ stmt_vec_info new_stmt_info = NULL;
FOR_EACH_VEC_ELT (vec_oprnds0, i, vop0)
{
vop1 = ((op_type == binary_op || op_type == ternary_op)
? vec_oprnds1[i] : NULL_TREE);
vop2 = ((op_type == ternary_op)
? vec_oprnds2[i] : NULL_TREE);
- new_stmt = gimple_build_assign (vec_dest, code, vop0, vop1, vop2);
+ gassign *new_stmt = gimple_build_assign (vec_dest, code,
+ vop0, vop1, vop2);
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_assign_set_lhs (new_stmt, new_temp);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
if (vec_cvt_dest)
{
new_temp = build1 (VIEW_CONVERT_EXPR, vectype_out, new_temp);
- new_stmt = gimple_build_assign (vec_cvt_dest, VIEW_CONVERT_EXPR,
- new_temp);
+ gassign *new_stmt
+ = gimple_build_assign (vec_cvt_dest, VIEW_CONVERT_EXPR,
+ new_temp);
new_temp = make_ssa_name (vec_cvt_dest, new_stmt);
gimple_assign_set_lhs (new_stmt, new_temp);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
}
if (slp_node)
- SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info);
}
if (slp_node)
continue;
if (j == 0)
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info;
else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
- prev_stmt_info = vinfo_for_stmt (new_stmt);
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
+ prev_stmt_info = new_stmt_info;
}
vec_oprnds0.release ();
@@ -6141,19 +6122,20 @@ vectorizable_operation (gimple *stmt, gimple_stmt_iterator *gsi,
return true;
}
-/* A helper function to ensure data reference DR's base alignment. */
+/* A helper function to ensure data reference DR_INFO's base alignment. */
static void
-ensure_base_align (struct data_reference *dr)
+ensure_base_align (dr_vec_info *dr_info)
{
- if (DR_VECT_AUX (dr)->misalignment == DR_MISALIGNMENT_UNINITIALIZED)
+ if (dr_info->misalignment == DR_MISALIGNMENT_UNINITIALIZED)
return;
- if (DR_VECT_AUX (dr)->base_misaligned)
+ if (dr_info->base_misaligned)
{
- tree base_decl = DR_VECT_AUX (dr)->base_decl;
+ tree base_decl = dr_info->base_decl;
- unsigned int align_base_to = DR_TARGET_ALIGNMENT (dr) * BITS_PER_UNIT;
+ unsigned int align_base_to
+ = DR_TARGET_ALIGNMENT (dr_info) * BITS_PER_UNIT;
if (decl_in_symtab_p (base_decl))
symtab_node::get (base_decl)->increase_alignment (align_base_to);
@@ -6162,26 +6144,25 @@ ensure_base_align (struct data_reference *dr)
SET_DECL_ALIGN (base_decl, align_base_to);
DECL_USER_ALIGN (base_decl) = 1;
}
- DR_VECT_AUX (dr)->base_misaligned = false;
+ dr_info->base_misaligned = false;
}
}
/* Function get_group_alias_ptr_type.
- Return the alias type for the group starting at FIRST_STMT. */
+ Return the alias type for the group starting at FIRST_STMT_INFO. */
static tree
-get_group_alias_ptr_type (gimple *first_stmt)
+get_group_alias_ptr_type (stmt_vec_info first_stmt_info)
{
struct data_reference *first_dr, *next_dr;
- gimple *next_stmt;
- first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
- next_stmt = DR_GROUP_NEXT_ELEMENT (vinfo_for_stmt (first_stmt));
- while (next_stmt)
+ first_dr = STMT_VINFO_DATA_REF (first_stmt_info);
+ stmt_vec_info next_stmt_info = DR_GROUP_NEXT_ELEMENT (first_stmt_info);
+ while (next_stmt_info)
{
- next_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (next_stmt));
+ next_dr = STMT_VINFO_DATA_REF (next_stmt_info);
if (get_alias_set (DR_REF (first_dr))
!= get_alias_set (DR_REF (next_dr)))
{
@@ -6190,7 +6171,7 @@ get_group_alias_ptr_type (gimple *first_stmt)
"conflicting alias set types.\n");
return ptr_type_node;
}
- next_stmt = DR_GROUP_NEXT_ELEMENT (vinfo_for_stmt (next_stmt));
+ next_stmt_info = DR_GROUP_NEXT_ELEMENT (next_stmt_info);
}
return reference_alias_ptr_type (DR_REF (first_dr));
}
@@ -6198,21 +6179,20 @@ get_group_alias_ptr_type (gimple *first_stmt)
/* Function vectorizable_store.
- Check if STMT defines a non scalar data-ref (array/pointer/structure) that
- can be vectorized.
- If VEC_STMT is also passed, vectorize the STMT: create a vectorized
- stmt to replace it, put it in VEC_STMT, and insert it at BSI.
- Return FALSE if not a vectorizable STMT, TRUE otherwise. */
+ Check if STMT_INFO defines a non scalar data-ref (array/pointer/structure)
+ that can be vectorized.
+ If VEC_STMT is also passed, vectorize STMT_INFO: create a vectorized
+ stmt to replace it, put it in VEC_STMT, and insert it at GSI.
+ Return true if STMT_INFO is vectorizable in this way. */
static bool
-vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
- slp_tree slp_node, stmt_vector_for_cost *cost_vec)
+vectorizable_store (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ stmt_vec_info *vec_stmt, slp_tree slp_node,
+ stmt_vector_for_cost *cost_vec)
{
tree data_ref;
tree op;
tree vec_oprnd = NULL_TREE;
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
- struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info), *first_dr = NULL;
tree elem_type;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
struct loop *loop = NULL;
@@ -6227,12 +6207,11 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
gimple *ptr_incr = NULL;
int ncopies;
int j;
- gimple *next_stmt, *first_stmt;
+ stmt_vec_info first_stmt_info;
bool grouped_store;
unsigned int group_size, i;
vec<tree> oprnds = vNULL;
vec<tree> result_chain = vNULL;
- bool inv_p;
tree offset = NULL_TREE;
vec<tree> vec_oprnds = vNULL;
bool slp = (slp_node != NULL);
@@ -6241,7 +6220,6 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
vec_info *vinfo = stmt_info->vinfo;
tree aggr_type;
gather_scatter_info gs_info;
- gimple *new_stmt;
poly_uint64 vf;
vec_load_store_type vls_type;
tree ref_type;
@@ -6256,9 +6234,9 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
/* Is vectorizable store? */
tree mask = NULL_TREE, mask_vectype = NULL_TREE;
- if (is_gimple_assign (stmt))
+ if (gassign *assign = dyn_cast <gassign *> (stmt_info->stmt))
{
- tree scalar_dest = gimple_assign_lhs (stmt);
+ tree scalar_dest = gimple_assign_lhs (assign);
if (TREE_CODE (scalar_dest) == VIEW_CONVERT_EXPR
&& is_pattern_stmt_p (stmt_info))
scalar_dest = TREE_OPERAND (scalar_dest, 0);
@@ -6273,7 +6251,7 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
}
else
{
- gcall *call = dyn_cast <gcall *> (stmt);
+ gcall *call = dyn_cast <gcall *> (stmt_info->stmt);
if (!call || !gimple_call_internal_p (call))
return false;
@@ -6293,13 +6271,13 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
if (mask_index >= 0)
{
mask = gimple_call_arg (call, mask_index);
- if (!vect_check_load_store_mask (stmt, mask, &mask_dt,
+ if (!vect_check_load_store_mask (stmt_info, mask, &mask_dt,
&mask_vectype))
return false;
}
}
- op = vect_get_store_rhs (stmt);
+ op = vect_get_store_rhs (stmt_info);
/* Cannot have hybrid store SLP -- that would mean storing to the
same location twice. */
@@ -6327,7 +6305,7 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
gcc_assert (ncopies >= 1);
/* FORNOW. This restriction should be relaxed. */
- if (loop && nested_in_vect_loop_p (loop, stmt) && ncopies > 1)
+ if (loop && nested_in_vect_loop_p (loop, stmt_info) && ncopies > 1)
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -6335,7 +6313,7 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
return false;
}
- if (!vect_check_store_rhs (stmt, op, &rhs_dt, &rhs_vectype, &vls_type))
+ if (!vect_check_store_rhs (stmt_info, op, &rhs_dt, &rhs_vectype, &vls_type))
return false;
elem_type = TREE_TYPE (vectype);
@@ -6345,7 +6323,7 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
return false;
vect_memory_access_type memory_access_type;
- if (!get_load_store_type (stmt, vectype, slp, mask, vls_type, ncopies,
+ if (!get_load_store_type (stmt_info, vectype, slp, mask, vls_type, ncopies,
&memory_access_type, &gs_info))
return false;
@@ -6375,19 +6353,20 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
return false;
}
+ dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info), *first_dr_info = NULL;
grouped_store = (STMT_VINFO_GROUPED_ACCESS (stmt_info)
&& memory_access_type != VMAT_GATHER_SCATTER
&& (slp || memory_access_type != VMAT_CONTIGUOUS));
if (grouped_store)
{
- first_stmt = DR_GROUP_FIRST_ELEMENT (stmt_info);
- first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
- group_size = DR_GROUP_SIZE (vinfo_for_stmt (first_stmt));
+ first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
+ first_dr_info = STMT_VINFO_DR_INFO (first_stmt_info);
+ group_size = DR_GROUP_SIZE (first_stmt_info);
}
else
{
- first_stmt = stmt;
- first_dr = dr;
+ first_stmt_info = stmt_info;
+ first_dr_info = dr_info;
group_size = vec_num = 1;
}
@@ -6409,7 +6388,7 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
/* Transform. */
- ensure_base_align (dr);
+ ensure_base_align (dr_info);
if (memory_access_type == VMAT_GATHER_SCATTER && gs_info.decl)
{
@@ -6482,7 +6461,7 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
/* Currently we support only unconditional scatter stores,
so mask should be all ones. */
mask = build_int_cst (masktype, -1);
- mask = vect_init_vector (stmt, mask, masktype, NULL);
+ mask = vect_init_vector (stmt_info, mask, masktype, NULL);
scale = build_int_cst (scaletype, gs_info.scale);
@@ -6492,26 +6471,25 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
if (j == 0)
{
src = vec_oprnd1
- = vect_get_vec_def_for_operand (op, stmt);
+ = vect_get_vec_def_for_operand (op, stmt_info);
op = vec_oprnd0
- = vect_get_vec_def_for_operand (gs_info.offset, stmt);
+ = vect_get_vec_def_for_operand (gs_info.offset, stmt_info);
}
else if (modifier != NONE && (j & 1))
{
if (modifier == WIDEN)
{
src = vec_oprnd1
- = vect_get_vec_def_for_stmt_copy (rhs_dt, vec_oprnd1);
+ = vect_get_vec_def_for_stmt_copy (vinfo, vec_oprnd1);
op = permute_vec_elements (vec_oprnd0, vec_oprnd0, perm_mask,
- stmt, gsi);
+ stmt_info, gsi);
}
else if (modifier == NARROW)
{
src = permute_vec_elements (vec_oprnd1, vec_oprnd1, perm_mask,
- stmt, gsi);
+ stmt_info, gsi);
op = vec_oprnd0
- = vect_get_vec_def_for_stmt_copy (gs_info.offset_dt,
- vec_oprnd0);
+ = vect_get_vec_def_for_stmt_copy (vinfo, vec_oprnd0);
}
else
gcc_unreachable ();
@@ -6519,10 +6497,9 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
else
{
src = vec_oprnd1
- = vect_get_vec_def_for_stmt_copy (rhs_dt, vec_oprnd1);
+ = vect_get_vec_def_for_stmt_copy (vinfo, vec_oprnd1);
op = vec_oprnd0
- = vect_get_vec_def_for_stmt_copy (gs_info.offset_dt,
- vec_oprnd0);
+ = vect_get_vec_def_for_stmt_copy (vinfo, vec_oprnd0);
}
if (!useless_type_conversion_p (srctype, TREE_TYPE (src)))
@@ -6531,8 +6508,9 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
TYPE_VECTOR_SUBPARTS (srctype)));
var = vect_get_new_ssa_name (srctype, vect_simple_var);
src = build1 (VIEW_CONVERT_EXPR, srctype, src);
- new_stmt = gimple_build_assign (var, VIEW_CONVERT_EXPR, src);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ gassign *new_stmt
+ = gimple_build_assign (var, VIEW_CONVERT_EXPR, src);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
src = var;
}
@@ -6542,40 +6520,38 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
TYPE_VECTOR_SUBPARTS (idxtype)));
var = vect_get_new_ssa_name (idxtype, vect_simple_var);
op = build1 (VIEW_CONVERT_EXPR, idxtype, op);
- new_stmt = gimple_build_assign (var, VIEW_CONVERT_EXPR, op);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ gassign *new_stmt
+ = gimple_build_assign (var, VIEW_CONVERT_EXPR, op);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
op = var;
}
- new_stmt
+ gcall *new_stmt
= gimple_build_call (gs_info.decl, 5, ptr, mask, op, src, scale);
-
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ stmt_vec_info new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
if (prev_stmt_info == NULL)
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info;
else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
- prev_stmt_info = vinfo_for_stmt (new_stmt);
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
+ prev_stmt_info = new_stmt_info;
}
return true;
}
if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
- {
- gimple *group_stmt = DR_GROUP_FIRST_ELEMENT (stmt_info);
- DR_GROUP_STORE_COUNT (vinfo_for_stmt (group_stmt))++;
- }
+ DR_GROUP_STORE_COUNT (DR_GROUP_FIRST_ELEMENT (stmt_info))++;
if (grouped_store)
{
/* FORNOW */
- gcc_assert (!loop || !nested_in_vect_loop_p (loop, stmt));
+ gcc_assert (!loop || !nested_in_vect_loop_p (loop, stmt_info));
/* We vectorize all the stmts of the interleaving group when we
reach the last stmt in the group. */
- if (DR_GROUP_STORE_COUNT (vinfo_for_stmt (first_stmt))
- < DR_GROUP_SIZE (vinfo_for_stmt (first_stmt))
+ if (DR_GROUP_STORE_COUNT (first_stmt_info)
+ < DR_GROUP_SIZE (first_stmt_info)
&& !slp)
{
*vec_stmt = NULL;
@@ -6588,20 +6564,21 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
/* VEC_NUM is the number of vect stmts to be created for this
group. */
vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
- first_stmt = SLP_TREE_SCALAR_STMTS (slp_node)[0];
- gcc_assert (DR_GROUP_FIRST_ELEMENT (vinfo_for_stmt (first_stmt)) == first_stmt);
- first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
- op = vect_get_store_rhs (first_stmt);
+ first_stmt_info = SLP_TREE_SCALAR_STMTS (slp_node)[0];
+ gcc_assert (DR_GROUP_FIRST_ELEMENT (first_stmt_info)
+ == first_stmt_info);
+ first_dr_info = STMT_VINFO_DR_INFO (first_stmt_info);
+ op = vect_get_store_rhs (first_stmt_info);
}
else
/* VEC_NUM is the number of vect stmts to be created for this
group. */
vec_num = group_size;
- ref_type = get_group_alias_ptr_type (first_stmt);
+ ref_type = get_group_alias_ptr_type (first_stmt_info);
}
else
- ref_type = reference_alias_ptr_type (DR_REF (first_dr));
+ ref_type = reference_alias_ptr_type (DR_REF (first_dr_info->dr));
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
@@ -6623,15 +6600,15 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
unsigned int const_nunits = nunits.to_constant ();
gcc_assert (!LOOP_VINFO_FULLY_MASKED_P (loop_vinfo));
- gcc_assert (!nested_in_vect_loop_p (loop, stmt));
+ gcc_assert (!nested_in_vect_loop_p (loop, stmt_info));
stride_base
= fold_build_pointer_plus
- (DR_BASE_ADDRESS (first_dr),
+ (DR_BASE_ADDRESS (first_dr_info->dr),
size_binop (PLUS_EXPR,
- convert_to_ptrofftype (DR_OFFSET (first_dr)),
- convert_to_ptrofftype (DR_INIT (first_dr))));
- stride_step = fold_convert (sizetype, DR_STEP (first_dr));
+ convert_to_ptrofftype (DR_OFFSET (first_dr_info->dr)),
+ convert_to_ptrofftype (DR_INIT (first_dr_info->dr))));
+ stride_step = fold_convert (sizetype, DR_STEP (first_dr_info->dr));
/* For a store with loop-invariant (but other than power-of-2)
stride (i.e. not a grouped access) like so:
@@ -6731,13 +6708,13 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
loop, &incr_gsi, insert_after,
&offvar, NULL);
incr = gsi_stmt (incr_gsi);
- set_vinfo_for_stmt (incr, new_stmt_vec_info (incr, loop_vinfo));
+ loop_vinfo->add_stmt (incr);
stride_step = cse_and_gimplify_to_preheader (loop_vinfo, stride_step);
prev_stmt_info = NULL;
alias_off = build_int_cst (ref_type, 0);
- next_stmt = first_stmt;
+ stmt_vec_info next_stmt_info = first_stmt_info;
for (g = 0; g < group_size; g++)
{
running_off = offvar;
@@ -6749,7 +6726,7 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
tree newoff = copy_ssa_name (running_off, NULL);
incr = gimple_build_assign (newoff, POINTER_PLUS_EXPR,
running_off, pos);
- vect_finish_stmt_generation (stmt, incr, gsi);
+ vect_finish_stmt_generation (stmt_info, incr, gsi);
running_off = newoff;
}
unsigned int group_el = 0;
@@ -6758,19 +6735,20 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
for (j = 0; j < ncopies; j++)
{
/* We've set op and dt above, from vect_get_store_rhs,
- and first_stmt == stmt. */
+ and first_stmt_info == stmt_info. */
if (j == 0)
{
if (slp)
{
- vect_get_vec_defs (op, NULL_TREE, stmt, &vec_oprnds, NULL,
- slp_node);
+ vect_get_vec_defs (op, NULL_TREE, stmt_info,
+ &vec_oprnds, NULL, slp_node);
vec_oprnd = vec_oprnds[0];
}
else
{
- op = vect_get_store_rhs (next_stmt);
- vec_oprnd = vect_get_vec_def_for_operand (op, next_stmt);
+ op = vect_get_store_rhs (next_stmt_info);
+ vec_oprnd = vect_get_vec_def_for_operand
+ (op, next_stmt_info);
}
}
else
@@ -6778,11 +6756,8 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
if (slp)
vec_oprnd = vec_oprnds[j];
else
- {
- vect_is_simple_use (op, vinfo, &rhs_dt);
- vec_oprnd = vect_get_vec_def_for_stmt_copy (rhs_dt,
- vec_oprnd);
- }
+ vec_oprnd = vect_get_vec_def_for_stmt_copy (vinfo,
+ vec_oprnd);
}
/* Pun the vector to extract from if necessary. */
if (lvectype != vectype)
@@ -6791,7 +6766,7 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
gimple *pun
= gimple_build_assign (tem, build1 (VIEW_CONVERT_EXPR,
lvectype, vec_oprnd));
- vect_finish_stmt_generation (stmt, pun, gsi);
+ vect_finish_stmt_generation (stmt_info, pun, gsi);
vec_oprnd = tem;
}
for (i = 0; i < nstores; i++)
@@ -6813,11 +6788,12 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
group_el * elsz);
newref = build2 (MEM_REF, ltype,
running_off, this_off);
- vect_copy_ref_info (newref, DR_REF (first_dr));
+ vect_copy_ref_info (newref, DR_REF (first_dr_info->dr));
/* And store it to *running_off. */
assign = gimple_build_assign (newref, elem);
- vect_finish_stmt_generation (stmt, assign, gsi);
+ stmt_vec_info assign_info
+ = vect_finish_stmt_generation (stmt_info, assign, gsi);
group_el += lnel;
if (! slp
@@ -6826,7 +6802,7 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
newoff = copy_ssa_name (running_off, NULL);
incr = gimple_build_assign (newoff, POINTER_PLUS_EXPR,
running_off, stride_step);
- vect_finish_stmt_generation (stmt, incr, gsi);
+ vect_finish_stmt_generation (stmt_info, incr, gsi);
running_off = newoff;
group_el = 0;
@@ -6836,14 +6812,14 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
{
if (j == 0 && i == 0)
STMT_VINFO_VEC_STMT (stmt_info)
- = *vec_stmt = assign;
+ = *vec_stmt = assign_info;
else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = assign;
- prev_stmt_info = vinfo_for_stmt (assign);
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = assign_info;
+ prev_stmt_info = assign_info;
}
}
}
- next_stmt = DR_GROUP_NEXT_ELEMENT (vinfo_for_stmt (next_stmt));
+ next_stmt_info = DR_GROUP_NEXT_ELEMENT (next_stmt_info);
if (slp)
break;
}
@@ -6855,7 +6831,8 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
auto_vec<tree> dr_chain (group_size);
oprnds.create (group_size);
- alignment_support_scheme = vect_supportable_dr_alignment (first_dr, false);
+ alignment_support_scheme
+ = vect_supportable_dr_alignment (first_dr_info, false);
gcc_assert (alignment_support_scheme);
vec_loop_masks *loop_masks
= (loop_vinfo && LOOP_VINFO_FULLY_MASKED_P (loop_vinfo)
@@ -6884,7 +6861,7 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
else if (memory_access_type == VMAT_GATHER_SCATTER)
{
aggr_type = elem_type;
- vect_get_strided_load_store_ops (stmt, loop_vinfo, &gs_info,
+ vect_get_strided_load_store_ops (stmt_info, loop_vinfo, &gs_info,
&bump, &vec_offset);
}
else
@@ -6893,7 +6870,8 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
aggr_type = build_array_type_nelts (elem_type, vec_num * nunits);
else
aggr_type = vectype;
- bump = vect_get_data_ptr_increment (dr, aggr_type, memory_access_type);
+ bump = vect_get_data_ptr_increment (dr_info, aggr_type,
+ memory_access_type);
}
if (mask)
@@ -6942,14 +6920,14 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
tree vec_mask = NULL_TREE;
for (j = 0; j < ncopies; j++)
{
-
+ stmt_vec_info new_stmt_info;
if (j == 0)
{
if (slp)
{
/* Get vectorized arguments for SLP_NODE. */
- vect_get_vec_defs (op, NULL_TREE, stmt, &vec_oprnds,
- NULL, slp_node);
+ vect_get_vec_defs (op, NULL_TREE, stmt_info, &vec_oprnds,
+ NULL, slp_node);
vec_oprnd = vec_oprnds[0];
}
@@ -6962,22 +6940,23 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
If the store is not grouped, DR_GROUP_SIZE is 1, and DR_CHAIN and
OPRNDS are of size 1. */
- next_stmt = first_stmt;
+ stmt_vec_info next_stmt_info = first_stmt_info;
for (i = 0; i < group_size; i++)
{
/* Since gaps are not supported for interleaved stores,
DR_GROUP_SIZE is the exact number of stmts in the chain.
- Therefore, NEXT_STMT can't be NULL_TREE. In case that
- there is no interleaving, DR_GROUP_SIZE is 1, and only one
- iteration of the loop will be executed. */
- op = vect_get_store_rhs (next_stmt);
- vec_oprnd = vect_get_vec_def_for_operand (op, next_stmt);
+ Therefore, NEXT_STMT_INFO can't be NULL_TREE. In case
+ that there is no interleaving, DR_GROUP_SIZE is 1,
+ and only one iteration of the loop will be executed. */
+ op = vect_get_store_rhs (next_stmt_info);
+ vec_oprnd = vect_get_vec_def_for_operand
+ (op, next_stmt_info);
dr_chain.quick_push (vec_oprnd);
oprnds.quick_push (vec_oprnd);
- next_stmt = DR_GROUP_NEXT_ELEMENT (vinfo_for_stmt (next_stmt));
+ next_stmt_info = DR_GROUP_NEXT_ELEMENT (next_stmt_info);
}
if (mask)
- vec_mask = vect_get_vec_def_for_operand (mask, stmt,
+ vec_mask = vect_get_vec_def_for_operand (mask, stmt_info,
mask_vectype);
}
@@ -6987,31 +6966,25 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
bool simd_lane_access_p
= STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info);
if (simd_lane_access_p
- && TREE_CODE (DR_BASE_ADDRESS (first_dr)) == ADDR_EXPR
- && VAR_P (TREE_OPERAND (DR_BASE_ADDRESS (first_dr), 0))
- && integer_zerop (DR_OFFSET (first_dr))
- && integer_zerop (DR_INIT (first_dr))
+ && TREE_CODE (DR_BASE_ADDRESS (first_dr_info->dr)) == ADDR_EXPR
+ && VAR_P (TREE_OPERAND (DR_BASE_ADDRESS (first_dr_info->dr), 0))
+ && integer_zerop (DR_OFFSET (first_dr_info->dr))
+ && integer_zerop (DR_INIT (first_dr_info->dr))
&& alias_sets_conflict_p (get_alias_set (aggr_type),
get_alias_set (TREE_TYPE (ref_type))))
{
- dataref_ptr = unshare_expr (DR_BASE_ADDRESS (first_dr));
+ dataref_ptr = unshare_expr (DR_BASE_ADDRESS (first_dr_info->dr));
dataref_offset = build_int_cst (ref_type, 0);
- inv_p = false;
}
else if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
- {
- vect_get_gather_scatter_ops (loop, stmt, &gs_info,
- &dataref_ptr, &vec_offset);
- inv_p = false;
- }
+ vect_get_gather_scatter_ops (loop, stmt_info, &gs_info,
+ &dataref_ptr, &vec_offset);
else
dataref_ptr
- = vect_create_data_ref_ptr (first_stmt, aggr_type,
+ = vect_create_data_ref_ptr (first_stmt_info, aggr_type,
simd_lane_access_p ? loop : NULL,
offset, &dummy, gsi, &ptr_incr,
- simd_lane_access_p, &inv_p,
- NULL_TREE, bump);
- gcc_assert (bb_vinfo || !inv_p);
+ simd_lane_access_p, NULL_TREE, bump);
}
else
{
@@ -7025,22 +6998,20 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
for (i = 0; i < group_size; i++)
{
op = oprnds[i];
- vect_is_simple_use (op, vinfo, &rhs_dt);
- vec_oprnd = vect_get_vec_def_for_stmt_copy (rhs_dt, op);
+ vec_oprnd = vect_get_vec_def_for_stmt_copy (vinfo, op);
dr_chain[i] = vec_oprnd;
oprnds[i] = vec_oprnd;
}
if (mask)
- vec_mask = vect_get_vec_def_for_stmt_copy (mask_dt, vec_mask);
+ vec_mask = vect_get_vec_def_for_stmt_copy (vinfo, vec_mask);
if (dataref_offset)
dataref_offset
= int_const_binop (PLUS_EXPR, dataref_offset, bump);
else if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
- vec_offset = vect_get_vec_def_for_stmt_copy (gs_info.offset_dt,
- vec_offset);
+ vec_offset = vect_get_vec_def_for_stmt_copy (vinfo, vec_offset);
else
- dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi, stmt,
- bump);
+ dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi,
+ stmt_info, bump);
}
if (memory_access_type == VMAT_LOAD_STORE_LANES)
@@ -7053,13 +7024,13 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
/* Invalidate the current contents of VEC_ARRAY. This should
become an RTL clobber too, which prevents the vector registers
from being upward-exposed. */
- vect_clobber_variable (stmt, gsi, vec_array);
+ vect_clobber_variable (stmt_info, gsi, vec_array);
/* Store the individual vectors into the array. */
for (i = 0; i < vec_num; i++)
{
vec_oprnd = dr_chain[i];
- write_vector_array (stmt, gsi, vec_oprnd, vec_array, i);
+ write_vector_array (stmt_info, gsi, vec_oprnd, vec_array, i);
}
tree final_mask = NULL;
@@ -7092,25 +7063,24 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
gimple_call_set_lhs (call, data_ref);
}
gimple_call_set_nothrow (call, true);
- new_stmt = call;
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ new_stmt_info = vect_finish_stmt_generation (stmt_info, call, gsi);
/* Record that VEC_ARRAY is now dead. */
- vect_clobber_variable (stmt, gsi, vec_array);
+ vect_clobber_variable (stmt_info, gsi, vec_array);
}
else
{
- new_stmt = NULL;
+ new_stmt_info = NULL;
if (grouped_store)
{
if (j == 0)
result_chain.create (group_size);
/* Permute. */
- vect_permute_store_chain (dr_chain, group_size, stmt, gsi,
+ vect_permute_store_chain (dr_chain, group_size, stmt_info, gsi,
&result_chain);
}
- next_stmt = first_stmt;
+ stmt_vec_info next_stmt_info = first_stmt_info;
for (i = 0; i < vec_num; i++)
{
unsigned align, misalign;
@@ -7137,15 +7107,15 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
(IFN_SCATTER_STORE, 4, dataref_ptr, vec_offset,
scale, vec_oprnd);
gimple_call_set_nothrow (call, true);
- new_stmt = call;
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, call, gsi);
break;
}
if (i > 0)
/* Bump the vector pointer. */
dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi,
- stmt, bump);
+ stmt_info, bump);
if (slp)
vec_oprnd = vec_oprnds[i];
@@ -7154,16 +7124,16 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
vect_permute_store_chain(). */
vec_oprnd = result_chain[i];
- align = DR_TARGET_ALIGNMENT (first_dr);
- if (aligned_access_p (first_dr))
+ align = DR_TARGET_ALIGNMENT (first_dr_info);
+ if (aligned_access_p (first_dr_info))
misalign = 0;
- else if (DR_MISALIGNMENT (first_dr) == -1)
+ else if (DR_MISALIGNMENT (first_dr_info) == -1)
{
- align = dr_alignment (vect_dr_behavior (first_dr));
+ align = dr_alignment (vect_dr_behavior (first_dr_info));
misalign = 0;
}
else
- misalign = DR_MISALIGNMENT (first_dr);
+ misalign = DR_MISALIGNMENT (first_dr_info);
if (dataref_offset == NULL_TREE
&& TREE_CODE (dataref_ptr) == SSA_NAME)
set_ptr_info_alignment (get_ptr_info (dataref_ptr), align,
@@ -7172,16 +7142,15 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
if (memory_access_type == VMAT_CONTIGUOUS_REVERSE)
{
tree perm_mask = perm_mask_for_reverse (vectype);
- tree perm_dest
- = vect_create_destination_var (vect_get_store_rhs (stmt),
- vectype);
+ tree perm_dest = vect_create_destination_var
+ (vect_get_store_rhs (stmt_info), vectype);
tree new_temp = make_ssa_name (perm_dest);
/* Generate the permute statement. */
gimple *perm_stmt
= gimple_build_assign (new_temp, VEC_PERM_EXPR, vec_oprnd,
vec_oprnd, perm_mask);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, perm_stmt, gsi);
perm_stmt = SSA_NAME_DEF_STMT (new_temp);
vec_oprnd = new_temp;
@@ -7197,7 +7166,8 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
dataref_ptr, ptr,
final_mask, vec_oprnd);
gimple_call_set_nothrow (call, true);
- new_stmt = call;
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, call, gsi);
}
else
{
@@ -7206,9 +7176,9 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
dataref_offset
? dataref_offset
: build_int_cst (ref_type, 0));
- if (aligned_access_p (first_dr))
+ if (aligned_access_p (first_dr_info))
;
- else if (DR_MISALIGNMENT (first_dr) == -1)
+ else if (DR_MISALIGNMENT (first_dr_info) == -1)
TREE_TYPE (data_ref)
= build_aligned_type (TREE_TYPE (data_ref),
align * BITS_PER_UNIT);
@@ -7216,26 +7186,28 @@ vectorizable_store (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
TREE_TYPE (data_ref)
= build_aligned_type (TREE_TYPE (data_ref),
TYPE_ALIGN (elem_type));
- vect_copy_ref_info (data_ref, DR_REF (first_dr));
- new_stmt = gimple_build_assign (data_ref, vec_oprnd);
+ vect_copy_ref_info (data_ref, DR_REF (first_dr_info->dr));
+ gassign *new_stmt
+ = gimple_build_assign (data_ref, vec_oprnd);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
}
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
if (slp)
continue;
- next_stmt = DR_GROUP_NEXT_ELEMENT (vinfo_for_stmt (next_stmt));
- if (!next_stmt)
+ next_stmt_info = DR_GROUP_NEXT_ELEMENT (next_stmt_info);
+ if (!next_stmt_info)
break;
}
}
if (!slp)
{
if (j == 0)
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info;
else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
- prev_stmt_info = vinfo_for_stmt (new_stmt);
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
+ prev_stmt_info = new_stmt_info;
}
}
@@ -7274,19 +7246,19 @@ vect_gen_perm_mask_checked (tree vectype, const vec_perm_indices &sel)
}
/* Given a vector variable X and Y, that was generated for the scalar
- STMT, generate instructions to permute the vector elements of X and Y
+ STMT_INFO, generate instructions to permute the vector elements of X and Y
using permutation mask MASK_VEC, insert them at *GSI and return the
permuted vector variable. */
static tree
-permute_vec_elements (tree x, tree y, tree mask_vec, gimple *stmt,
+permute_vec_elements (tree x, tree y, tree mask_vec, stmt_vec_info stmt_info,
gimple_stmt_iterator *gsi)
{
tree vectype = TREE_TYPE (x);
tree perm_dest, data_ref;
gimple *perm_stmt;
- tree scalar_dest = gimple_get_lhs (stmt);
+ tree scalar_dest = gimple_get_lhs (stmt_info->stmt);
if (TREE_CODE (scalar_dest) == SSA_NAME)
perm_dest = vect_create_destination_var (scalar_dest, vectype);
else
@@ -7295,24 +7267,24 @@ permute_vec_elements (tree x, tree y, tree mask_vec, gimple *stmt,
/* Generate the permute statement. */
perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR, x, y, mask_vec);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, perm_stmt, gsi);
return data_ref;
}
-/* Hoist the definitions of all SSA uses on STMT out of the loop LOOP,
+/* Hoist the definitions of all SSA uses on STMT_INFO out of the loop LOOP,
inserting them on the loops preheader edge. Returns true if we
- were successful in doing so (and thus STMT can be moved then),
+ were successful in doing so (and thus STMT_INFO can be moved then),
otherwise returns false. */
static bool
-hoist_defs_of_uses (gimple *stmt, struct loop *loop)
+hoist_defs_of_uses (stmt_vec_info stmt_info, struct loop *loop)
{
ssa_op_iter i;
tree op;
bool any = false;
- FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_USE)
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt_info->stmt, i, SSA_OP_USE)
{
gimple *def_stmt = SSA_NAME_DEF_STMT (op);
if (!gimple_nop_p (def_stmt)
@@ -7340,7 +7312,7 @@ hoist_defs_of_uses (gimple *stmt, struct loop *loop)
if (!any)
return true;
- FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_USE)
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt_info->stmt, i, SSA_OP_USE)
{
gimple *def_stmt = SSA_NAME_DEF_STMT (op);
if (!gimple_nop_p (def_stmt)
@@ -7357,31 +7329,29 @@ hoist_defs_of_uses (gimple *stmt, struct loop *loop)
/* vectorizable_load.
- Check if STMT reads a non scalar data-ref (array/pointer/structure) that
- can be vectorized.
- If VEC_STMT is also passed, vectorize the STMT: create a vectorized
- stmt to replace it, put it in VEC_STMT, and insert it at BSI.
- Return FALSE if not a vectorizable STMT, TRUE otherwise. */
+ Check if STMT_INFO reads a non scalar data-ref (array/pointer/structure)
+ that can be vectorized.
+ If VEC_STMT is also passed, vectorize STMT_INFO: create a vectorized
+ stmt to replace it, put it in VEC_STMT, and insert it at GSI.
+ Return true if STMT_INFO is vectorizable in this way. */
static bool
-vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
- slp_tree slp_node, slp_instance slp_node_instance,
+vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ stmt_vec_info *vec_stmt, slp_tree slp_node,
+ slp_instance slp_node_instance,
stmt_vector_for_cost *cost_vec)
{
tree scalar_dest;
tree vec_dest = NULL;
tree data_ref = NULL;
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
stmt_vec_info prev_stmt_info;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
struct loop *loop = NULL;
- struct loop *containing_loop = (gimple_bb (stmt))->loop_father;
+ struct loop *containing_loop = gimple_bb (stmt_info->stmt)->loop_father;
bool nested_in_vect_loop = false;
- struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info), *first_dr = NULL;
tree elem_type;
tree new_temp;
machine_mode mode;
- gimple *new_stmt = NULL;
tree dummy;
enum dr_alignment_support alignment_support_scheme;
tree dataref_ptr = NULL_TREE;
@@ -7398,9 +7368,8 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
gphi *phi = NULL;
vec<tree> dr_chain = vNULL;
bool grouped_load = false;
- gimple *first_stmt;
- gimple *first_stmt_for_drptr = NULL;
- bool inv_p;
+ stmt_vec_info first_stmt_info;
+ stmt_vec_info first_stmt_info_for_drptr = NULL;
bool compute_in_loop = false;
struct loop *at_loop;
int vec_num;
@@ -7422,13 +7391,13 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
return false;
tree mask = NULL_TREE, mask_vectype = NULL_TREE;
- if (is_gimple_assign (stmt))
+ if (gassign *assign = dyn_cast <gassign *> (stmt_info->stmt))
{
- scalar_dest = gimple_assign_lhs (stmt);
+ scalar_dest = gimple_assign_lhs (assign);
if (TREE_CODE (scalar_dest) != SSA_NAME)
return false;
- tree_code code = gimple_assign_rhs_code (stmt);
+ tree_code code = gimple_assign_rhs_code (assign);
if (code != ARRAY_REF
&& code != BIT_FIELD_REF
&& code != INDIRECT_REF
@@ -7441,7 +7410,7 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
}
else
{
- gcall *call = dyn_cast <gcall *> (stmt);
+ gcall *call = dyn_cast <gcall *> (stmt_info->stmt);
if (!call || !gimple_call_internal_p (call))
return false;
@@ -7465,7 +7434,7 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
if (mask_index >= 0)
{
mask = gimple_call_arg (call, mask_index);
- if (!vect_check_load_store_mask (stmt, mask, &mask_dt,
+ if (!vect_check_load_store_mask (stmt_info, mask, &mask_dt,
&mask_vectype))
return false;
}
@@ -7480,7 +7449,7 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
if (loop_vinfo)
{
loop = LOOP_VINFO_LOOP (loop_vinfo);
- nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt);
+ nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt_info);
vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
}
else
@@ -7540,8 +7509,8 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
gcc_assert (!nested_in_vect_loop);
gcc_assert (!STMT_VINFO_GATHER_SCATTER_P (stmt_info));
- first_stmt = DR_GROUP_FIRST_ELEMENT (stmt_info);
- group_size = DR_GROUP_SIZE (vinfo_for_stmt (first_stmt));
+ first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
+ group_size = DR_GROUP_SIZE (first_stmt_info);
if (slp && SLP_TREE_LOAD_PERMUTATION (slp_node).exists ())
slp_perm = true;
@@ -7565,8 +7534,7 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
we have to give up. */
if (DR_GROUP_SAME_DR_STMT (stmt_info)
&& (STMT_SLP_TYPE (stmt_info)
- != STMT_SLP_TYPE (vinfo_for_stmt
- (DR_GROUP_SAME_DR_STMT (stmt_info)))))
+ != STMT_SLP_TYPE (DR_GROUP_SAME_DR_STMT (stmt_info))))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -7578,7 +7546,7 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
group_size = 1;
vect_memory_access_type memory_access_type;
- if (!get_load_store_type (stmt, vectype, slp, mask, VLS_LOAD, ncopies,
+ if (!get_load_store_type (stmt_info, vectype, slp, mask, VLS_LOAD, ncopies,
&memory_access_type, &gs_info))
return false;
@@ -7642,12 +7610,66 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
/* Transform. */
- ensure_base_align (dr);
+ dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info), *first_dr_info = NULL;
+ ensure_base_align (dr_info);
if (memory_access_type == VMAT_GATHER_SCATTER && gs_info.decl)
{
- vect_build_gather_load_calls (stmt, gsi, vec_stmt, &gs_info, mask,
- mask_dt);
+ vect_build_gather_load_calls (stmt_info, gsi, vec_stmt, &gs_info, mask);
+ return true;
+ }
+
+ if (memory_access_type == VMAT_INVARIANT)
+ {
+ gcc_assert (!grouped_load && !mask && !bb_vinfo);
+ /* If we have versioned for aliasing or the loop doesn't
+ have any data dependencies that would preclude this,
+ then we are sure this is a loop invariant load and
+ thus we can insert it on the preheader edge. */
+ bool hoist_p = (LOOP_VINFO_NO_DATA_DEPENDENCIES (loop_vinfo)
+ && !nested_in_vect_loop
+ && hoist_defs_of_uses (stmt_info, loop));
+ if (hoist_p)
+ {
+ gassign *stmt = as_a <gassign *> (stmt_info->stmt);
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "hoisting out of the vectorized loop: %G", stmt);
+ scalar_dest = copy_ssa_name (scalar_dest);
+ tree rhs = unshare_expr (gimple_assign_rhs1 (stmt));
+ gsi_insert_on_edge_immediate
+ (loop_preheader_edge (loop),
+ gimple_build_assign (scalar_dest, rhs));
+ }
+ /* These copies are all equivalent, but currently the representation
+ requires a separate STMT_VINFO_VEC_STMT for each one. */
+ prev_stmt_info = NULL;
+ gimple_stmt_iterator gsi2 = *gsi;
+ gsi_next (&gsi2);
+ for (j = 0; j < ncopies; j++)
+ {
+ stmt_vec_info new_stmt_info;
+ if (hoist_p)
+ {
+ new_temp = vect_init_vector (stmt_info, scalar_dest,
+ vectype, NULL);
+ gimple *new_stmt = SSA_NAME_DEF_STMT (new_temp);
+ new_stmt_info = vinfo->add_stmt (new_stmt);
+ }
+ else
+ {
+ new_temp = vect_init_vector (stmt_info, scalar_dest,
+ vectype, &gsi2);
+ new_stmt_info = vinfo->lookup_def (new_temp);
+ }
+ if (slp)
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info);
+ else if (j == 0)
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info;
+ else
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
+ prev_stmt_info = new_stmt_info;
+ }
return true;
}
@@ -7671,36 +7693,37 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
if (grouped_load)
{
- first_stmt = DR_GROUP_FIRST_ELEMENT (stmt_info);
- first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
+ first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
+ first_dr_info = STMT_VINFO_DR_INFO (first_stmt_info);
}
else
{
- first_stmt = stmt;
- first_dr = dr;
+ first_stmt_info = stmt_info;
+ first_dr_info = dr_info;
}
if (slp && grouped_load)
{
- group_size = DR_GROUP_SIZE (vinfo_for_stmt (first_stmt));
- ref_type = get_group_alias_ptr_type (first_stmt);
+ group_size = DR_GROUP_SIZE (first_stmt_info);
+ ref_type = get_group_alias_ptr_type (first_stmt_info);
}
else
{
if (grouped_load)
cst_offset
= (tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (vectype)))
- * vect_get_place_in_interleaving_chain (stmt, first_stmt));
+ * vect_get_place_in_interleaving_chain (stmt_info,
+ first_stmt_info));
group_size = 1;
- ref_type = reference_alias_ptr_type (DR_REF (dr));
+ ref_type = reference_alias_ptr_type (DR_REF (dr_info->dr));
}
stride_base
= fold_build_pointer_plus
- (DR_BASE_ADDRESS (first_dr),
+ (DR_BASE_ADDRESS (first_dr_info->dr),
size_binop (PLUS_EXPR,
- convert_to_ptrofftype (DR_OFFSET (first_dr)),
- convert_to_ptrofftype (DR_INIT (first_dr))));
- stride_step = fold_convert (sizetype, DR_STEP (first_dr));
+ convert_to_ptrofftype (DR_OFFSET (first_dr_info->dr)),
+ convert_to_ptrofftype (DR_INIT (first_dr_info->dr))));
+ stride_step = fold_convert (sizetype, DR_STEP (first_dr_info->dr));
/* For a load with loop-invariant (but other than power-of-2)
stride (i.e. not a grouped access) like so:
@@ -7729,7 +7752,7 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
loop, &incr_gsi, insert_after,
&offvar, NULL);
incr = gsi_stmt (incr_gsi);
- set_vinfo_for_stmt (incr, new_stmt_vec_info (incr, loop_vinfo));
+ loop_vinfo->add_stmt (incr);
stride_step = cse_and_gimplify_to_preheader (loop_vinfo, stride_step);
@@ -7823,14 +7846,17 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
{
if (nloads > 1)
vec_alloc (v, nloads);
+ stmt_vec_info new_stmt_info = NULL;
for (i = 0; i < nloads; i++)
{
tree this_off = build_int_cst (TREE_TYPE (alias_off),
group_el * elsz + cst_offset);
tree data_ref = build2 (MEM_REF, ltype, running_off, this_off);
- vect_copy_ref_info (data_ref, DR_REF (first_dr));
- new_stmt = gimple_build_assign (make_ssa_name (ltype), data_ref);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ vect_copy_ref_info (data_ref, DR_REF (first_dr_info->dr));
+ gassign *new_stmt
+ = gimple_build_assign (make_ssa_name (ltype), data_ref);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
if (nloads > 1)
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
gimple_assign_lhs (new_stmt));
@@ -7842,7 +7868,7 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
tree newoff = copy_ssa_name (running_off);
gimple *incr = gimple_build_assign (newoff, POINTER_PLUS_EXPR,
running_off, stride_step);
- vect_finish_stmt_generation (stmt, incr, gsi);
+ vect_finish_stmt_generation (stmt_info, incr, gsi);
running_off = newoff;
group_el = 0;
@@ -7851,32 +7877,34 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
if (nloads > 1)
{
tree vec_inv = build_constructor (lvectype, v);
- new_temp = vect_init_vector (stmt, vec_inv, lvectype, gsi);
- new_stmt = SSA_NAME_DEF_STMT (new_temp);
+ new_temp = vect_init_vector (stmt_info, vec_inv, lvectype, gsi);
+ new_stmt_info = vinfo->lookup_def (new_temp);
if (lvectype != vectype)
{
- new_stmt = gimple_build_assign (make_ssa_name (vectype),
- VIEW_CONVERT_EXPR,
- build1 (VIEW_CONVERT_EXPR,
- vectype, new_temp));
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ gassign *new_stmt
+ = gimple_build_assign (make_ssa_name (vectype),
+ VIEW_CONVERT_EXPR,
+ build1 (VIEW_CONVERT_EXPR,
+ vectype, new_temp));
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
}
}
if (slp)
{
if (slp_perm)
- dr_chain.quick_push (gimple_assign_lhs (new_stmt));
+ dr_chain.quick_push (gimple_assign_lhs (new_stmt_info->stmt));
else
- SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info);
}
else
{
if (j == 0)
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info;
else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
- prev_stmt_info = vinfo_for_stmt (new_stmt);
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
+ prev_stmt_info = new_stmt_info;
}
}
if (slp_perm)
@@ -7894,19 +7922,19 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
if (grouped_load)
{
- first_stmt = DR_GROUP_FIRST_ELEMENT (stmt_info);
- group_size = DR_GROUP_SIZE (vinfo_for_stmt (first_stmt));
+ first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
+ group_size = DR_GROUP_SIZE (first_stmt_info);
/* For SLP vectorization we directly vectorize a subchain
without permutation. */
if (slp && ! SLP_TREE_LOAD_PERMUTATION (slp_node).exists ())
- first_stmt = SLP_TREE_SCALAR_STMTS (slp_node)[0];
+ first_stmt_info = SLP_TREE_SCALAR_STMTS (slp_node)[0];
/* For BB vectorization always use the first stmt to base
the data ref pointer on. */
if (bb_vinfo)
- first_stmt_for_drptr = SLP_TREE_SCALAR_STMTS (slp_node)[0];
+ first_stmt_info_for_drptr = 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))
+ if (STMT_VINFO_VEC_STMT (first_stmt_info)
/* For SLP we would need to copy over SLP_TREE_VEC_STMTS.
??? But we can only do so if there is exactly one
as we have no way to get at the rest. Leave the CSE
@@ -7920,20 +7948,25 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
*vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
return true;
}
- first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
+ first_dr_info = STMT_VINFO_DR_INFO (first_stmt_info);
group_gap_adj = 0;
/* VEC_NUM is the number of vect stmts to be created for this group. */
if (slp)
{
grouped_load = false;
- /* For SLP permutation support we need to load the whole group,
- not only the number of vector stmts the permutation result
- fits in. */
- if (slp_perm)
+ /* If an SLP permutation is from N elements to N elements,
+ and if one vector holds a whole number of N, we can load
+ the inputs to the permutation in the same way as an
+ unpermuted sequence. In other cases we need to load the
+ whole group, not only the number of vector stmts the
+ permutation result fits in. */
+ if (slp_perm
+ && (group_size != SLP_INSTANCE_GROUP_SIZE (slp_node_instance)
+ || !multiple_p (nunits, group_size)))
{
- /* We don't yet generate SLP_TREE_LOAD_PERMUTATIONs for
- variable VF. */
+ /* We don't yet generate such SLP_TREE_LOAD_PERMUTATIONs for
+ variable VF; see vect_transform_slp_perm_load. */
unsigned int const_vf = vf.to_constant ();
unsigned int const_nunits = nunits.to_constant ();
vec_num = CEIL (group_size * const_vf, const_nunits);
@@ -7949,18 +7982,19 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
else
vec_num = group_size;
- ref_type = get_group_alias_ptr_type (first_stmt);
+ ref_type = get_group_alias_ptr_type (first_stmt_info);
}
else
{
- first_stmt = stmt;
- first_dr = dr;
+ first_stmt_info = stmt_info;
+ first_dr_info = dr_info;
group_size = vec_num = 1;
group_gap_adj = 0;
- ref_type = reference_alias_ptr_type (DR_REF (first_dr));
+ ref_type = reference_alias_ptr_type (DR_REF (first_dr_info->dr));
}
- alignment_support_scheme = vect_supportable_dr_alignment (first_dr, false);
+ alignment_support_scheme
+ = vect_supportable_dr_alignment (first_dr_info, false);
gcc_assert (alignment_support_scheme);
vec_loop_masks *loop_masks
= (loop_vinfo && LOOP_VINFO_FULLY_MASKED_P (loop_vinfo)
@@ -8079,7 +8113,7 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
nested within an outer-loop that is being vectorized. */
if (nested_in_vect_loop
- && !multiple_p (DR_STEP_ALIGNMENT (dr),
+ && !multiple_p (DR_STEP_ALIGNMENT (dr_info->dr),
GET_MODE_SIZE (TYPE_MODE (vectype))))
{
gcc_assert (alignment_support_scheme != dr_explicit_realign_optimized);
@@ -8090,7 +8124,7 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
|| alignment_support_scheme == dr_explicit_realign)
&& !compute_in_loop)
{
- msq = vect_setup_realignment (first_stmt, gsi, &realignment_token,
+ msq = vect_setup_realignment (first_stmt_info, gsi, &realignment_token,
alignment_support_scheme, NULL_TREE,
&at_loop);
if (alignment_support_scheme == dr_explicit_realign_optimized)
@@ -8116,7 +8150,7 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
else if (memory_access_type == VMAT_GATHER_SCATTER)
{
aggr_type = elem_type;
- vect_get_strided_load_store_ops (stmt, loop_vinfo, &gs_info,
+ vect_get_strided_load_store_ops (stmt_info, loop_vinfo, &gs_info,
&bump, &vec_offset);
}
else
@@ -8125,7 +8159,8 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
aggr_type = build_array_type_nelts (elem_type, vec_num * nunits);
else
aggr_type = vectype;
- bump = vect_get_data_ptr_increment (dr, aggr_type, memory_access_type);
+ bump = vect_get_data_ptr_increment (dr_info, aggr_type,
+ memory_access_type);
}
tree vec_mask = NULL_TREE;
@@ -8133,57 +8168,55 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
poly_uint64 group_elt = 0;
for (j = 0; j < ncopies; j++)
{
+ stmt_vec_info new_stmt_info = NULL;
/* 1. Create the vector or array pointer update chain. */
if (j == 0)
{
bool simd_lane_access_p
= STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info);
if (simd_lane_access_p
- && TREE_CODE (DR_BASE_ADDRESS (first_dr)) == ADDR_EXPR
- && VAR_P (TREE_OPERAND (DR_BASE_ADDRESS (first_dr), 0))
- && integer_zerop (DR_OFFSET (first_dr))
- && integer_zerop (DR_INIT (first_dr))
+ && TREE_CODE (DR_BASE_ADDRESS (first_dr_info->dr)) == ADDR_EXPR
+ && VAR_P (TREE_OPERAND (DR_BASE_ADDRESS (first_dr_info->dr), 0))
+ && integer_zerop (DR_OFFSET (first_dr_info->dr))
+ && integer_zerop (DR_INIT (first_dr_info->dr))
&& alias_sets_conflict_p (get_alias_set (aggr_type),
get_alias_set (TREE_TYPE (ref_type)))
&& (alignment_support_scheme == dr_aligned
|| alignment_support_scheme == dr_unaligned_supported))
{
- dataref_ptr = unshare_expr (DR_BASE_ADDRESS (first_dr));
+ dataref_ptr = unshare_expr (DR_BASE_ADDRESS (first_dr_info->dr));
dataref_offset = build_int_cst (ref_type, 0);
- inv_p = false;
}
- else if (first_stmt_for_drptr
- && first_stmt != first_stmt_for_drptr)
+ else if (first_stmt_info_for_drptr
+ && first_stmt_info != first_stmt_info_for_drptr)
{
dataref_ptr
- = vect_create_data_ref_ptr (first_stmt_for_drptr, aggr_type,
- at_loop, offset, &dummy, gsi,
- &ptr_incr, simd_lane_access_p,
- &inv_p, byte_offset, bump);
+ = vect_create_data_ref_ptr (first_stmt_info_for_drptr,
+ aggr_type, at_loop, offset, &dummy,
+ gsi, &ptr_incr, simd_lane_access_p,
+ byte_offset, bump);
/* Adjust the pointer by the difference to first_stmt. */
data_reference_p ptrdr
- = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt_for_drptr));
- tree diff = fold_convert (sizetype,
- size_binop (MINUS_EXPR,
- DR_INIT (first_dr),
- DR_INIT (ptrdr)));
+ = STMT_VINFO_DATA_REF (first_stmt_info_for_drptr);
+ tree diff
+ = fold_convert (sizetype,
+ size_binop (MINUS_EXPR,
+ DR_INIT (first_dr_info->dr),
+ DR_INIT (ptrdr)));
dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi,
- stmt, diff);
+ stmt_info, diff);
}
else if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
- {
- vect_get_gather_scatter_ops (loop, stmt, &gs_info,
- &dataref_ptr, &vec_offset);
- inv_p = false;
- }
+ vect_get_gather_scatter_ops (loop, stmt_info, &gs_info,
+ &dataref_ptr, &vec_offset);
else
dataref_ptr
- = vect_create_data_ref_ptr (first_stmt, aggr_type, at_loop,
+ = vect_create_data_ref_ptr (first_stmt_info, aggr_type, at_loop,
offset, &dummy, gsi, &ptr_incr,
- simd_lane_access_p, &inv_p,
+ simd_lane_access_p,
byte_offset, bump);
if (mask)
- vec_mask = vect_get_vec_def_for_operand (mask, stmt,
+ vec_mask = vect_get_vec_def_for_operand (mask, stmt_info,
mask_vectype);
}
else
@@ -8192,13 +8225,12 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
dataref_offset = int_const_binop (PLUS_EXPR, dataref_offset,
bump);
else if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
- vec_offset = vect_get_vec_def_for_stmt_copy (gs_info.offset_dt,
- vec_offset);
+ vec_offset = vect_get_vec_def_for_stmt_copy (vinfo, vec_offset);
else
dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi,
- stmt, bump);
+ stmt_info, bump);
if (mask)
- vec_mask = vect_get_vec_def_for_stmt_copy (mask_dt, vec_mask);
+ vec_mask = vect_get_vec_def_for_stmt_copy (vinfo, vec_mask);
}
if (grouped_load || slp_perm)
@@ -8239,22 +8271,21 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
}
gimple_call_set_lhs (call, vec_array);
gimple_call_set_nothrow (call, true);
- new_stmt = call;
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ new_stmt_info = vect_finish_stmt_generation (stmt_info, call, gsi);
/* Extract each vector into an SSA_NAME. */
for (i = 0; i < vec_num; i++)
{
- new_temp = read_vector_array (stmt, gsi, scalar_dest,
+ new_temp = read_vector_array (stmt_info, gsi, scalar_dest,
vec_array, i);
dr_chain.quick_push (new_temp);
}
/* Record the mapping between SSA_NAMEs and statements. */
- vect_record_grouped_load_vectors (stmt, dr_chain);
+ vect_record_grouped_load_vectors (stmt_info, dr_chain);
/* Record that VEC_ARRAY is now dead. */
- vect_clobber_variable (stmt, gsi, vec_array);
+ vect_clobber_variable (stmt_info, gsi, vec_array);
}
else
{
@@ -8272,9 +8303,10 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
if (i > 0)
dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi,
- stmt, bump);
+ stmt_info, bump);
/* 2. Create the vector-load in the loop. */
+ gimple *new_stmt = NULL;
switch (alignment_support_scheme)
{
case dr_aligned:
@@ -8300,19 +8332,20 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
break;
}
- align = DR_TARGET_ALIGNMENT (dr);
+ align = DR_TARGET_ALIGNMENT (dr_info);
if (alignment_support_scheme == dr_aligned)
{
- gcc_assert (aligned_access_p (first_dr));
+ gcc_assert (aligned_access_p (first_dr_info));
misalign = 0;
}
- else if (DR_MISALIGNMENT (first_dr) == -1)
+ else if (DR_MISALIGNMENT (first_dr_info) == -1)
{
- align = dr_alignment (vect_dr_behavior (first_dr));
+ align = dr_alignment
+ (vect_dr_behavior (first_dr_info));
misalign = 0;
}
else
- misalign = DR_MISALIGNMENT (first_dr);
+ misalign = DR_MISALIGNMENT (first_dr_info);
if (dataref_offset == NULL_TREE
&& TREE_CODE (dataref_ptr) == SSA_NAME)
set_ptr_info_alignment (get_ptr_info (dataref_ptr),
@@ -8339,7 +8372,7 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
: build_int_cst (ref_type, 0));
if (alignment_support_scheme == dr_aligned)
;
- else if (DR_MISALIGNMENT (first_dr) == -1)
+ else if (DR_MISALIGNMENT (first_dr_info) == -1)
TREE_TYPE (data_ref)
= build_aligned_type (TREE_TYPE (data_ref),
align * BITS_PER_UNIT);
@@ -8357,7 +8390,7 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
tree vs = size_int (TYPE_VECTOR_SUBPARTS (vectype));
if (compute_in_loop)
- msq = vect_setup_realignment (first_stmt, gsi,
+ msq = vect_setup_realignment (first_stmt_info, gsi,
&realignment_token,
dr_explicit_realign,
dataref_ptr, NULL);
@@ -8366,38 +8399,39 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
ptr = copy_ssa_name (dataref_ptr);
else
ptr = make_ssa_name (TREE_TYPE (dataref_ptr));
- unsigned int align = DR_TARGET_ALIGNMENT (first_dr);
+ unsigned int align = DR_TARGET_ALIGNMENT (first_dr_info);
new_stmt = gimple_build_assign
(ptr, BIT_AND_EXPR, dataref_ptr,
build_int_cst
(TREE_TYPE (dataref_ptr),
-(HOST_WIDE_INT) align));
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
data_ref
= build2 (MEM_REF, vectype, ptr,
build_int_cst (ref_type, 0));
- vect_copy_ref_info (data_ref, DR_REF (first_dr));
+ vect_copy_ref_info (data_ref, DR_REF (first_dr_info->dr));
vec_dest = vect_create_destination_var (scalar_dest,
vectype);
new_stmt = gimple_build_assign (vec_dest, data_ref);
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_assign_set_lhs (new_stmt, new_temp);
- gimple_set_vdef (new_stmt, gimple_vdef (stmt));
- gimple_set_vuse (new_stmt, gimple_vuse (stmt));
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ gimple_set_vdef (new_stmt, gimple_vdef (stmt_info->stmt));
+ gimple_set_vuse (new_stmt, gimple_vuse (stmt_info->stmt));
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
msq = new_temp;
bump = size_binop (MULT_EXPR, vs,
TYPE_SIZE_UNIT (elem_type));
bump = size_binop (MINUS_EXPR, bump, size_one_node);
- ptr = bump_vector_ptr (dataref_ptr, NULL, gsi, stmt, bump);
+ ptr = bump_vector_ptr (dataref_ptr, NULL, gsi,
+ stmt_info, bump);
new_stmt = gimple_build_assign
(NULL_TREE, BIT_AND_EXPR, ptr,
build_int_cst
(TREE_TYPE (ptr), -(HOST_WIDE_INT) align));
ptr = copy_ssa_name (ptr, new_stmt);
gimple_assign_set_lhs (new_stmt, ptr);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
data_ref
= build2 (MEM_REF, vectype, ptr,
build_int_cst (ref_type, 0));
@@ -8409,12 +8443,12 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
new_temp = copy_ssa_name (dataref_ptr);
else
new_temp = make_ssa_name (TREE_TYPE (dataref_ptr));
- unsigned int align = DR_TARGET_ALIGNMENT (first_dr);
+ unsigned int align = DR_TARGET_ALIGNMENT (first_dr_info);
new_stmt = gimple_build_assign
(new_temp, BIT_AND_EXPR, dataref_ptr,
build_int_cst (TREE_TYPE (dataref_ptr),
-(HOST_WIDE_INT) align));
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
data_ref
= build2 (MEM_REF, vectype, new_temp,
build_int_cst (ref_type, 0));
@@ -8427,12 +8461,13 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
/* DATA_REF is null if we've already built the statement. */
if (data_ref)
{
- vect_copy_ref_info (data_ref, DR_REF (first_dr));
+ vect_copy_ref_info (data_ref, DR_REF (first_dr_info->dr));
new_stmt = gimple_build_assign (vec_dest, data_ref);
}
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_set_lhs (new_stmt, new_temp);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
/* 3. Handle explicit realignment if necessary/supported.
Create in loop:
@@ -8448,7 +8483,8 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
msq, lsq, realignment_token);
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_assign_set_lhs (new_stmt, new_temp);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
if (alignment_support_scheme == dr_explicit_realign_optimized)
{
@@ -8461,52 +8497,12 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
}
}
- /* 4. Handle invariant-load. */
- if (inv_p && !bb_vinfo)
- {
- gcc_assert (!grouped_load);
- /* If we have versioned for aliasing or the loop doesn't
- have any data dependencies that would preclude this,
- then we are sure this is a loop invariant load and
- thus we can insert it on the preheader edge. */
- if (LOOP_VINFO_NO_DATA_DEPENDENCIES (loop_vinfo)
- && !nested_in_vect_loop
- && hoist_defs_of_uses (stmt, loop))
- {
- if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "hoisting out of the vectorized "
- "loop: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
- }
- tree tem = copy_ssa_name (scalar_dest);
- gsi_insert_on_edge_immediate
- (loop_preheader_edge (loop),
- gimple_build_assign (tem,
- unshare_expr
- (gimple_assign_rhs1 (stmt))));
- new_temp = vect_init_vector (stmt, tem, vectype, NULL);
- new_stmt = SSA_NAME_DEF_STMT (new_temp);
- set_vinfo_for_stmt (new_stmt,
- new_stmt_vec_info (new_stmt, vinfo));
- }
- else
- {
- gimple_stmt_iterator gsi2 = *gsi;
- gsi_next (&gsi2);
- new_temp = vect_init_vector (stmt, scalar_dest,
- vectype, &gsi2);
- new_stmt = SSA_NAME_DEF_STMT (new_temp);
- }
- }
-
if (memory_access_type == VMAT_CONTIGUOUS_REVERSE)
{
tree perm_mask = perm_mask_for_reverse (vectype);
new_temp = permute_vec_elements (new_temp, new_temp,
- perm_mask, stmt, gsi);
- new_stmt = SSA_NAME_DEF_STMT (new_temp);
+ perm_mask, stmt_info, gsi);
+ new_stmt_info = vinfo->lookup_def (new_temp);
}
/* Collect vector loads and later create their permutation in
@@ -8516,7 +8512,7 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
/* Store vector loads in the corresponding SLP_NODE. */
if (slp && !slp_perm)
- SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info);
/* With SLP permutation we load the gaps as well, without
we need to skip the gaps after we manage to fully load
@@ -8531,7 +8527,7 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
* group_gap_adj);
tree bump = wide_int_to_tree (sizetype, bump_val);
dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi,
- stmt, bump);
+ stmt_info, bump);
group_elt = 0;
}
}
@@ -8544,7 +8540,7 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
* group_gap_adj);
tree bump = wide_int_to_tree (sizetype, bump_val);
dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi,
- stmt, bump);
+ stmt_info, bump);
}
}
@@ -8567,16 +8563,17 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
if (grouped_load)
{
if (memory_access_type != VMAT_LOAD_STORE_LANES)
- vect_transform_grouped_load (stmt, dr_chain, group_size, gsi);
+ vect_transform_grouped_load (stmt_info, dr_chain,
+ group_size, gsi);
*vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
}
else
{
if (j == 0)
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info;
else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
- prev_stmt_info = vinfo_for_stmt (new_stmt);
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
+ prev_stmt_info = new_stmt_info;
}
}
dr_chain.release ();
@@ -8670,27 +8667,28 @@ vect_is_simple_cond (tree cond, vec_info *vinfo,
/* vectorizable_condition.
- Check if STMT is conditional modify expression that can be vectorized.
- If VEC_STMT is also passed, vectorize the STMT: create a vectorized
+ Check if STMT_INFO is conditional modify expression that can be vectorized.
+ If VEC_STMT is also passed, vectorize STMT_INFO: create a vectorized
stmt using VEC_COND_EXPR to replace it, put it in VEC_STMT, and insert it
at GSI.
- When STMT is vectorized as nested cycle, REDUC_DEF is the vector variable
- to be used at REDUC_INDEX (in then clause if REDUC_INDEX is 1, and in
- else clause if it is 2).
+ When STMT_INFO is vectorized as a nested cycle, REDUC_DEF is the vector
+ variable to be used at REDUC_INDEX (in then clause if REDUC_INDEX is 1,
+ and in else clause if it is 2).
- Return FALSE if not a vectorizable STMT, TRUE otherwise. */
+ Return true if STMT_INFO is vectorizable in this way. */
bool
-vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
- gimple **vec_stmt, tree reduc_def, int reduc_index,
- slp_tree slp_node, stmt_vector_for_cost *cost_vec)
+vectorizable_condition (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ stmt_vec_info *vec_stmt, tree reduc_def,
+ int reduc_index, slp_tree slp_node,
+ stmt_vector_for_cost *cost_vec)
{
+ vec_info *vinfo = stmt_info->vinfo;
tree scalar_dest = NULL_TREE;
tree vec_dest = NULL_TREE;
tree cond_expr, cond_expr0 = NULL_TREE, cond_expr1 = NULL_TREE;
tree then_clause, else_clause;
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
tree comp_vectype = NULL_TREE;
tree vec_cond_lhs = NULL_TREE, vec_cond_rhs = NULL_TREE;
tree vec_then_clause = NULL_TREE, vec_else_clause = NULL_TREE;
@@ -8739,7 +8737,8 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
}
/* Is vectorizable conditional operation? */
- if (!is_gimple_assign (stmt))
+ gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt);
+ if (!stmt)
return false;
code = gimple_assign_rhs_code (stmt);
@@ -8881,7 +8880,7 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
/* Handle cond expr. */
for (j = 0; j < ncopies; j++)
{
- gimple *new_stmt = NULL;
+ stmt_vec_info new_stmt_info = NULL;
if (j == 0)
{
if (slp_node)
@@ -8910,7 +8909,7 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
if (masked)
{
vec_cond_lhs
- = vect_get_vec_def_for_operand (cond_expr, stmt,
+ = vect_get_vec_def_for_operand (cond_expr, stmt_info,
comp_vectype);
vect_is_simple_use (cond_expr, stmt_info->vinfo, &dts[0]);
}
@@ -8918,12 +8917,12 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
{
vec_cond_lhs
= vect_get_vec_def_for_operand (cond_expr0,
- stmt, comp_vectype);
+ stmt_info, comp_vectype);
vect_is_simple_use (cond_expr0, loop_vinfo, &dts[0]);
vec_cond_rhs
= vect_get_vec_def_for_operand (cond_expr1,
- stmt, comp_vectype);
+ stmt_info, comp_vectype);
vect_is_simple_use (cond_expr1, loop_vinfo, &dts[1]);
}
if (reduc_index == 1)
@@ -8931,7 +8930,7 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
else
{
vec_then_clause = vect_get_vec_def_for_operand (then_clause,
- stmt);
+ stmt_info);
vect_is_simple_use (then_clause, loop_vinfo, &dts[2]);
}
if (reduc_index == 2)
@@ -8939,7 +8938,7 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
else
{
vec_else_clause = vect_get_vec_def_for_operand (else_clause,
- stmt);
+ stmt_info);
vect_is_simple_use (else_clause, loop_vinfo, &dts[3]);
}
}
@@ -8947,16 +8946,14 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
else
{
vec_cond_lhs
- = vect_get_vec_def_for_stmt_copy (dts[0],
- vec_oprnds0.pop ());
+ = vect_get_vec_def_for_stmt_copy (vinfo, vec_oprnds0.pop ());
if (!masked)
vec_cond_rhs
- = vect_get_vec_def_for_stmt_copy (dts[1],
- vec_oprnds1.pop ());
+ = vect_get_vec_def_for_stmt_copy (vinfo, vec_oprnds1.pop ());
- vec_then_clause = vect_get_vec_def_for_stmt_copy (dts[2],
+ vec_then_clause = vect_get_vec_def_for_stmt_copy (vinfo,
vec_oprnds2.pop ());
- vec_else_clause = vect_get_vec_def_for_stmt_copy (dts[3],
+ vec_else_clause = vect_get_vec_def_for_stmt_copy (vinfo,
vec_oprnds3.pop ());
}
@@ -8986,6 +8983,7 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
else
{
new_temp = make_ssa_name (vec_cmp_type);
+ gassign *new_stmt;
if (bitop1 == BIT_NOT_EXPR)
new_stmt = gimple_build_assign (new_temp, bitop1,
vec_cond_rhs);
@@ -8993,7 +8991,7 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
new_stmt
= gimple_build_assign (new_temp, bitop1, vec_cond_lhs,
vec_cond_rhs);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
if (bitop2 == NOP_EXPR)
vec_compare = new_temp;
else if (bitop2 == BIT_NOT_EXPR)
@@ -9008,7 +9006,7 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
new_stmt
= gimple_build_assign (vec_compare, bitop2,
vec_cond_lhs, new_temp);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
}
}
}
@@ -9017,50 +9015,53 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
if (!is_gimple_val (vec_compare))
{
tree vec_compare_name = make_ssa_name (vec_cmp_type);
- new_stmt = gimple_build_assign (vec_compare_name,
- vec_compare);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ gassign *new_stmt = gimple_build_assign (vec_compare_name,
+ vec_compare);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
vec_compare = vec_compare_name;
}
gcc_assert (reduc_index == 2);
- new_stmt = gimple_build_call_internal
+ gcall *new_stmt = gimple_build_call_internal
(IFN_FOLD_EXTRACT_LAST, 3, else_clause, vec_compare,
vec_then_clause);
gimple_call_set_lhs (new_stmt, scalar_dest);
SSA_NAME_DEF_STMT (scalar_dest) = new_stmt;
- if (stmt == gsi_stmt (*gsi))
- vect_finish_replace_stmt (stmt, new_stmt);
+ if (stmt_info->stmt == gsi_stmt (*gsi))
+ new_stmt_info = vect_finish_replace_stmt (stmt_info, new_stmt);
else
{
/* In this case we're moving the definition to later in the
block. That doesn't matter because the only uses of the
lhs are in phi statements. */
- gimple_stmt_iterator old_gsi = gsi_for_stmt (stmt);
+ gimple_stmt_iterator old_gsi
+ = gsi_for_stmt (stmt_info->stmt);
gsi_remove (&old_gsi, true);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
}
}
else
{
new_temp = make_ssa_name (vec_dest);
- new_stmt = gimple_build_assign (new_temp, VEC_COND_EXPR,
- vec_compare, vec_then_clause,
- vec_else_clause);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ gassign *new_stmt
+ = gimple_build_assign (new_temp, VEC_COND_EXPR, vec_compare,
+ vec_then_clause, vec_else_clause);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
}
if (slp_node)
- SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info);
}
if (slp_node)
continue;
- if (j == 0)
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
- else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
+ if (j == 0)
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info;
+ else
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
- prev_stmt_info = vinfo_for_stmt (new_stmt);
+ prev_stmt_info = new_stmt_info;
}
vec_oprnds0.release ();
@@ -9073,19 +9074,19 @@ vectorizable_condition (gimple *stmt, gimple_stmt_iterator *gsi,
/* vectorizable_comparison.
- Check if STMT is comparison expression that can be vectorized.
- If VEC_STMT is also passed, vectorize the STMT: create a vectorized
+ Check if STMT_INFO is comparison expression that can be vectorized.
+ If VEC_STMT is also passed, vectorize STMT_INFO: create a vectorized
comparison, put it in VEC_STMT, and insert it at GSI.
- Return FALSE if not a vectorizable STMT, TRUE otherwise. */
+ Return true if STMT_INFO is vectorizable in this way. */
static bool
-vectorizable_comparison (gimple *stmt, gimple_stmt_iterator *gsi,
- gimple **vec_stmt, tree reduc_def,
+vectorizable_comparison (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ stmt_vec_info *vec_stmt, tree reduc_def,
slp_tree slp_node, stmt_vector_for_cost *cost_vec)
{
+ vec_info *vinfo = stmt_info->vinfo;
tree lhs, rhs1, rhs2;
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
tree vectype1 = NULL_TREE, vectype2 = NULL_TREE;
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
tree vec_rhs1 = NULL_TREE, vec_rhs2 = NULL_TREE;
@@ -9132,7 +9133,8 @@ vectorizable_comparison (gimple *stmt, gimple_stmt_iterator *gsi,
return false;
}
- if (!is_gimple_assign (stmt))
+ gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt);
+ if (!stmt)
return false;
code = gimple_assign_rhs_code (stmt);
@@ -9256,7 +9258,7 @@ vectorizable_comparison (gimple *stmt, gimple_stmt_iterator *gsi,
/* Handle cmp expr. */
for (j = 0; j < ncopies; j++)
{
- gassign *new_stmt = NULL;
+ stmt_vec_info new_stmt_info = NULL;
if (j == 0)
{
if (slp_node)
@@ -9272,15 +9274,17 @@ vectorizable_comparison (gimple *stmt, gimple_stmt_iterator *gsi,
}
else
{
- vec_rhs1 = vect_get_vec_def_for_operand (rhs1, stmt, vectype);
- vec_rhs2 = vect_get_vec_def_for_operand (rhs2, stmt, vectype);
+ vec_rhs1 = vect_get_vec_def_for_operand (rhs1, stmt_info,
+ vectype);
+ vec_rhs2 = vect_get_vec_def_for_operand (rhs2, stmt_info,
+ vectype);
}
}
else
{
- vec_rhs1 = vect_get_vec_def_for_stmt_copy (dts[0],
+ vec_rhs1 = vect_get_vec_def_for_stmt_copy (vinfo,
vec_oprnds0.pop ());
- vec_rhs2 = vect_get_vec_def_for_stmt_copy (dts[1],
+ vec_rhs2 = vect_get_vec_def_for_stmt_copy (vinfo,
vec_oprnds1.pop ());
}
@@ -9298,18 +9302,21 @@ vectorizable_comparison (gimple *stmt, gimple_stmt_iterator *gsi,
new_temp = make_ssa_name (mask);
if (bitop1 == NOP_EXPR)
{
- new_stmt = gimple_build_assign (new_temp, code,
- vec_rhs1, vec_rhs2);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ gassign *new_stmt = gimple_build_assign (new_temp, code,
+ vec_rhs1, vec_rhs2);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
}
else
{
+ gassign *new_stmt;
if (bitop1 == BIT_NOT_EXPR)
new_stmt = gimple_build_assign (new_temp, bitop1, vec_rhs2);
else
new_stmt = gimple_build_assign (new_temp, bitop1, vec_rhs1,
vec_rhs2);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
if (bitop2 != NOP_EXPR)
{
tree res = make_ssa_name (mask);
@@ -9318,22 +9325,23 @@ vectorizable_comparison (gimple *stmt, gimple_stmt_iterator *gsi,
else
new_stmt = gimple_build_assign (res, bitop2, vec_rhs1,
new_temp);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
}
}
if (slp_node)
- SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info);
}
if (slp_node)
continue;
if (j == 0)
- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info;
else
- STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
- prev_stmt_info = vinfo_for_stmt (new_stmt);
+ prev_stmt_info = new_stmt_info;
}
vec_oprnds0.release ();
@@ -9344,30 +9352,29 @@ vectorizable_comparison (gimple *stmt, gimple_stmt_iterator *gsi,
/* If SLP_NODE is nonnull, return true if vectorizable_live_operation
can handle all live statements in the node. Otherwise return true
- if STMT is not live or if vectorizable_live_operation can handle it.
+ if STMT_INFO is not live or if vectorizable_live_operation can handle it.
GSI and VEC_STMT are as for vectorizable_live_operation. */
static bool
-can_vectorize_live_stmts (gimple *stmt, gimple_stmt_iterator *gsi,
- slp_tree slp_node, gimple **vec_stmt,
+can_vectorize_live_stmts (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ slp_tree slp_node, stmt_vec_info *vec_stmt,
stmt_vector_for_cost *cost_vec)
{
if (slp_node)
{
- gimple *slp_stmt;
+ stmt_vec_info slp_stmt_info;
unsigned int i;
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (slp_node), i, slp_stmt)
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (slp_node), i, slp_stmt_info)
{
- stmt_vec_info slp_stmt_info = vinfo_for_stmt (slp_stmt);
if (STMT_VINFO_LIVE_P (slp_stmt_info)
- && !vectorizable_live_operation (slp_stmt, gsi, slp_node, i,
+ && !vectorizable_live_operation (slp_stmt_info, gsi, slp_node, i,
vec_stmt, cost_vec))
return false;
}
}
- else if (STMT_VINFO_LIVE_P (vinfo_for_stmt (stmt))
- && !vectorizable_live_operation (stmt, gsi, slp_node, -1, vec_stmt,
- cost_vec))
+ else if (STMT_VINFO_LIVE_P (stmt_info)
+ && !vectorizable_live_operation (stmt_info, gsi, slp_node, -1,
+ vec_stmt, cost_vec))
return false;
return true;
@@ -9376,23 +9383,21 @@ can_vectorize_live_stmts (gimple *stmt, gimple_stmt_iterator *gsi,
/* Make sure the statement is vectorizable. */
bool
-vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node,
- slp_instance node_instance, stmt_vector_for_cost *cost_vec)
+vect_analyze_stmt (stmt_vec_info stmt_info, bool *need_to_vectorize,
+ slp_tree node, slp_instance node_instance,
+ stmt_vector_for_cost *cost_vec)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ vec_info *vinfo = stmt_info->vinfo;
bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
enum vect_relevant relevance = STMT_VINFO_RELEVANT (stmt_info);
bool ok;
- gimple *pattern_stmt;
gimple_seq pattern_def_seq;
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "==> examining statement: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "==> examining statement: %G",
+ stmt_info->stmt);
- if (gimple_has_volatile_ops (stmt))
+ if (gimple_has_volatile_ops (stmt_info->stmt))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -9409,19 +9414,18 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node,
for (si = gsi_start (pattern_def_seq); !gsi_end_p (si); gsi_next (&si))
{
- gimple *pattern_def_stmt = gsi_stmt (si);
- if (STMT_VINFO_RELEVANT_P (vinfo_for_stmt (pattern_def_stmt))
- || STMT_VINFO_LIVE_P (vinfo_for_stmt (pattern_def_stmt)))
+ stmt_vec_info pattern_def_stmt_info
+ = vinfo->lookup_stmt (gsi_stmt (si));
+ if (STMT_VINFO_RELEVANT_P (pattern_def_stmt_info)
+ || STMT_VINFO_LIVE_P (pattern_def_stmt_info))
{
/* Analyze def stmt of STMT if it's a pattern stmt. */
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "==> examining pattern def statement: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_def_stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "==> examining pattern def statement: %G",
+ pattern_def_stmt_info->stmt);
- if (!vect_analyze_stmt (pattern_def_stmt,
+ if (!vect_analyze_stmt (pattern_def_stmt_info,
need_to_vectorize, node, node_instance,
cost_vec))
return false;
@@ -9443,24 +9447,21 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node,
traversal, don't analyze pattern stmts instead, the pattern stmts
already will be part of SLP instance. */
- pattern_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
+ stmt_vec_info pattern_stmt_info = STMT_VINFO_RELATED_STMT (stmt_info);
if (!STMT_VINFO_RELEVANT_P (stmt_info)
&& !STMT_VINFO_LIVE_P (stmt_info))
{
if (STMT_VINFO_IN_PATTERN_P (stmt_info)
- && pattern_stmt
- && (STMT_VINFO_RELEVANT_P (vinfo_for_stmt (pattern_stmt))
- || STMT_VINFO_LIVE_P (vinfo_for_stmt (pattern_stmt))))
+ && pattern_stmt_info
+ && (STMT_VINFO_RELEVANT_P (pattern_stmt_info)
+ || STMT_VINFO_LIVE_P (pattern_stmt_info)))
{
/* Analyze PATTERN_STMT instead of the original stmt. */
- stmt = pattern_stmt;
- stmt_info = vinfo_for_stmt (pattern_stmt);
+ stmt_info = pattern_stmt_info;
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "==> examining pattern statement: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "==> examining pattern statement: %G",
+ stmt_info->stmt);
}
else
{
@@ -9472,19 +9473,17 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node,
}
else if (STMT_VINFO_IN_PATTERN_P (stmt_info)
&& node == NULL
- && pattern_stmt
- && (STMT_VINFO_RELEVANT_P (vinfo_for_stmt (pattern_stmt))
- || STMT_VINFO_LIVE_P (vinfo_for_stmt (pattern_stmt))))
+ && pattern_stmt_info
+ && (STMT_VINFO_RELEVANT_P (pattern_stmt_info)
+ || STMT_VINFO_LIVE_P (pattern_stmt_info)))
{
/* Analyze PATTERN_STMT too. */
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "==> examining pattern statement: ");
- dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "==> examining pattern statement: %G",
+ pattern_stmt_info->stmt);
- if (!vect_analyze_stmt (pattern_stmt, need_to_vectorize, node,
+ if (!vect_analyze_stmt (pattern_stmt_info, need_to_vectorize, node,
node_instance, cost_vec))
return false;
}
@@ -9517,10 +9516,11 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node,
if (STMT_VINFO_RELEVANT_P (stmt_info))
{
- gcc_assert (!VECTOR_MODE_P (TYPE_MODE (gimple_expr_type (stmt))));
+ tree type = gimple_expr_type (stmt_info->stmt);
+ gcc_assert (!VECTOR_MODE_P (TYPE_MODE (type)));
+ gcall *call = dyn_cast <gcall *> (stmt_info->stmt);
gcc_assert (STMT_VINFO_VECTYPE (stmt_info)
- || (is_gimple_call (stmt)
- && gimple_call_lhs (stmt) == NULL_TREE));
+ || (call && gimple_call_lhs (call) == NULL_TREE));
*need_to_vectorize = true;
}
@@ -9535,46 +9535,49 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node,
if (!bb_vinfo
&& (STMT_VINFO_RELEVANT_P (stmt_info)
|| STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def))
- ok = (vectorizable_simd_clone_call (stmt, NULL, NULL, node, cost_vec)
- || vectorizable_conversion (stmt, NULL, NULL, node, cost_vec)
- || vectorizable_shift (stmt, NULL, NULL, node, cost_vec)
- || vectorizable_operation (stmt, NULL, NULL, node, cost_vec)
- || vectorizable_assignment (stmt, NULL, NULL, node, cost_vec)
- || vectorizable_load (stmt, NULL, NULL, node, node_instance, cost_vec)
- || vectorizable_call (stmt, NULL, NULL, node, cost_vec)
- || vectorizable_store (stmt, NULL, NULL, node, cost_vec)
- || vectorizable_reduction (stmt, NULL, NULL, node, node_instance,
+ ok = (vectorizable_simd_clone_call (stmt_info, NULL, NULL, node, cost_vec)
+ || vectorizable_conversion (stmt_info, NULL, NULL, node, cost_vec)
+ || vectorizable_shift (stmt_info, NULL, NULL, node, cost_vec)
+ || vectorizable_operation (stmt_info, NULL, NULL, node, cost_vec)
+ || vectorizable_assignment (stmt_info, NULL, NULL, node, cost_vec)
+ || vectorizable_load (stmt_info, NULL, NULL, node, node_instance,
+ cost_vec)
+ || vectorizable_call (stmt_info, NULL, NULL, node, cost_vec)
+ || vectorizable_store (stmt_info, NULL, NULL, node, cost_vec)
+ || vectorizable_reduction (stmt_info, NULL, NULL, node,
+ node_instance, cost_vec)
+ || vectorizable_induction (stmt_info, NULL, NULL, node, cost_vec)
+ || vectorizable_condition (stmt_info, NULL, NULL, NULL, 0, node,
cost_vec)
- || vectorizable_induction (stmt, NULL, NULL, node, cost_vec)
- || vectorizable_condition (stmt, NULL, NULL, NULL, 0, node, cost_vec)
- || vectorizable_comparison (stmt, NULL, NULL, NULL, node, cost_vec));
+ || vectorizable_comparison (stmt_info, NULL, NULL, NULL, node,
+ cost_vec));
else
{
if (bb_vinfo)
- ok = (vectorizable_simd_clone_call (stmt, NULL, NULL, node, cost_vec)
- || vectorizable_conversion (stmt, NULL, NULL, node, cost_vec)
- || vectorizable_shift (stmt, NULL, NULL, node, cost_vec)
- || vectorizable_operation (stmt, NULL, NULL, node, cost_vec)
- || vectorizable_assignment (stmt, NULL, NULL, node, cost_vec)
- || vectorizable_load (stmt, NULL, NULL, node, node_instance,
+ ok = (vectorizable_simd_clone_call (stmt_info, NULL, NULL, node,
+ cost_vec)
+ || vectorizable_conversion (stmt_info, NULL, NULL, node,
+ cost_vec)
+ || vectorizable_shift (stmt_info, NULL, NULL, node, cost_vec)
+ || vectorizable_operation (stmt_info, NULL, NULL, node, cost_vec)
+ || vectorizable_assignment (stmt_info, NULL, NULL, node,
+ cost_vec)
+ || vectorizable_load (stmt_info, NULL, NULL, node, node_instance,
cost_vec)
- || vectorizable_call (stmt, NULL, NULL, node, cost_vec)
- || vectorizable_store (stmt, NULL, NULL, node, cost_vec)
- || vectorizable_condition (stmt, NULL, NULL, NULL, 0, node,
+ || vectorizable_call (stmt_info, NULL, NULL, node, cost_vec)
+ || vectorizable_store (stmt_info, NULL, NULL, node, cost_vec)
+ || vectorizable_condition (stmt_info, NULL, NULL, NULL, 0, node,
cost_vec)
- || vectorizable_comparison (stmt, NULL, NULL, NULL, node,
+ || vectorizable_comparison (stmt_info, NULL, NULL, NULL, node,
cost_vec));
}
if (!ok)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: relevant stmt not ");
- dump_printf (MSG_MISSED_OPTIMIZATION, "supported: ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: relevant stmt not supported: %G",
+ stmt_info->stmt);
return false;
}
@@ -9583,14 +9586,12 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node,
need extra handling, except for vectorizable reductions. */
if (!bb_vinfo
&& STMT_VINFO_TYPE (stmt_info) != reduc_vec_info_type
- && !can_vectorize_live_stmts (stmt, NULL, node, NULL, cost_vec))
+ && !can_vectorize_live_stmts (stmt_info, NULL, node, NULL, cost_vec))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: live stmt not supported: ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: live stmt not supported: %G",
+ stmt_info->stmt);
return false;
}
@@ -9601,63 +9602,67 @@ vect_analyze_stmt (gimple *stmt, bool *need_to_vectorize, slp_tree node,
/* Function vect_transform_stmt.
- Create a vectorized stmt to replace STMT, and insert it at BSI. */
+ Create a vectorized stmt to replace STMT_INFO, and insert it at BSI. */
bool
-vect_transform_stmt (gimple *stmt, gimple_stmt_iterator *gsi,
- bool *grouped_store, slp_tree slp_node,
- slp_instance slp_node_instance)
+vect_transform_stmt (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ slp_tree slp_node, slp_instance slp_node_instance)
{
+ vec_info *vinfo = stmt_info->vinfo;
bool is_store = false;
- gimple *vec_stmt = NULL;
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ stmt_vec_info vec_stmt = NULL;
bool done;
gcc_assert (slp_node || !PURE_SLP_STMT (stmt_info));
- gimple *old_vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
+ stmt_vec_info old_vec_stmt_info = STMT_VINFO_VEC_STMT (stmt_info);
bool nested_p = (STMT_VINFO_LOOP_VINFO (stmt_info)
&& nested_in_vect_loop_p
(LOOP_VINFO_LOOP (STMT_VINFO_LOOP_VINFO (stmt_info)),
- stmt));
+ stmt_info));
+ gimple *stmt = stmt_info->stmt;
switch (STMT_VINFO_TYPE (stmt_info))
{
case type_demotion_vec_info_type:
case type_promotion_vec_info_type:
case type_conversion_vec_info_type:
- done = vectorizable_conversion (stmt, gsi, &vec_stmt, slp_node, NULL);
+ done = vectorizable_conversion (stmt_info, gsi, &vec_stmt, slp_node,
+ NULL);
gcc_assert (done);
break;
case induc_vec_info_type:
- done = vectorizable_induction (stmt, gsi, &vec_stmt, slp_node, NULL);
+ done = vectorizable_induction (stmt_info, gsi, &vec_stmt, slp_node,
+ NULL);
gcc_assert (done);
break;
case shift_vec_info_type:
- done = vectorizable_shift (stmt, gsi, &vec_stmt, slp_node, NULL);
+ done = vectorizable_shift (stmt_info, gsi, &vec_stmt, slp_node, NULL);
gcc_assert (done);
break;
case op_vec_info_type:
- done = vectorizable_operation (stmt, gsi, &vec_stmt, slp_node, NULL);
+ done = vectorizable_operation (stmt_info, gsi, &vec_stmt, slp_node,
+ NULL);
gcc_assert (done);
break;
case assignment_vec_info_type:
- done = vectorizable_assignment (stmt, gsi, &vec_stmt, slp_node, NULL);
+ done = vectorizable_assignment (stmt_info, gsi, &vec_stmt, slp_node,
+ NULL);
gcc_assert (done);
break;
case load_vec_info_type:
- done = vectorizable_load (stmt, gsi, &vec_stmt, slp_node,
+ done = vectorizable_load (stmt_info, gsi, &vec_stmt, slp_node,
slp_node_instance, NULL);
gcc_assert (done);
break;
case store_vec_info_type:
- done = vectorizable_store (stmt, gsi, &vec_stmt, slp_node, NULL);
+ done = vectorizable_store (stmt_info, gsi, &vec_stmt, slp_node, NULL);
gcc_assert (done);
if (STMT_VINFO_GROUPED_ACCESS (stmt_info) && !slp_node)
{
@@ -9665,9 +9670,7 @@ vect_transform_stmt (gimple *stmt, gimple_stmt_iterator *gsi,
last store in the chain is reached. Store stmts before the last
one are skipped, and there vec_stmt_info shouldn't be freed
meanwhile. */
- *grouped_store = true;
- stmt_vec_info group_info
- = vinfo_for_stmt (DR_GROUP_FIRST_ELEMENT (stmt_info));
+ stmt_vec_info group_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
if (DR_GROUP_STORE_COUNT (group_info) == DR_GROUP_SIZE (group_info))
is_store = true;
}
@@ -9676,27 +9679,30 @@ vect_transform_stmt (gimple *stmt, gimple_stmt_iterator *gsi,
break;
case condition_vec_info_type:
- done = vectorizable_condition (stmt, gsi, &vec_stmt, NULL, 0, slp_node, NULL);
+ done = vectorizable_condition (stmt_info, gsi, &vec_stmt, NULL, 0,
+ slp_node, NULL);
gcc_assert (done);
break;
case comparison_vec_info_type:
- done = vectorizable_comparison (stmt, gsi, &vec_stmt, NULL, slp_node, NULL);
+ done = vectorizable_comparison (stmt_info, gsi, &vec_stmt, NULL,
+ slp_node, NULL);
gcc_assert (done);
break;
case call_vec_info_type:
- done = vectorizable_call (stmt, gsi, &vec_stmt, slp_node, NULL);
+ done = vectorizable_call (stmt_info, gsi, &vec_stmt, slp_node, NULL);
stmt = gsi_stmt (*gsi);
break;
case call_simd_clone_vec_info_type:
- done = vectorizable_simd_clone_call (stmt, gsi, &vec_stmt, slp_node, NULL);
+ done = vectorizable_simd_clone_call (stmt_info, gsi, &vec_stmt,
+ slp_node, NULL);
stmt = gsi_stmt (*gsi);
break;
case reduc_vec_info_type:
- done = vectorizable_reduction (stmt, gsi, &vec_stmt, slp_node,
+ done = vectorizable_reduction (stmt_info, gsi, &vec_stmt, slp_node,
slp_node_instance, NULL);
gcc_assert (done);
break;
@@ -9715,7 +9721,7 @@ vect_transform_stmt (gimple *stmt, gimple_stmt_iterator *gsi,
This would break hybrid SLP vectorization. */
if (slp_node)
gcc_assert (!vec_stmt
- && STMT_VINFO_VEC_STMT (stmt_info) == old_vec_stmt);
+ && STMT_VINFO_VEC_STMT (stmt_info) == old_vec_stmt_info);
/* Handle inner-loop stmts whose DEF is used in the loop-nest that
is being vectorized, but outside the immediately enclosing loop. */
@@ -9731,7 +9737,6 @@ vect_transform_stmt (gimple *stmt, gimple_stmt_iterator *gsi,
imm_use_iterator imm_iter;
use_operand_p use_p;
tree scalar_dest;
- gimple *exit_phi;
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
@@ -9743,23 +9748,23 @@ vect_transform_stmt (gimple *stmt, gimple_stmt_iterator *gsi,
if (gimple_code (stmt) == GIMPLE_PHI)
scalar_dest = PHI_RESULT (stmt);
else
- scalar_dest = gimple_assign_lhs (stmt);
+ scalar_dest = gimple_get_lhs (stmt);
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, scalar_dest)
- {
- if (!flow_bb_inside_loop_p (innerloop, gimple_bb (USE_STMT (use_p))))
- {
- exit_phi = USE_STMT (use_p);
- STMT_VINFO_VEC_STMT (vinfo_for_stmt (exit_phi)) = vec_stmt;
- }
- }
+ if (!flow_bb_inside_loop_p (innerloop, gimple_bb (USE_STMT (use_p))))
+ {
+ stmt_vec_info exit_phi_info
+ = vinfo->lookup_stmt (USE_STMT (use_p));
+ STMT_VINFO_VEC_STMT (exit_phi_info) = vec_stmt;
+ }
}
/* Handle stmts whose DEF is used outside the loop-nest that is
being vectorized. */
if (STMT_VINFO_TYPE (stmt_info) != reduc_vec_info_type)
{
- done = can_vectorize_live_stmts (stmt, gsi, slp_node, &vec_stmt, NULL);
+ done = can_vectorize_live_stmts (stmt_info, gsi, slp_node, &vec_stmt,
+ NULL);
gcc_assert (done);
}
@@ -9774,150 +9779,21 @@ vect_transform_stmt (gimple *stmt, gimple_stmt_iterator *gsi,
stmt_vec_info. */
void
-vect_remove_stores (gimple *first_stmt)
+vect_remove_stores (stmt_vec_info first_stmt_info)
{
- gimple *next = first_stmt;
- gimple *tmp;
- gimple_stmt_iterator next_si;
+ vec_info *vinfo = first_stmt_info->vinfo;
+ stmt_vec_info next_stmt_info = first_stmt_info;
- while (next)
+ while (next_stmt_info)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (next);
-
- tmp = DR_GROUP_NEXT_ELEMENT (stmt_info);
- if (is_pattern_stmt_p (stmt_info))
- next = STMT_VINFO_RELATED_STMT (stmt_info);
+ stmt_vec_info tmp = DR_GROUP_NEXT_ELEMENT (next_stmt_info);
+ next_stmt_info = vect_orig_stmt (next_stmt_info);
/* Free the attached stmt_vec_info and remove the stmt. */
- next_si = gsi_for_stmt (next);
- unlink_stmt_vdef (next);
- gsi_remove (&next_si, true);
- release_defs (next);
- free_stmt_vec_info (next);
- next = tmp;
+ vinfo->remove_stmt (next_stmt_info);
+ next_stmt_info = tmp;
}
}
-
-/* Function new_stmt_vec_info.
-
- Create and initialize a new stmt_vec_info struct for STMT. */
-
-stmt_vec_info
-new_stmt_vec_info (gimple *stmt, vec_info *vinfo)
-{
- stmt_vec_info res;
- res = (stmt_vec_info) xcalloc (1, sizeof (struct _stmt_vec_info));
-
- STMT_VINFO_TYPE (res) = undef_vec_info_type;
- STMT_VINFO_STMT (res) = stmt;
- res->vinfo = vinfo;
- STMT_VINFO_RELEVANT (res) = vect_unused_in_scope;
- STMT_VINFO_LIVE_P (res) = false;
- STMT_VINFO_VECTYPE (res) = NULL;
- STMT_VINFO_VEC_STMT (res) = NULL;
- STMT_VINFO_VECTORIZABLE (res) = true;
- STMT_VINFO_IN_PATTERN_P (res) = false;
- STMT_VINFO_RELATED_STMT (res) = NULL;
- STMT_VINFO_PATTERN_DEF_SEQ (res) = NULL;
- STMT_VINFO_DATA_REF (res) = NULL;
- STMT_VINFO_VEC_REDUCTION_TYPE (res) = TREE_CODE_REDUCTION;
- STMT_VINFO_VEC_CONST_COND_REDUC_CODE (res) = ERROR_MARK;
-
- if (gimple_code (stmt) == GIMPLE_PHI
- && is_loop_header_bb_p (gimple_bb (stmt)))
- STMT_VINFO_DEF_TYPE (res) = vect_unknown_def_type;
- else
- STMT_VINFO_DEF_TYPE (res) = vect_internal_def;
-
- STMT_VINFO_SAME_ALIGN_REFS (res).create (0);
- STMT_SLP_TYPE (res) = loop_vect;
- STMT_VINFO_NUM_SLP_USES (res) = 0;
-
- res->first_element = NULL; /* GROUP_FIRST_ELEMENT */
- res->next_element = NULL; /* GROUP_NEXT_ELEMENT */
- res->size = 0; /* GROUP_SIZE */
- res->store_count = 0; /* GROUP_STORE_COUNT */
- res->gap = 0; /* GROUP_GAP */
- res->same_dr_stmt = NULL; /* GROUP_SAME_DR_STMT */
-
- /* This is really "uninitialized" until vect_compute_data_ref_alignment. */
- res->dr_aux.misalignment = DR_MISALIGNMENT_UNINITIALIZED;
-
- return res;
-}
-
-
-/* Set the current stmt_vec_info vector to V. */
-
-void
-set_stmt_vec_info_vec (vec<stmt_vec_info> *v)
-{
- stmt_vec_info_vec = v;
-}
-
-/* Free the stmt_vec_info entries in V and release V. */
-
-void
-free_stmt_vec_infos (vec<stmt_vec_info> *v)
-{
- unsigned int i;
- stmt_vec_info info;
- FOR_EACH_VEC_ELT (*v, i, info)
- if (info != NULL)
- free_stmt_vec_info (STMT_VINFO_STMT (info));
- if (v == stmt_vec_info_vec)
- stmt_vec_info_vec = NULL;
- v->release ();
-}
-
-
-/* Free stmt vectorization related info. */
-
-void
-free_stmt_vec_info (gimple *stmt)
-{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
-
- if (!stmt_info)
- return;
-
- /* Check if this statement has a related "pattern stmt"
- (introduced by the vectorizer during the pattern recognition
- pass). Free pattern's stmt_vec_info and def stmt's stmt_vec_info
- too. */
- if (STMT_VINFO_IN_PATTERN_P (stmt_info))
- {
- if (gimple_seq seq = STMT_VINFO_PATTERN_DEF_SEQ (stmt_info))
- for (gimple_stmt_iterator si = gsi_start (seq);
- !gsi_end_p (si); gsi_next (&si))
- {
- gimple *seq_stmt = gsi_stmt (si);
- gimple_set_bb (seq_stmt, NULL);
- tree lhs = gimple_get_lhs (seq_stmt);
- if (lhs && TREE_CODE (lhs) == SSA_NAME)
- release_ssa_name (lhs);
- free_stmt_vec_info (seq_stmt);
- }
- stmt_vec_info patt_info
- = vinfo_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info));
- if (patt_info)
- {
- gimple *patt_stmt = STMT_VINFO_STMT (patt_info);
- gimple_set_bb (patt_stmt, NULL);
- tree lhs = gimple_get_lhs (patt_stmt);
- if (lhs && TREE_CODE (lhs) == SSA_NAME)
- release_ssa_name (lhs);
- free_stmt_vec_info (patt_stmt);
- }
- }
-
- STMT_VINFO_SAME_ALIGN_REFS (stmt_info).release ();
- STMT_VINFO_SIMD_CLONE_INFO (stmt_info).release ();
- set_vinfo_for_stmt (stmt, NULL);
- free (stmt_info);
-}
-
-
/* Function get_vectype_for_scalar_type_and_size.
Returns the vector type corresponding to SCALAR_TYPE and SIZE as supported
@@ -10052,7 +9928,10 @@ get_same_sized_vectype (tree scalar_type, tree vector_type)
VINFO - the vect info of the loop or basic block that is being vectorized.
OPERAND - operand in the loop or bb.
Output:
- DEF_STMT_OUT (optional) - the defining stmt in case OPERAND is an SSA_NAME.
+ DEF_STMT_INFO_OUT (optional) - information about the defining stmt in
+ case OPERAND is an SSA_NAME that is defined in the vectorizable region
+ DEF_STMT_OUT (optional) - the defining stmt in case OPERAND is an SSA_NAME;
+ the definition could be anywhere in the function
DT - the type of definition
Returns whether a stmt with OPERAND can be vectorized.
@@ -10065,8 +9944,10 @@ get_same_sized_vectype (tree scalar_type, tree vector_type)
bool
vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt,
- gimple **def_stmt_out)
+ stmt_vec_info *def_stmt_info_out, gimple **def_stmt_out)
{
+ if (def_stmt_info_out)
+ *def_stmt_info_out = NULL;
if (def_stmt_out)
*def_stmt_out = NULL;
*dt = vect_unknown_def_type;
@@ -10093,16 +9974,13 @@ vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt,
else
{
gimple *def_stmt = SSA_NAME_DEF_STMT (operand);
- if (! vect_stmt_in_region_p (vinfo, def_stmt))
+ stmt_vec_info stmt_vinfo = vinfo->lookup_def (operand);
+ if (!stmt_vinfo)
*dt = vect_external_def;
else
{
- stmt_vec_info stmt_vinfo = vinfo_for_stmt (def_stmt);
- if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo))
- {
- def_stmt = STMT_VINFO_RELATED_STMT (stmt_vinfo);
- stmt_vinfo = vinfo_for_stmt (def_stmt);
- }
+ stmt_vinfo = vect_stmt_to_vectorize (stmt_vinfo);
+ def_stmt = stmt_vinfo->stmt;
switch (gimple_code (def_stmt))
{
case GIMPLE_PHI:
@@ -10114,6 +9992,8 @@ vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt,
*dt = vect_unknown_def_type;
break;
}
+ if (def_stmt_info_out)
+ *def_stmt_info_out = stmt_vinfo;
}
if (def_stmt_out)
*def_stmt_out = def_stmt;
@@ -10176,14 +10056,18 @@ vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt,
bool
vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt,
- tree *vectype, gimple **def_stmt_out)
+ tree *vectype, stmt_vec_info *def_stmt_info_out,
+ gimple **def_stmt_out)
{
+ stmt_vec_info def_stmt_info;
gimple *def_stmt;
- if (!vect_is_simple_use (operand, vinfo, dt, &def_stmt))
+ if (!vect_is_simple_use (operand, vinfo, dt, &def_stmt_info, &def_stmt))
return false;
if (def_stmt_out)
*def_stmt_out = def_stmt;
+ if (def_stmt_info_out)
+ *def_stmt_info_out = def_stmt_info;
/* Now get a vector type if the def is internal, otherwise supply
NULL_TREE and leave it up to the caller to figure out a proper
@@ -10194,16 +10078,11 @@ vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt,
|| *dt == vect_double_reduction_def
|| *dt == vect_nested_cycle)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (def_stmt);
- *vectype = STMT_VINFO_VECTYPE (stmt_info);
+ *vectype = STMT_VINFO_VECTYPE (def_stmt_info);
gcc_assert (*vectype != NULL_TREE);
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "vect_is_simple_use: vectype ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, *vectype);
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "vect_is_simple_use: vectype %T\n", *vectype);
}
else if (*dt == vect_uninitialized_def
|| *dt == vect_constant_def
@@ -10238,13 +10117,12 @@ vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt,
widening operation (short in the above example). */
bool
-supportable_widening_operation (enum tree_code code, gimple *stmt,
+supportable_widening_operation (enum tree_code code, stmt_vec_info stmt_info,
tree vectype_out, tree vectype_in,
enum tree_code *code1, enum tree_code *code2,
int *multi_step_cvt,
vec<tree> *interm_types)
{
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (stmt_info);
struct loop *vect_loop = NULL;
machine_mode vec_mode;
@@ -10300,25 +10178,22 @@ supportable_widening_operation (enum tree_code code, gimple *stmt,
a VEC_WIDEN_MULT_LO/HI_EXPR check. */
if (vect_loop
&& STMT_VINFO_RELEVANT (stmt_info) == vect_used_by_reduction
- && !nested_in_vect_loop_p (vect_loop, stmt)
+ && !nested_in_vect_loop_p (vect_loop, stmt_info)
&& supportable_widening_operation (VEC_WIDEN_MULT_EVEN_EXPR,
- stmt, vectype_out, vectype_in,
- code1, code2, multi_step_cvt,
- interm_types))
+ stmt_info, vectype_out,
+ vectype_in, code1, code2,
+ multi_step_cvt, interm_types))
{
/* Elements in a vector with vect_used_by_reduction property cannot
be reordered if the use chain with this property does not have the
same operation. One such an example is s += a * b, where elements
in a and b cannot be reordered. Here we check if the vector defined
by STMT is only directly used in the reduction statement. */
- tree lhs = gimple_assign_lhs (stmt);
- use_operand_p dummy;
- gimple *use_stmt;
- stmt_vec_info use_stmt_info = NULL;
- if (single_imm_use (lhs, &dummy, &use_stmt)
- && (use_stmt_info = vinfo_for_stmt (use_stmt))
- && STMT_VINFO_DEF_TYPE (use_stmt_info) == vect_reduction_def)
- return true;
+ tree lhs = gimple_assign_lhs (stmt_info->stmt);
+ stmt_vec_info use_stmt_info = loop_info->lookup_single_use (lhs);
+ if (use_stmt_info
+ && STMT_VINFO_DEF_TYPE (use_stmt_info) == vect_reduction_def)
+ return true;
}
c1 = VEC_WIDEN_MULT_LO_EXPR;
c2 = VEC_WIDEN_MULT_HI_EXPR;
@@ -10689,22 +10564,16 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info,
}
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: irregular stmt.");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: irregular stmt.%G", stmt);
return false;
}
if (VECTOR_MODE_P (TYPE_MODE (gimple_expr_type (stmt))))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: vector stmt in loop:");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: vector stmt in loop:%G", stmt);
return false;
}
@@ -10742,23 +10611,15 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info,
}
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "get vectype for scalar type: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, scalar_type);
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "get vectype for scalar type: %T\n", scalar_type);
vectype = get_vectype_for_scalar_type (scalar_type);
if (!vectype)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: unsupported data-type ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- scalar_type);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: unsupported data-type %T\n",
+ scalar_type);
return false;
}
@@ -10766,11 +10627,7 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info,
*stmt_vectype_out = vectype;
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location, "vectype: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, vectype);
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location, "vectype: %T\n", vectype);
}
/* Don't try to compute scalar types if the stmt produces a boolean
@@ -10786,26 +10643,20 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info,
if (*stmt_vectype_out != boolean_type_node)
{
HOST_WIDE_INT dummy;
- scalar_type = vect_get_smallest_scalar_type (stmt, &dummy, &dummy);
+ scalar_type = vect_get_smallest_scalar_type (stmt_info,
+ &dummy, &dummy);
}
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "get vectype for scalar type: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, scalar_type);
- dump_printf (MSG_NOTE, "\n");
- }
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "get vectype for scalar type: %T\n", scalar_type);
nunits_vectype = get_vectype_for_scalar_type (scalar_type);
}
if (!nunits_vectype)
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: unsupported data-type ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, scalar_type);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: unsupported data-type %T\n",
+ scalar_type);
return false;
}
@@ -10813,23 +10664,17 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info,
GET_MODE_SIZE (TYPE_MODE (nunits_vectype))))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: different sized vector "
- "types in statement, ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, vectype);
- dump_printf (MSG_MISSED_OPTIMIZATION, " and ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, nunits_vectype);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: different sized vector "
+ "types in statement, %T and %T\n",
+ vectype, nunits_vectype);
return false;
}
if (dump_enabled_p ())
{
- dump_printf_loc (MSG_NOTE, vect_location, "vectype: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, nunits_vectype);
- dump_printf (MSG_NOTE, "\n");
+ dump_printf_loc (MSG_NOTE, vect_location, "vectype: %T\n",
+ nunits_vectype);
dump_printf_loc (MSG_NOTE, vect_location, "nunits = ");
dump_dec (MSG_NOTE, TYPE_VECTOR_SUBPARTS (nunits_vectype));
@@ -10877,13 +10722,9 @@ vect_get_mask_type_for_stmt (stmt_vec_info stmt_info)
if (!vect_is_simple_use (rhs, stmt_info->vinfo, &dt, &vectype))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: can't compute mask type "
- "for statement, ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt,
- 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: can't compute mask type "
+ "for statement, %G", stmt);
return NULL_TREE;
}
@@ -10899,34 +10740,21 @@ vect_get_mask_type_for_stmt (stmt_vec_info stmt_info)
TYPE_VECTOR_SUBPARTS (vectype)))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: different sized masks "
- "types in statement, ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- mask_type);
- dump_printf (MSG_MISSED_OPTIMIZATION, " and ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- vectype);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: different sized masks "
+ "types in statement, %T and %T\n",
+ mask_type, vectype);
return NULL_TREE;
}
else if (VECTOR_BOOLEAN_TYPE_P (mask_type)
!= VECTOR_BOOLEAN_TYPE_P (vectype))
{
if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: mixed mask and "
- "nonmask vector types in statement, ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- mask_type);
- dump_printf (MSG_MISSED_OPTIMIZATION, " and ");
- dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
- vectype);
- dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: mixed mask and "
+ "nonmask vector types in statement, "
+ "%T and %T\n",
+ mask_type, vectype);
return NULL_TREE;
}
}
@@ -10943,11 +10771,8 @@ vect_get_mask_type_for_stmt (stmt_vec_info stmt_info)
/* No mask_type should mean loop invariant predicate.
This is probably a subject for optimization in if-conversion. */
if (!mask_type && dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: can't compute mask type "
- "for statement, ");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
- }
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: can't compute mask type "
+ "for statement, %G", stmt);
return mask_type;
}
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index 971221c..23bddf3 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -84,9 +84,6 @@ along with GCC; see the file COPYING3. If not see
/* Loop or bb location, with hotness information. */
dump_user_location_t vect_location;
-/* Vector mapping GIMPLE stmt to stmt_vec_info. */
-vec<stmt_vec_info> *stmt_vec_info_vec;
-
/* Dump a cost entry according to args to F. */
void
@@ -457,7 +454,6 @@ vec_info::vec_info (vec_info::vec_kind kind_in, void *target_cost_data_in,
target_cost_data (target_cost_data_in)
{
stmt_vec_infos.create (50);
- set_stmt_vec_info_vec (&stmt_vec_infos);
}
vec_info::~vec_info ()
@@ -466,10 +462,10 @@ vec_info::~vec_info ()
unsigned int i;
FOR_EACH_VEC_ELT (slp_instances, i, instance)
- vect_free_slp_instance (instance);
+ vect_free_slp_instance (instance, true);
destroy_cost_data (target_cost_data);
- free_stmt_vec_infos (&stmt_vec_infos);
+ free_stmt_vec_infos ();
}
vec_info_shared::vec_info_shared ()
@@ -507,47 +503,213 @@ vec_info_shared::check_datarefs ()
gcc_unreachable ();
}
-/* A helper function to free scev and LOOP niter information, as well as
- clear loop constraint LOOP_C_FINITE. */
+/* Record that STMT belongs to the vectorizable region. Create and return
+ an associated stmt_vec_info. */
+
+stmt_vec_info
+vec_info::add_stmt (gimple *stmt)
+{
+ stmt_vec_info res = new_stmt_vec_info (stmt);
+ set_vinfo_for_stmt (stmt, res);
+ return res;
+}
+
+/* If STMT has an associated stmt_vec_info, return that vec_info, otherwise
+ return null. It is safe to call this function on any statement, even if
+ it might not be part of the vectorizable region. */
+
+stmt_vec_info
+vec_info::lookup_stmt (gimple *stmt)
+{
+ unsigned int uid = gimple_uid (stmt);
+ if (uid > 0 && uid - 1 < stmt_vec_infos.length ())
+ {
+ stmt_vec_info res = stmt_vec_infos[uid - 1];
+ if (res && res->stmt == stmt)
+ return res;
+ }
+ return NULL;
+}
+
+/* If NAME is an SSA_NAME and its definition has an associated stmt_vec_info,
+ return that stmt_vec_info, otherwise return null. It is safe to call
+ this on arbitrary operands. */
+
+stmt_vec_info
+vec_info::lookup_def (tree name)
+{
+ if (TREE_CODE (name) == SSA_NAME
+ && !SSA_NAME_IS_DEFAULT_DEF (name))
+ return lookup_stmt (SSA_NAME_DEF_STMT (name));
+ return NULL;
+}
+
+/* See whether there is a single non-debug statement that uses LHS and
+ whether that statement has an associated stmt_vec_info. Return the
+ stmt_vec_info if so, otherwise return null. */
+
+stmt_vec_info
+vec_info::lookup_single_use (tree lhs)
+{
+ use_operand_p dummy;
+ gimple *use_stmt;
+ if (single_imm_use (lhs, &dummy, &use_stmt))
+ return lookup_stmt (use_stmt);
+ return NULL;
+}
+
+/* Return vectorization information about DR. */
+
+dr_vec_info *
+vec_info::lookup_dr (data_reference *dr)
+{
+ stmt_vec_info stmt_info = lookup_stmt (DR_STMT (dr));
+ /* DR_STMT should never refer to a stmt in a pattern replacement. */
+ gcc_checking_assert (!is_pattern_stmt_p (stmt_info));
+ return STMT_VINFO_DR_INFO (stmt_info->dr_aux.stmt);
+}
+
+/* Record that NEW_STMT_INFO now implements the same data reference
+ as OLD_STMT_INFO. */
void
-vect_free_loop_info_assumptions (struct loop *loop)
+vec_info::move_dr (stmt_vec_info new_stmt_info, stmt_vec_info old_stmt_info)
{
- scev_reset_htab ();
- /* We need to explicitly reset upper bound information since they are
- used even after free_numbers_of_iterations_estimates. */
- loop->any_upper_bound = false;
- loop->any_likely_upper_bound = false;
- free_numbers_of_iterations_estimates (loop);
- loop_constraint_clear (loop, LOOP_C_FINITE);
+ gcc_assert (!is_pattern_stmt_p (old_stmt_info));
+ STMT_VINFO_DR_INFO (old_stmt_info)->stmt = new_stmt_info;
+ new_stmt_info->dr_aux = old_stmt_info->dr_aux;
+ STMT_VINFO_DR_WRT_VEC_LOOP (new_stmt_info)
+ = STMT_VINFO_DR_WRT_VEC_LOOP (old_stmt_info);
+ STMT_VINFO_GATHER_SCATTER_P (new_stmt_info)
+ = STMT_VINFO_GATHER_SCATTER_P (old_stmt_info);
+}
+
+/* Permanently remove the statement described by STMT_INFO from the
+ function. */
+
+void
+vec_info::remove_stmt (stmt_vec_info stmt_info)
+{
+ gcc_assert (!stmt_info->pattern_stmt_p);
+ set_vinfo_for_stmt (stmt_info->stmt, NULL);
+ gimple_stmt_iterator si = gsi_for_stmt (stmt_info->stmt);
+ unlink_stmt_vdef (stmt_info->stmt);
+ gsi_remove (&si, true);
+ release_defs (stmt_info->stmt);
+ free_stmt_vec_info (stmt_info);
}
-/* Return whether STMT is inside the region we try to vectorize. */
+/* Replace the statement at GSI by NEW_STMT, both the vectorization
+ information and the function itself. STMT_INFO describes the statement
+ at GSI. */
-bool
-vect_stmt_in_region_p (vec_info *vinfo, gimple *stmt)
+void
+vec_info::replace_stmt (gimple_stmt_iterator *gsi, stmt_vec_info stmt_info,
+ gimple *new_stmt)
+{
+ gimple *old_stmt = stmt_info->stmt;
+ gcc_assert (!stmt_info->pattern_stmt_p && old_stmt == gsi_stmt (*gsi));
+ set_vinfo_for_stmt (old_stmt, NULL);
+ set_vinfo_for_stmt (new_stmt, stmt_info);
+ stmt_info->stmt = new_stmt;
+ gsi_replace (gsi, new_stmt, true);
+}
+
+/* Create and initialize a new stmt_vec_info struct for STMT. */
+
+stmt_vec_info
+vec_info::new_stmt_vec_info (gimple *stmt)
{
- if (!gimple_bb (stmt))
- return false;
+ stmt_vec_info res = XCNEW (struct _stmt_vec_info);
+ res->vinfo = this;
+ res->stmt = stmt;
+
+ STMT_VINFO_TYPE (res) = undef_vec_info_type;
+ STMT_VINFO_RELEVANT (res) = vect_unused_in_scope;
+ STMT_VINFO_VECTORIZABLE (res) = true;
+ STMT_VINFO_VEC_REDUCTION_TYPE (res) = TREE_CODE_REDUCTION;
+ STMT_VINFO_VEC_CONST_COND_REDUC_CODE (res) = ERROR_MARK;
+
+ if (gimple_code (stmt) == GIMPLE_PHI
+ && is_loop_header_bb_p (gimple_bb (stmt)))
+ STMT_VINFO_DEF_TYPE (res) = vect_unknown_def_type;
+ else
+ STMT_VINFO_DEF_TYPE (res) = vect_internal_def;
+
+ STMT_VINFO_SAME_ALIGN_REFS (res).create (0);
+ STMT_SLP_TYPE (res) = loop_vect;
+
+ /* This is really "uninitialized" until vect_compute_data_ref_alignment. */
+ res->dr_aux.misalignment = DR_MISALIGNMENT_UNINITIALIZED;
+
+ return res;
+}
+
+/* Associate STMT with INFO. */
- if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo))
+void
+vec_info::set_vinfo_for_stmt (gimple *stmt, stmt_vec_info info)
+{
+ unsigned int uid = gimple_uid (stmt);
+ if (uid == 0)
{
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
- if (!flow_bb_inside_loop_p (loop, gimple_bb (stmt)))
- return false;
+ gcc_checking_assert (info);
+ uid = stmt_vec_infos.length () + 1;
+ gimple_set_uid (stmt, uid);
+ stmt_vec_infos.safe_push (info);
}
else
{
- bb_vec_info bb_vinfo = as_a <bb_vec_info> (vinfo);
- if (gimple_bb (stmt) != BB_VINFO_BB (bb_vinfo)
- || gimple_uid (stmt) == -1U
- || gimple_code (stmt) == GIMPLE_PHI)
- return false;
+ gcc_checking_assert (info == NULL);
+ stmt_vec_infos[uid - 1] = info;
}
+}
- return true;
+/* Free the contents of stmt_vec_infos. */
+
+void
+vec_info::free_stmt_vec_infos (void)
+{
+ unsigned int i;
+ stmt_vec_info info;
+ FOR_EACH_VEC_ELT (stmt_vec_infos, i, info)
+ if (info != NULL)
+ free_stmt_vec_info (info);
+ stmt_vec_infos.release ();
}
+/* Free STMT_INFO. */
+
+void
+vec_info::free_stmt_vec_info (stmt_vec_info stmt_info)
+{
+ if (stmt_info->pattern_stmt_p)
+ {
+ gimple_set_bb (stmt_info->stmt, NULL);
+ tree lhs = gimple_get_lhs (stmt_info->stmt);
+ if (lhs && TREE_CODE (lhs) == SSA_NAME)
+ release_ssa_name (lhs);
+ }
+
+ STMT_VINFO_SAME_ALIGN_REFS (stmt_info).release ();
+ STMT_VINFO_SIMD_CLONE_INFO (stmt_info).release ();
+ free (stmt_info);
+}
+
+/* A helper function to free scev and LOOP niter information, as well as
+ clear loop constraint LOOP_C_FINITE. */
+
+void
+vect_free_loop_info_assumptions (struct loop *loop)
+{
+ scev_reset_htab ();
+ /* We need to explicitly reset upper bound information since they are
+ used even after free_numbers_of_iterations_estimates. */
+ loop->any_upper_bound = false;
+ loop->any_likely_upper_bound = false;
+ free_numbers_of_iterations_estimates (loop);
+ loop_constraint_clear (loop, LOOP_C_FINITE);
+}
/* If LOOP has been versioned during ifcvt, return the internal call
guarding it. */
@@ -773,9 +935,7 @@ try_vectorize_loop_1 (hash_table<simduid_to_vf> *&simduid_to_vf_htab,
unsigned HOST_WIDE_INT bytes;
if (current_vector_size.is_constant (&bytes))
dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
- "loop vectorized vectorized using "
- HOST_WIDE_INT_PRINT_UNSIGNED " byte "
- "vectors\n", bytes);
+ "loop vectorized using %wu byte vectors\n", bytes);
else
dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
"loop vectorized using variable length vectors\n");
@@ -862,8 +1022,6 @@ vectorize_loops (void)
if (cfun->has_simduid_loops)
note_simd_array_uses (&simd_array_to_simduid_htab);
- set_stmt_vec_info_vec (NULL);
-
/* ----------- Analyze loops. ----------- */
/* If some loop was duplicated, it gets bigger number
@@ -1267,9 +1425,7 @@ increase_alignment (void)
if (alignment && vect_can_force_dr_alignment_p (decl, alignment))
{
vnode->increase_alignment (alignment);
- dump_printf (MSG_NOTE, "Increasing alignment of decl: ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, decl);
- dump_printf (MSG_NOTE, "\n");
+ dump_printf (MSG_NOTE, "Increasing alignment of decl: %T\n", decl);
}
}
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 28be41f..d91cc07 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_TREE_VECTORIZER_H
#define GCC_TREE_VECTORIZER_H
+typedef struct _stmt_vec_info *stmt_vec_info;
+
#include "tree-data-ref.h"
#include "tree-hash-traits.h"
#include "target.h"
@@ -95,7 +97,7 @@ struct stmt_info_for_cost {
int count;
enum vect_cost_for_stmt kind;
enum vect_cost_model_location where;
- gimple *stmt;
+ stmt_vec_info stmt_info;
int misalign;
};
@@ -117,12 +119,12 @@ struct _slp_tree {
/* Nodes that contain def-stmts of this node statements operands. */
vec<slp_tree> children;
/* A group of scalar stmts to be vectorized together. */
- vec<gimple *> stmts;
+ vec<stmt_vec_info> stmts;
/* Load permutation relative to the stores, NULL if there is no
permutation. */
vec<unsigned> load_permutation;
/* Vectorized stmt/s. */
- vec<gimple *> vec_stmts;
+ vec<stmt_vec_info> vec_stmts;
/* Number of vector stmts that are created to replace the group of scalar
stmts. It is calculated during the transformation phase as the number of
scalar elements in one scalar iteration (GROUP_SIZE) multiplied by VF
@@ -215,6 +217,15 @@ struct vec_info {
vec_info (vec_kind, void *, vec_info_shared *);
~vec_info ();
+ stmt_vec_info add_stmt (gimple *);
+ stmt_vec_info lookup_stmt (gimple *);
+ stmt_vec_info lookup_def (tree);
+ stmt_vec_info lookup_single_use (tree);
+ struct dr_vec_info *lookup_dr (data_reference *);
+ void move_dr (stmt_vec_info, stmt_vec_info);
+ void remove_stmt (stmt_vec_info);
+ void replace_stmt (gimple_stmt_iterator *, stmt_vec_info, gimple *);
+
/* The type of vectorization. */
vec_kind kind;
@@ -222,7 +233,7 @@ struct vec_info {
vec_info_shared *shared;
/* The mapping of GIMPLE UID to stmt_vec_info. */
- vec<struct _stmt_vec_info *> stmt_vec_infos;
+ vec<stmt_vec_info> stmt_vec_infos;
/* All SLP instances. */
auto_vec<slp_instance> slp_instances;
@@ -233,10 +244,16 @@ struct vec_info {
/* All interleaving chains of stores, represented by the first
stmt in the chain. */
- auto_vec<gimple *> grouped_stores;
+ auto_vec<stmt_vec_info> grouped_stores;
/* Cost data used by the target cost model. */
void *target_cost_data;
+
+private:
+ stmt_vec_info new_stmt_vec_info (gimple *stmt);
+ void set_vinfo_for_stmt (gimple *, stmt_vec_info);
+ void free_stmt_vec_infos ();
+ void free_stmt_vec_info (stmt_vec_info);
};
struct _loop_vec_info;
@@ -410,7 +427,7 @@ typedef struct _loop_vec_info : public vec_info {
tree mask_compare_type;
/* Unknown DRs according to which loop was peeled. */
- struct data_reference *unaligned_dr;
+ struct dr_vec_info *unaligned_dr;
/* peeling_for_alignment indicates whether peeling for alignment will take
place, and what the peeling factor should be:
@@ -446,14 +463,14 @@ typedef struct _loop_vec_info : public vec_info {
/* Statements in the loop that have data references that are candidates for a
runtime (loop versioning) misalignment check. */
- auto_vec<gimple *> may_misalign_stmts;
+ auto_vec<stmt_vec_info> may_misalign_stmts;
/* Reduction cycles detected in the loop. Used in loop-aware SLP. */
- auto_vec<gimple *> reductions;
+ auto_vec<stmt_vec_info> reductions;
/* All reduction chains in the loop, represented by the first
stmt in the chain. */
- auto_vec<gimple *> reduction_chains;
+ auto_vec<stmt_vec_info> reduction_chains;
/* Cost vector for a single scalar iteration. */
auto_vec<stmt_info_for_cost> scalar_cost_vec;
@@ -601,13 +618,6 @@ loop_vec_info_for_loop (struct loop *loop)
return (loop_vec_info) loop->aux;
}
-static inline bool
-nested_in_vect_loop_p (struct loop *loop, gimple *stmt)
-{
- return (loop->inner
- && (loop->inner == (gimple_bb (stmt))->loop_father));
-}
-
typedef struct _bb_vec_info : public vec_info
{
_bb_vec_info (gimple_stmt_iterator, gimple_stmt_iterator, vec_info_shared *);
@@ -748,7 +758,11 @@ enum vect_memory_access_type {
VMAT_GATHER_SCATTER
};
-struct dataref_aux {
+struct dr_vec_info {
+ /* The data reference itself. */
+ data_reference *dr;
+ /* The statement that contains the data reference. */
+ stmt_vec_info stmt;
/* The misalignment in bytes of the reference, or -1 if not known. */
int misalignment;
/* The byte alignment that we'd ideally like the reference to have,
@@ -761,7 +775,7 @@ struct dataref_aux {
typedef struct data_reference *dr_p;
-typedef struct _stmt_vec_info {
+struct _stmt_vec_info {
enum stmt_vec_info_type type;
@@ -772,6 +786,12 @@ typedef struct _stmt_vec_info {
/* Stmt is part of some pattern (computation idiom) */
bool in_pattern_p;
+ /* True if the statement was created during pattern recognition as
+ part of the replacement for RELATED_STMT. This implies that the
+ statement isn't part of any basic block, although for convenience
+ its gimple_bb is the same as for RELATED_STMT. */
+ bool pattern_stmt_p;
+
/* Is this statement vectorizable or should it be skipped in (partial)
vectorization. */
bool vectorizable;
@@ -786,18 +806,14 @@ typedef struct _stmt_vec_info {
tree vectype;
/* The vectorized version of the stmt. */
- gimple *vectorized_stmt;
+ stmt_vec_info vectorized_stmt;
/* The following is relevant only for stmts that contain a non-scalar
data-ref (array/pointer/struct access). A GIMPLE stmt is expected to have
at most one such data-ref. */
- /* Information about the data-ref (access function, etc),
- relative to the inner-most containing loop. */
- struct data_reference *data_ref_info;
-
- dataref_aux dr_aux;
+ dr_vec_info dr_aux;
/* Information about the data-ref relative to this loop
nest (the loop that is being considered for vectorization). */
@@ -821,7 +837,7 @@ typedef struct _stmt_vec_info {
related_stmt of the "pattern stmt" points back to this stmt (which is
the last stmt in the original sequence of stmts that constitutes the
pattern). */
- gimple *related_stmt;
+ stmt_vec_info related_stmt;
/* Used to keep a sequence of def stmts of a pattern stmt if such exists.
The sequence is attached to the original statement rather than the
@@ -845,12 +861,12 @@ typedef struct _stmt_vec_info {
/* Interleaving and reduction chains info. */
/* First element in the group. */
- gimple *first_element;
+ stmt_vec_info first_element;
/* Pointer to the next element in the group. */
- gimple *next_element;
+ stmt_vec_info next_element;
/* For data-refs, in case that two or more stmts share data-ref, this is the
pointer to the previously detected stmt with the same dr. */
- gimple *same_dr_stmt;
+ stmt_vec_info same_dr_stmt;
/* The size of the group. */
unsigned int size;
/* For stores, number of stores from this group seen. We vectorize the last
@@ -895,7 +911,7 @@ typedef struct _stmt_vec_info {
/* On a reduction PHI the def returned by vect_force_simple_reduction.
On the def returned by vect_force_simple_reduction the
corresponding PHI. */
- gimple *reduc_def;
+ stmt_vec_info reduc_def;
/* The number of scalar stmt references from active SLP instances. */
unsigned int num_slp_uses;
@@ -914,7 +930,7 @@ typedef struct _stmt_vec_info {
and OPERATION_BITS without changing the result. */
unsigned int operation_precision;
signop operation_sign;
-} *stmt_vec_info;
+};
/* Information about a gather/scatter call. */
struct gather_scatter_info {
@@ -971,7 +987,7 @@ STMT_VINFO_BB_VINFO (stmt_vec_info stmt_vinfo)
#define STMT_VINFO_VECTYPE(S) (S)->vectype
#define STMT_VINFO_VEC_STMT(S) (S)->vectorized_stmt
#define STMT_VINFO_VECTORIZABLE(S) (S)->vectorizable
-#define STMT_VINFO_DATA_REF(S) (S)->data_ref_info
+#define STMT_VINFO_DATA_REF(S) ((S)->dr_aux.dr + 0)
#define STMT_VINFO_GATHER_SCATTER_P(S) (S)->gather_scatter_p
#define STMT_VINFO_STRIDED_P(S) (S)->strided_p
#define STMT_VINFO_MEMORY_ACCESS_TYPE(S) (S)->memory_access_type
@@ -992,13 +1008,17 @@ STMT_VINFO_BB_VINFO (stmt_vec_info stmt_vinfo)
#define STMT_VINFO_DR_STEP_ALIGNMENT(S) \
(S)->dr_wrt_vec_loop.step_alignment
+#define STMT_VINFO_DR_INFO(S) \
+ (gcc_checking_assert ((S)->dr_aux.stmt == (S)), &(S)->dr_aux)
+
#define STMT_VINFO_IN_PATTERN_P(S) (S)->in_pattern_p
#define STMT_VINFO_RELATED_STMT(S) (S)->related_stmt
#define STMT_VINFO_PATTERN_DEF_SEQ(S) (S)->pattern_def_seq
#define STMT_VINFO_SAME_ALIGN_REFS(S) (S)->same_align_refs
#define STMT_VINFO_SIMD_CLONE_INFO(S) (S)->simd_clone_info
#define STMT_VINFO_DEF_TYPE(S) (S)->def_type
-#define STMT_VINFO_GROUPED_ACCESS(S) ((S)->data_ref_info && DR_GROUP_FIRST_ELEMENT(S))
+#define STMT_VINFO_GROUPED_ACCESS(S) \
+ ((S)->dr_aux.dr && DR_GROUP_FIRST_ELEMENT(S))
#define STMT_VINFO_LOOP_PHI_EVOLUTION_BASE_UNCHANGED(S) (S)->loop_phi_evolution_base_unchanged
#define STMT_VINFO_LOOP_PHI_EVOLUTION_PART(S) (S)->loop_phi_evolution_part
#define STMT_VINFO_MIN_NEG_DIST(S) (S)->min_neg_dist
@@ -1006,16 +1026,25 @@ STMT_VINFO_BB_VINFO (stmt_vec_info stmt_vinfo)
#define STMT_VINFO_REDUC_TYPE(S) (S)->reduc_type
#define STMT_VINFO_REDUC_DEF(S) (S)->reduc_def
-#define DR_GROUP_FIRST_ELEMENT(S) (gcc_checking_assert ((S)->data_ref_info), (S)->first_element)
-#define DR_GROUP_NEXT_ELEMENT(S) (gcc_checking_assert ((S)->data_ref_info), (S)->next_element)
-#define DR_GROUP_SIZE(S) (gcc_checking_assert ((S)->data_ref_info), (S)->size)
-#define DR_GROUP_STORE_COUNT(S) (gcc_checking_assert ((S)->data_ref_info), (S)->store_count)
-#define DR_GROUP_GAP(S) (gcc_checking_assert ((S)->data_ref_info), (S)->gap)
-#define DR_GROUP_SAME_DR_STMT(S) (gcc_checking_assert ((S)->data_ref_info), (S)->same_dr_stmt)
-
-#define REDUC_GROUP_FIRST_ELEMENT(S) (gcc_checking_assert (!(S)->data_ref_info), (S)->first_element)
-#define REDUC_GROUP_NEXT_ELEMENT(S) (gcc_checking_assert (!(S)->data_ref_info), (S)->next_element)
-#define REDUC_GROUP_SIZE(S) (gcc_checking_assert (!(S)->data_ref_info), (S)->size)
+#define DR_GROUP_FIRST_ELEMENT(S) \
+ (gcc_checking_assert ((S)->dr_aux.dr), (S)->first_element)
+#define DR_GROUP_NEXT_ELEMENT(S) \
+ (gcc_checking_assert ((S)->dr_aux.dr), (S)->next_element)
+#define DR_GROUP_SIZE(S) \
+ (gcc_checking_assert ((S)->dr_aux.dr), (S)->size)
+#define DR_GROUP_STORE_COUNT(S) \
+ (gcc_checking_assert ((S)->dr_aux.dr), (S)->store_count)
+#define DR_GROUP_GAP(S) \
+ (gcc_checking_assert ((S)->dr_aux.dr), (S)->gap)
+#define DR_GROUP_SAME_DR_STMT(S) \
+ (gcc_checking_assert ((S)->dr_aux.dr), (S)->same_dr_stmt)
+
+#define REDUC_GROUP_FIRST_ELEMENT(S) \
+ (gcc_checking_assert (!(S)->dr_aux.dr), (S)->first_element)
+#define REDUC_GROUP_NEXT_ELEMENT(S) \
+ (gcc_checking_assert (!(S)->dr_aux.dr), (S)->next_element)
+#define REDUC_GROUP_SIZE(S) \
+ (gcc_checking_assert (!(S)->dr_aux.dr), (S)->size)
#define STMT_VINFO_RELEVANT_P(S) ((S)->relevant != vect_unused_in_scope)
@@ -1023,8 +1052,6 @@ STMT_VINFO_BB_VINFO (stmt_vec_info stmt_vinfo)
#define PURE_SLP_STMT(S) ((S)->slp_type == pure_slp)
#define STMT_SLP_TYPE(S) (S)->slp_type
-#define DR_VECT_AUX(dr) (&vinfo_for_stmt (DR_STMT (dr))->dr_aux)
-
#define VECT_MAX_COST 1000
/* The maximum number of intermediate steps required in multi-step type
@@ -1045,105 +1072,43 @@ STMT_VINFO_BB_VINFO (stmt_vec_info stmt_vinfo)
&& TYPE_PRECISION (TYPE) == 1 \
&& TYPE_UNSIGNED (TYPE)))
-extern vec<stmt_vec_info> *stmt_vec_info_vec;
-
-void set_stmt_vec_info_vec (vec<stmt_vec_info> *);
-void free_stmt_vec_infos (vec<stmt_vec_info> *);
-
-/* Return a stmt_vec_info corresponding to STMT. */
-
-static inline stmt_vec_info
-vinfo_for_stmt (gimple *stmt)
-{
- int uid = gimple_uid (stmt);
- if (uid <= 0)
- return NULL;
-
- return (*stmt_vec_info_vec)[uid - 1];
-}
-
-/* Set vectorizer information INFO for STMT. */
-
-static inline void
-set_vinfo_for_stmt (gimple *stmt, stmt_vec_info info)
+static inline bool
+nested_in_vect_loop_p (struct loop *loop, stmt_vec_info stmt_info)
{
- unsigned int uid = gimple_uid (stmt);
- if (uid == 0)
- {
- gcc_checking_assert (info);
- uid = stmt_vec_info_vec->length () + 1;
- gimple_set_uid (stmt, uid);
- stmt_vec_info_vec->safe_push (info);
- }
- else
- {
- gcc_checking_assert (info == NULL);
- (*stmt_vec_info_vec)[uid - 1] = info;
- }
+ return (loop->inner
+ && (loop->inner == (gimple_bb (stmt_info->stmt))->loop_father));
}
-/* Return the earlier statement between STMT1 and STMT2. */
+/* Return the earlier statement between STMT1_INFO and STMT2_INFO. */
-static inline gimple *
-get_earlier_stmt (gimple *stmt1, gimple *stmt2)
+static inline stmt_vec_info
+get_earlier_stmt (stmt_vec_info stmt1_info, stmt_vec_info stmt2_info)
{
- unsigned int uid1, uid2;
-
- if (stmt1 == NULL)
- return stmt2;
+ gcc_checking_assert ((STMT_VINFO_IN_PATTERN_P (stmt1_info)
+ || !STMT_VINFO_RELATED_STMT (stmt1_info))
+ && (STMT_VINFO_IN_PATTERN_P (stmt2_info)
+ || !STMT_VINFO_RELATED_STMT (stmt2_info)));
- if (stmt2 == NULL)
- return stmt1;
-
- uid1 = gimple_uid (stmt1);
- uid2 = gimple_uid (stmt2);
-
- if (uid1 == 0 || uid2 == 0)
- return NULL;
-
- gcc_assert (uid1 <= stmt_vec_info_vec->length ()
- && uid2 <= stmt_vec_info_vec->length ());
- gcc_checking_assert ((STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (stmt1))
- || !STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt1)))
- && (STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (stmt2))
- || !STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt2))));
-
- if (uid1 < uid2)
- return stmt1;
+ if (gimple_uid (stmt1_info->stmt) < gimple_uid (stmt2_info->stmt))
+ return stmt1_info;
else
- return stmt2;
+ return stmt2_info;
}
-/* Return the later statement between STMT1 and STMT2. */
+/* Return the later statement between STMT1_INFO and STMT2_INFO. */
-static inline gimple *
-get_later_stmt (gimple *stmt1, gimple *stmt2)
+static inline stmt_vec_info
+get_later_stmt (stmt_vec_info stmt1_info, stmt_vec_info stmt2_info)
{
- unsigned int uid1, uid2;
-
- if (stmt1 == NULL)
- return stmt2;
-
- if (stmt2 == NULL)
- return stmt1;
-
- uid1 = gimple_uid (stmt1);
- uid2 = gimple_uid (stmt2);
+ gcc_checking_assert ((STMT_VINFO_IN_PATTERN_P (stmt1_info)
+ || !STMT_VINFO_RELATED_STMT (stmt1_info))
+ && (STMT_VINFO_IN_PATTERN_P (stmt2_info)
+ || !STMT_VINFO_RELATED_STMT (stmt2_info)));
- if (uid1 == 0 || uid2 == 0)
- return NULL;
-
- gcc_assert (uid1 <= stmt_vec_info_vec->length ()
- && uid2 <= stmt_vec_info_vec->length ());
- gcc_checking_assert ((STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (stmt1))
- || !STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt1)))
- && (STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (stmt2))
- || !STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt2))));
-
- if (uid1 > uid2)
- return stmt1;
+ if (gimple_uid (stmt1_info->stmt) > gimple_uid (stmt2_info->stmt))
+ return stmt1_info;
else
- return stmt2;
+ return stmt2_info;
}
/* Return TRUE if a statement represented by STMT_INFO is a part of a
@@ -1152,16 +1117,29 @@ get_later_stmt (gimple *stmt1, gimple *stmt2)
static inline bool
is_pattern_stmt_p (stmt_vec_info stmt_info)
{
- gimple *related_stmt;
- stmt_vec_info related_stmt_info;
+ return stmt_info->pattern_stmt_p;
+}
- related_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
- if (related_stmt
- && (related_stmt_info = vinfo_for_stmt (related_stmt))
- && STMT_VINFO_IN_PATTERN_P (related_stmt_info))
- return true;
+/* If STMT_INFO is a pattern statement, return the statement that it
+ replaces, otherwise return STMT_INFO itself. */
- return false;
+inline stmt_vec_info
+vect_orig_stmt (stmt_vec_info stmt_info)
+{
+ if (is_pattern_stmt_p (stmt_info))
+ return STMT_VINFO_RELATED_STMT (stmt_info);
+ return stmt_info;
+}
+
+/* If STMT_INFO has been replaced by a pattern statement, return the
+ replacement statement, otherwise return STMT_INFO itself. */
+
+inline stmt_vec_info
+vect_stmt_to_vectorize (stmt_vec_info stmt_info)
+{
+ if (STMT_VINFO_IN_PATTERN_P (stmt_info))
+ return STMT_VINFO_RELATED_STMT (stmt_info);
+ return stmt_info;
}
/* Return true if BB is a loop header. */
@@ -1253,8 +1231,7 @@ add_stmt_costs (void *data, stmt_vector_for_cost *cost_vec)
stmt_info_for_cost *cost;
unsigned i;
FOR_EACH_VEC_ELT (*cost_vec, i, cost)
- add_stmt_cost (data, cost->count, cost->kind,
- cost->stmt ? vinfo_for_stmt (cost->stmt) : NULL,
+ add_stmt_cost (data, cost->count, cost->kind, cost->stmt_info,
cost->misalign, cost->where);
}
@@ -1265,16 +1242,15 @@ add_stmt_costs (void *data, stmt_vector_for_cost *cost_vec)
#define DR_MISALIGNMENT_UNINITIALIZED (-2)
inline void
-set_dr_misalignment (struct data_reference *dr, int val)
+set_dr_misalignment (dr_vec_info *dr_info, int val)
{
- dataref_aux *data_aux = DR_VECT_AUX (dr);
- data_aux->misalignment = val;
+ dr_info->misalignment = val;
}
inline int
-dr_misalignment (struct data_reference *dr)
+dr_misalignment (dr_vec_info *dr_info)
{
- int misalign = DR_VECT_AUX (dr)->misalignment;
+ int misalign = dr_info->misalignment;
gcc_assert (misalign != DR_MISALIGNMENT_UNINITIALIZED);
return misalign;
}
@@ -1285,72 +1261,55 @@ dr_misalignment (struct data_reference *dr)
#define SET_DR_MISALIGNMENT(DR, VAL) set_dr_misalignment (DR, VAL)
/* Only defined once DR_MISALIGNMENT is defined. */
-#define DR_TARGET_ALIGNMENT(DR) DR_VECT_AUX (DR)->target_alignment
+#define DR_TARGET_ALIGNMENT(DR) ((DR)->target_alignment)
-/* Return true if data access DR is aligned to its target alignment
+/* Return true if data access DR_INFO is aligned to its target alignment
(which may be less than a full vector). */
static inline bool
-aligned_access_p (struct data_reference *data_ref_info)
+aligned_access_p (dr_vec_info *dr_info)
{
- return (DR_MISALIGNMENT (data_ref_info) == 0);
+ return (DR_MISALIGNMENT (dr_info) == 0);
}
/* Return TRUE if the alignment of the data access is known, and FALSE
otherwise. */
static inline bool
-known_alignment_for_access_p (struct data_reference *data_ref_info)
+known_alignment_for_access_p (dr_vec_info *dr_info)
{
- return (DR_MISALIGNMENT (data_ref_info) != DR_MISALIGNMENT_UNKNOWN);
+ return (DR_MISALIGNMENT (dr_info) != DR_MISALIGNMENT_UNKNOWN);
}
/* Return the minimum alignment in bytes that the vectorized version
- of DR is guaranteed to have. */
+ of DR_INFO is guaranteed to have. */
static inline unsigned int
-vect_known_alignment_in_bytes (struct data_reference *dr)
+vect_known_alignment_in_bytes (dr_vec_info *dr_info)
{
- if (DR_MISALIGNMENT (dr) == DR_MISALIGNMENT_UNKNOWN)
- return TYPE_ALIGN_UNIT (TREE_TYPE (DR_REF (dr)));
- if (DR_MISALIGNMENT (dr) == 0)
- return DR_TARGET_ALIGNMENT (dr);
- return DR_MISALIGNMENT (dr) & -DR_MISALIGNMENT (dr);
+ if (DR_MISALIGNMENT (dr_info) == DR_MISALIGNMENT_UNKNOWN)
+ return TYPE_ALIGN_UNIT (TREE_TYPE (DR_REF (dr_info->dr)));
+ if (DR_MISALIGNMENT (dr_info) == 0)
+ return DR_TARGET_ALIGNMENT (dr_info);
+ return DR_MISALIGNMENT (dr_info) & -DR_MISALIGNMENT (dr_info);
}
-/* Return the behavior of DR with respect to the vectorization context
+/* Return the behavior of DR_INFO with respect to the vectorization context
(which for outer loop vectorization might not be the behavior recorded
- in DR itself). */
+ in DR_INFO itself). */
static inline innermost_loop_behavior *
-vect_dr_behavior (data_reference *dr)
+vect_dr_behavior (dr_vec_info *dr_info)
{
- gimple *stmt = DR_STMT (dr);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ stmt_vec_info stmt_info = dr_info->stmt;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
if (loop_vinfo == NULL
- || !nested_in_vect_loop_p (LOOP_VINFO_LOOP (loop_vinfo), stmt))
- return &DR_INNERMOST (dr);
+ || !nested_in_vect_loop_p (LOOP_VINFO_LOOP (loop_vinfo), stmt_info))
+ return &DR_INNERMOST (dr_info->dr);
else
return &STMT_VINFO_DR_WRT_VEC_LOOP (stmt_info);
}
-/* Return the stmt DR is in. For DR_STMT that have been replaced by
- a pattern this returns the corresponding pattern stmt. Otherwise
- DR_STMT is returned. */
-
-inline gimple *
-vect_dr_stmt (data_reference *dr)
-{
- gimple *stmt = DR_STMT (dr);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
- if (STMT_VINFO_IN_PATTERN_P (stmt_info))
- return STMT_VINFO_RELATED_STMT (stmt_info);
- /* DR_STMT should never refer to a stmt in a pattern replacement. */
- gcc_checking_assert (!STMT_VINFO_RELATED_STMT (stmt_info));
- return stmt;
-}
-
/* Return true if the vect cost model is unlimited. */
static inline bool
unlimited_cost_model (loop_p loop)
@@ -1439,17 +1398,17 @@ vect_max_vf (loop_vec_info loop_vinfo)
return MAX_VECTORIZATION_FACTOR;
}
-/* Return the size of the value accessed by unvectorized data reference DR.
- This is only valid once STMT_VINFO_VECTYPE has been calculated for the
- associated gimple statement, since that guarantees that DR accesses
- either a scalar or a scalar equivalent. ("Scalar equivalent" here
- includes things like V1SI, which can be vectorized in the same way
+/* Return the size of the value accessed by unvectorized data reference
+ DR_INFO. This is only valid once STMT_VINFO_VECTYPE has been calculated
+ for the associated gimple statement, since that guarantees that DR_INFO
+ accesses either a scalar or a scalar equivalent. ("Scalar equivalent"
+ here includes things like V1SI, which can be vectorized in the same way
as a plain SI.) */
inline unsigned int
-vect_get_scalar_dr_size (struct data_reference *dr)
+vect_get_scalar_dr_size (dr_vec_info *dr_info)
{
- return tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr))));
+ return tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_info->dr))));
}
/* Source location + hotness information. */
@@ -1493,42 +1452,41 @@ extern tree get_mask_type_for_scalar_type (tree);
extern tree get_same_sized_vectype (tree, tree);
extern bool vect_get_loop_mask_type (loop_vec_info);
extern bool vect_is_simple_use (tree, vec_info *, enum vect_def_type *,
- gimple ** = NULL);
+ stmt_vec_info * = NULL, gimple ** = NULL);
extern bool vect_is_simple_use (tree, vec_info *, enum vect_def_type *,
- tree *, gimple ** = NULL);
-extern bool supportable_widening_operation (enum tree_code, gimple *, tree,
- tree, enum tree_code *,
+ tree *, stmt_vec_info * = NULL,
+ gimple ** = NULL);
+extern bool supportable_widening_operation (enum tree_code, stmt_vec_info,
+ tree, tree, enum tree_code *,
enum tree_code *, int *,
vec<tree> *);
extern bool supportable_narrowing_operation (enum tree_code, tree, tree,
enum tree_code *,
int *, vec<tree> *);
-extern stmt_vec_info new_stmt_vec_info (gimple *stmt, vec_info *);
-extern void free_stmt_vec_info (gimple *stmt);
extern unsigned record_stmt_cost (stmt_vector_for_cost *, int,
enum vect_cost_for_stmt, stmt_vec_info,
int, enum vect_cost_model_location);
-extern void vect_finish_replace_stmt (gimple *, gimple *);
-extern void vect_finish_stmt_generation (gimple *, gimple *,
- gimple_stmt_iterator *);
+extern stmt_vec_info vect_finish_replace_stmt (stmt_vec_info, gimple *);
+extern stmt_vec_info vect_finish_stmt_generation (stmt_vec_info, gimple *,
+ gimple_stmt_iterator *);
extern bool vect_mark_stmts_to_be_vectorized (loop_vec_info);
-extern tree vect_get_store_rhs (gimple *);
-extern tree vect_get_vec_def_for_operand_1 (gimple *, enum vect_def_type);
-extern tree vect_get_vec_def_for_operand (tree, gimple *, tree = NULL);
-extern void vect_get_vec_defs (tree, tree, gimple *, vec<tree> *,
+extern tree vect_get_store_rhs (stmt_vec_info);
+extern tree vect_get_vec_def_for_operand_1 (stmt_vec_info, enum vect_def_type);
+extern tree vect_get_vec_def_for_operand (tree, stmt_vec_info, tree = NULL);
+extern void vect_get_vec_defs (tree, tree, stmt_vec_info, vec<tree> *,
vec<tree> *, slp_tree);
-extern void vect_get_vec_defs_for_stmt_copy (enum vect_def_type *,
+extern void vect_get_vec_defs_for_stmt_copy (vec_info *,
vec<tree> *, vec<tree> *);
-extern tree vect_init_vector (gimple *, tree, tree,
+extern tree vect_init_vector (stmt_vec_info, tree, tree,
gimple_stmt_iterator *);
-extern tree vect_get_vec_def_for_stmt_copy (enum vect_def_type, tree);
-extern bool vect_transform_stmt (gimple *, gimple_stmt_iterator *,
- bool *, slp_tree, slp_instance);
-extern void vect_remove_stores (gimple *);
-extern bool vect_analyze_stmt (gimple *, bool *, slp_tree, slp_instance,
+extern tree vect_get_vec_def_for_stmt_copy (vec_info *, tree);
+extern bool vect_transform_stmt (stmt_vec_info, gimple_stmt_iterator *,
+ slp_tree, slp_instance);
+extern void vect_remove_stores (stmt_vec_info);
+extern bool vect_analyze_stmt (stmt_vec_info, bool *, slp_tree, slp_instance,
stmt_vector_for_cost *);
-extern bool vectorizable_condition (gimple *, gimple_stmt_iterator *,
- gimple **, tree, int, slp_tree,
+extern bool vectorizable_condition (stmt_vec_info, gimple_stmt_iterator *,
+ stmt_vec_info *, tree, int, slp_tree,
stmt_vector_for_cost *);
extern void vect_get_load_cost (stmt_vec_info, int, bool,
unsigned int *, unsigned int *,
@@ -1548,8 +1506,8 @@ extern tree vect_get_mask_type_for_stmt (stmt_vec_info);
/* In tree-vect-data-refs.c. */
extern bool vect_can_force_dr_alignment_p (const_tree, unsigned int);
extern enum dr_alignment_support vect_supportable_dr_alignment
- (struct data_reference *, bool);
-extern tree vect_get_smallest_scalar_type (gimple *, HOST_WIDE_INT *,
+ (dr_vec_info *, bool);
+extern tree vect_get_smallest_scalar_type (stmt_vec_info, HOST_WIDE_INT *,
HOST_WIDE_INT *);
extern bool vect_analyze_data_ref_dependences (loop_vec_info, unsigned int *);
extern bool vect_slp_analyze_instance_dependence (slp_instance);
@@ -1561,42 +1519,42 @@ extern bool vect_analyze_data_ref_accesses (vec_info *);
extern bool vect_prune_runtime_alias_test_list (loop_vec_info);
extern bool vect_gather_scatter_fn_p (bool, bool, tree, tree, unsigned int,
signop, int, internal_fn *, tree *);
-extern bool vect_check_gather_scatter (gimple *, loop_vec_info,
+extern bool vect_check_gather_scatter (stmt_vec_info, loop_vec_info,
gather_scatter_info *);
extern bool vect_find_stmt_data_reference (loop_p, gimple *,
vec<data_reference_p> *);
extern bool vect_analyze_data_refs (vec_info *, poly_uint64 *);
extern void vect_record_base_alignments (vec_info *);
-extern tree vect_create_data_ref_ptr (gimple *, tree, struct loop *, tree,
+extern tree vect_create_data_ref_ptr (stmt_vec_info, tree, struct loop *, tree,
tree *, gimple_stmt_iterator *,
- gimple **, bool, bool *,
+ gimple **, bool,
tree = NULL_TREE, tree = NULL_TREE);
-extern tree bump_vector_ptr (tree, gimple *, gimple_stmt_iterator *, gimple *,
- tree);
+extern tree bump_vector_ptr (tree, gimple *, gimple_stmt_iterator *,
+ stmt_vec_info, tree);
extern void vect_copy_ref_info (tree, tree);
extern tree vect_create_destination_var (tree, tree);
extern bool vect_grouped_store_supported (tree, unsigned HOST_WIDE_INT);
extern bool vect_store_lanes_supported (tree, unsigned HOST_WIDE_INT, bool);
extern bool vect_grouped_load_supported (tree, bool, unsigned HOST_WIDE_INT);
extern bool vect_load_lanes_supported (tree, unsigned HOST_WIDE_INT, bool);
-extern void vect_permute_store_chain (vec<tree> ,unsigned int, gimple *,
+extern void vect_permute_store_chain (vec<tree> ,unsigned int, stmt_vec_info,
gimple_stmt_iterator *, vec<tree> *);
-extern tree vect_setup_realignment (gimple *, gimple_stmt_iterator *, tree *,
- enum dr_alignment_support, tree,
+extern tree vect_setup_realignment (stmt_vec_info, gimple_stmt_iterator *,
+ tree *, enum dr_alignment_support, tree,
struct loop **);
-extern void vect_transform_grouped_load (gimple *, vec<tree> , int,
+extern void vect_transform_grouped_load (stmt_vec_info, vec<tree> , int,
gimple_stmt_iterator *);
-extern void vect_record_grouped_load_vectors (gimple *, vec<tree> );
+extern void vect_record_grouped_load_vectors (stmt_vec_info, vec<tree>);
extern tree vect_get_new_vect_var (tree, enum vect_var_kind, const char *);
extern tree vect_get_new_ssa_name (tree, enum vect_var_kind,
const char * = NULL);
-extern tree vect_create_addr_base_for_vector_ref (gimple *, gimple_seq *,
+extern tree vect_create_addr_base_for_vector_ref (stmt_vec_info, gimple_seq *,
tree, tree = NULL_TREE);
/* In tree-vect-loop.c. */
/* FORNOW: Used in tree-parloops.c. */
-extern gimple *vect_force_simple_reduction (loop_vec_info, gimple *,
- bool *, bool);
+extern stmt_vec_info vect_force_simple_reduction (loop_vec_info, stmt_vec_info,
+ bool *, bool);
/* Used in gimple-loop-interchange.c. */
extern bool check_reduction_path (dump_user_location_t, loop_p, gphi *, tree,
enum tree_code);
@@ -1616,16 +1574,16 @@ extern tree vect_get_loop_mask (gimple_stmt_iterator *, vec_loop_masks *,
/* Drive for loop transformation stage. */
extern struct loop *vect_transform_loop (loop_vec_info);
extern loop_vec_info vect_analyze_loop_form (struct loop *, vec_info_shared *);
-extern bool vectorizable_live_operation (gimple *, gimple_stmt_iterator *,
- slp_tree, int, gimple **,
+extern bool vectorizable_live_operation (stmt_vec_info, gimple_stmt_iterator *,
+ slp_tree, int, stmt_vec_info *,
stmt_vector_for_cost *);
-extern bool vectorizable_reduction (gimple *, gimple_stmt_iterator *,
- gimple **, slp_tree, slp_instance,
+extern bool vectorizable_reduction (stmt_vec_info, gimple_stmt_iterator *,
+ stmt_vec_info *, slp_tree, slp_instance,
stmt_vector_for_cost *);
-extern bool vectorizable_induction (gimple *, gimple_stmt_iterator *,
- gimple **, slp_tree,
+extern bool vectorizable_induction (stmt_vec_info, gimple_stmt_iterator *,
+ stmt_vec_info *, slp_tree,
stmt_vector_for_cost *);
-extern tree get_initial_def_for_reduction (gimple *, tree, tree *);
+extern tree get_initial_def_for_reduction (stmt_vec_info, tree, tree *);
extern bool vect_worthwhile_without_simd_p (vec_info *, tree_code);
extern int vect_get_known_peeling_cost (loop_vec_info, int, int *,
stmt_vector_for_cost *,
@@ -1634,25 +1592,25 @@ extern int vect_get_known_peeling_cost (loop_vec_info, int, int *,
extern tree cse_and_gimplify_to_preheader (loop_vec_info, tree);
/* In tree-vect-slp.c. */
-extern void vect_free_slp_instance (slp_instance);
+extern void vect_free_slp_instance (slp_instance, bool);
extern bool vect_transform_slp_perm_load (slp_tree, vec<tree> ,
gimple_stmt_iterator *, poly_uint64,
slp_instance, bool, unsigned *);
extern bool vect_slp_analyze_operations (vec_info *);
-extern bool vect_schedule_slp (vec_info *);
+extern void vect_schedule_slp (vec_info *);
extern bool vect_analyze_slp (vec_info *, unsigned);
extern bool vect_make_slp_decision (loop_vec_info);
extern void vect_detect_hybrid_slp (loop_vec_info);
extern void vect_get_slp_defs (vec<tree> , slp_tree, vec<vec<tree> > *);
extern bool vect_slp_bb (basic_block);
-extern gimple *vect_find_last_scalar_stmt_in_slp (slp_tree);
-extern bool is_simple_and_all_uses_invariant (gimple *, loop_vec_info);
+extern stmt_vec_info vect_find_last_scalar_stmt_in_slp (slp_tree);
+extern bool is_simple_and_all_uses_invariant (stmt_vec_info, loop_vec_info);
extern bool can_duplicate_and_interleave_p (unsigned int, machine_mode,
unsigned int * = NULL,
tree * = NULL, tree * = NULL);
extern void duplicate_and_interleave (gimple_seq *, tree, vec<tree>,
unsigned int, vec<tree> &);
-extern int vect_get_place_in_interleaving_chain (gimple *, gimple *);
+extern int vect_get_place_in_interleaving_chain (stmt_vec_info, stmt_vec_info);
/* In tree-vect-patterns.c. */
/* Pattern recognition functions.
@@ -1662,7 +1620,6 @@ void vect_pattern_recog (vec_info *);
/* In tree-vectorizer.c. */
unsigned vectorize_loops (void);
-bool vect_stmt_in_region_p (vec_info *, gimple *);
void vect_free_loop_info_assumptions (struct loop *);
#endif /* GCC_TREE_VECTORIZER_H */
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 7ab8898..ab222a3 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -67,6 +67,7 @@ along with GCC; see the file COPYING3. If not see
#include "attribs.h"
#include "vr-values.h"
#include "builtins.h"
+#include "wide-int-range.h"
/* Set of SSA names found live during the RPO traversal of the function
for still active basic-blocks. */
@@ -120,10 +121,6 @@ static bitmap need_assert_for;
ASSERT_EXPRs for SSA name N_I should be inserted. */
static assert_locus **asserts_for;
-vec<edge> to_remove_edges;
-vec<switch_update> to_update_switch_stmts;
-
-
/* Return the maximum value for TYPE. */
tree
@@ -441,7 +438,7 @@ set_and_canonicalize_value_range (value_range *vr, enum value_range_type t,
/* Copy value range FROM into value range TO. */
void
-copy_value_range (value_range *to, value_range *from)
+copy_value_range (value_range *to, const value_range *from)
{
set_value_range (to, from->type, from->min, from->max, from->equiv);
}
@@ -477,42 +474,6 @@ set_value_range_to_null (value_range *vr, tree type)
set_value_range_to_value (vr, build_int_cst (type, 0), vr->equiv);
}
-
-/* If abs (min) < abs (max), set VR to [-max, max], if
- abs (min) >= abs (max), set VR to [-min, min]. */
-
-static void
-abs_extent_range (value_range *vr, tree min, tree max)
-{
- int cmp;
-
- gcc_assert (TREE_CODE (min) == INTEGER_CST);
- gcc_assert (TREE_CODE (max) == INTEGER_CST);
- gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (min)));
- gcc_assert (!TYPE_UNSIGNED (TREE_TYPE (min)));
- min = fold_unary (ABS_EXPR, TREE_TYPE (min), min);
- max = fold_unary (ABS_EXPR, TREE_TYPE (max), max);
- if (TREE_OVERFLOW (min) || TREE_OVERFLOW (max))
- {
- set_value_range_to_varying (vr);
- return;
- }
- cmp = compare_values (min, max);
- if (cmp == -1)
- min = fold_unary (NEGATE_EXPR, TREE_TYPE (min), max);
- else if (cmp == 0 || cmp == 1)
- {
- max = min;
- min = fold_unary (NEGATE_EXPR, TREE_TYPE (min), min);
- }
- else
- {
- set_value_range_to_varying (vr);
- return;
- }
- set_and_canonicalize_value_range (vr, VR_RANGE, min, max, NULL);
-}
-
/* Return true, if VAL1 and VAL2 are equal values for VRP purposes. */
bool
@@ -537,21 +498,10 @@ vrp_bitmap_equal_p (const_bitmap b1, const_bitmap b2)
&& bitmap_equal_p (b1, b2)));
}
-/* Return true if VR is ~[0, 0]. */
-
-bool
-range_is_nonnull (value_range *vr)
-{
- return vr->type == VR_ANTI_RANGE
- && integer_zerop (vr->min)
- && integer_zerop (vr->max);
-}
-
-
/* Return true if VR is [0, 0]. */
static inline bool
-range_is_null (value_range *vr)
+range_is_null (const value_range *vr)
{
return vr->type == VR_RANGE
&& integer_zerop (vr->min)
@@ -562,7 +512,7 @@ range_is_null (value_range *vr)
a singleton. */
bool
-range_int_cst_p (value_range *vr)
+range_int_cst_p (const value_range *vr)
{
return (vr->type == VR_RANGE
&& TREE_CODE (vr->max) == INTEGER_CST
@@ -572,7 +522,7 @@ range_int_cst_p (value_range *vr)
/* Return true if VR is a INTEGER_CST singleton. */
bool
-range_int_cst_singleton_p (value_range *vr)
+range_int_cst_singleton_p (const value_range *vr)
{
return (range_int_cst_p (vr)
&& tree_int_cst_equal (vr->min, vr->max));
@@ -581,7 +531,7 @@ range_int_cst_singleton_p (value_range *vr)
/* Return true if value range VR involves at least one symbol. */
bool
-symbolic_range_p (value_range *vr)
+symbolic_range_p (const value_range *vr)
{
return (!is_gimple_min_invariant (vr->min)
|| !is_gimple_min_invariant (vr->max));
@@ -902,7 +852,7 @@ value_inside_range (tree val, tree min, tree max)
*/
static inline bool
-value_ranges_intersect_p (value_range *vr0, value_range *vr1)
+value_ranges_intersect_p (const value_range *vr0, const value_range *vr1)
{
/* The value ranges do not intersect if the maximum of the first range is
less than the minimum of the second range or vice versa.
@@ -915,20 +865,31 @@ value_ranges_intersect_p (value_range *vr0, value_range *vr1)
}
-/* Return 1 if [MIN, MAX] includes the value zero, 0 if it does not
- include the value zero, -2 if we cannot tell. */
+/* Return TRUE if *VR includes the value zero. */
-int
-range_includes_zero_p (tree min, tree max)
+bool
+range_includes_zero_p (const value_range *vr)
{
- tree zero = build_int_cst (TREE_TYPE (min), 0);
- return value_inside_range (zero, min, max);
+ if (vr->type == VR_VARYING)
+ return true;
+
+ /* Ughh, we don't know. We choose not to optimize. */
+ if (vr->type == VR_UNDEFINED)
+ return true;
+
+ tree zero = build_int_cst (TREE_TYPE (vr->min), 0);
+ if (vr->type == VR_ANTI_RANGE)
+ {
+ int res = value_inside_range (zero, vr->min, vr->max);
+ return res == 0 || res == -2;
+ }
+ return value_inside_range (zero, vr->min, vr->max) != 0;
}
/* Return true if *VR is know to only contain nonnegative values. */
static inline bool
-value_range_nonnegative_p (value_range *vr)
+value_range_nonnegative_p (const value_range *vr)
{
/* Testing for VR_ANTI_RANGE is not useful here as any anti-range
which would return a useful value should be encoded as a
@@ -946,7 +907,7 @@ value_range_nonnegative_p (value_range *vr)
otherwise return NULL_TREE. */
tree
-value_range_constant_singleton (value_range *vr)
+value_range_constant_singleton (const value_range *vr)
{
if (vr->type == VR_RANGE
&& vrp_operand_equal_p (vr->min, vr->max)
@@ -956,98 +917,16 @@ value_range_constant_singleton (value_range *vr)
return NULL_TREE;
}
-/* Wrapper around wide_int_binop that adjusts for overflow.
-
- Return true if we can compute the result; i.e. if the operation
- doesn't overflow or if the overflow is undefined. In the latter
- case (if the operation overflows and overflow is undefined), then
- adjust the result to be -INF or +INF depending on CODE, VAL1 and
- VAL2. Return the value in *RES.
+/* Value range wrapper for wide_int_range_set_zero_nonzero_bits.
- Return false for division by zero, for which the result is
- indeterminate. */
-
-static bool
-wide_int_binop_overflow (wide_int &res,
- enum tree_code code,
- const wide_int &w0, const wide_int &w1,
- signop sign, bool overflow_undefined)
-{
- wi::overflow_type overflow;
- if (!wide_int_binop (res, code, w0, w1, sign, &overflow))
- return false;
+ Compute MAY_BE_NONZERO and MUST_BE_NONZERO bit masks for range in VR.
- /* If the operation overflowed return -INF or +INF depending on the
- operation and the combination of signs of the operands. */
- if (overflow && overflow_undefined)
- {
- switch (code)
- {
- case MULT_EXPR:
- /* For multiplication, the sign of the overflow is given
- by the comparison of the signs of the operands. */
- if (sign == UNSIGNED || w0.sign_mask () == w1.sign_mask ())
- res = wi::max_value (w0.get_precision (), sign);
- else
- res = wi::min_value (w0.get_precision (), sign);
- return true;
-
- case TRUNC_DIV_EXPR:
- case FLOOR_DIV_EXPR:
- case CEIL_DIV_EXPR:
- case EXACT_DIV_EXPR:
- case ROUND_DIV_EXPR:
- /* For division, the only case is -INF / -1 = +INF. */
- res = wi::max_value (w0.get_precision (), sign);
- return true;
-
- default:
- gcc_unreachable ();
- }
- }
- return !overflow;
-}
-
-/* For range [LB, UB] compute two wide_int bitmasks. In *MAY_BE_NONZERO
- bitmask, if some bit is unset, it means for all numbers in the range
- the bit is 0, otherwise it might be 0 or 1. In *MUST_BE_NONZERO
- bitmask, if some bit is set, it means for all numbers in the range
- the bit is 1, otherwise it might be 0 or 1. */
-
-void
-zero_nonzero_bits_from_bounds (signop sign,
- const wide_int &lb, const wide_int &ub,
- wide_int *may_be_nonzero,
- wide_int *must_be_nonzero)
-{
- *may_be_nonzero = wi::minus_one (lb.get_precision ());
- *must_be_nonzero = wi::zero (lb.get_precision ());
-
- if (wi::eq_p (lb, ub))
- {
- *may_be_nonzero = lb;
- *must_be_nonzero = *may_be_nonzero;
- }
- else if (wi::ge_p (lb, 0, sign) || wi::lt_p (ub, 0, sign))
- {
- wide_int xor_mask = lb ^ ub;
- *may_be_nonzero = lb | ub;
- *must_be_nonzero = lb & ub;
- if (xor_mask != 0)
- {
- wide_int mask = wi::mask (wi::floor_log2 (xor_mask), false,
- may_be_nonzero->get_precision ());
- *may_be_nonzero = *may_be_nonzero | mask;
- *must_be_nonzero = wi::bit_and_not (*must_be_nonzero, mask);
- }
- }
-}
-
-/* Like zero_nonzero_bits_from_bounds, but use the range in value_range VR. */
+ Return TRUE if VR was a constant range and we were able to compute
+ the bit masks. */
bool
-zero_nonzero_bits_from_vr (const tree expr_type,
- value_range *vr,
+vrp_set_zero_nonzero_bits (const tree expr_type,
+ const value_range *vr,
wide_int *may_be_nonzero,
wide_int *must_be_nonzero)
{
@@ -1057,10 +936,10 @@ zero_nonzero_bits_from_vr (const tree expr_type,
*must_be_nonzero = wi::zero (TYPE_PRECISION (expr_type));
return false;
}
-
- zero_nonzero_bits_from_bounds (TYPE_SIGN (expr_type),
- wi::to_wide (vr->min), wi::to_wide (vr->max),
- may_be_nonzero, must_be_nonzero);
+ wide_int_range_set_zero_nonzero_bits (TYPE_SIGN (expr_type),
+ wi::to_wide (vr->min),
+ wi::to_wide (vr->max),
+ *may_be_nonzero, *must_be_nonzero);
return true;
}
@@ -1070,7 +949,7 @@ zero_nonzero_bits_from_vr (const tree expr_type,
*VR1 will be VR_UNDEFINED. */
static bool
-ranges_from_anti_range (value_range *ar,
+ranges_from_anti_range (const value_range *ar,
value_range *vr0, value_range *vr1)
{
tree type = TREE_TYPE (ar->min);
@@ -1078,6 +957,9 @@ ranges_from_anti_range (value_range *ar,
vr0->type = VR_UNDEFINED;
vr1->type = VR_UNDEFINED;
+ /* As a future improvement, we could handle ~[0, A] as: [-INF, -1] U
+ [A+1, +INF]. Not sure if this helps in practice, though. */
+
if (ar->type != VR_ANTI_RANGE
|| TREE_CODE (ar->min) != INTEGER_CST
|| TREE_CODE (ar->max) != INTEGER_CST
@@ -1106,169 +988,42 @@ ranges_from_anti_range (value_range *ar,
return vr0->type != VR_UNDEFINED;
}
-/* Order 2 sets of wide int ranges (w0/w1, w2/w3) and set MIN/MAX
- accordingly. */
-
-static void
-wide_int_range_min_max (wide_int &min, wide_int &max,
- wide_int &w0, wide_int &w1, wide_int &w2, wide_int &w3,
- signop sign)
-{
- /* Order pairs w0,w1 and w2,w3. */
- if (wi::gt_p (w0, w1, sign))
- std::swap (w0, w1);
- if (wi::gt_p (w2, w3, sign))
- std::swap (w2, w3);
-
- /* Choose min and max from the ordered pairs. */
- min = wi::min (w0, w2, sign);
- max = wi::max (w1, w3, sign);
-}
+/* Extract the components of a value range into a pair of wide ints in
+ [WMIN, WMAX].
-/* Calculate the cross product of two sets of ranges (VR0 and VR1) and
- store the result in [RES_LB, RES_UB].
+ If the value range is anything but a VR_*RANGE of constants, the
+ resulting wide ints are set to [-MIN, +MAX] for the type. */
- CODE is the operation to perform with sign SIGN.
-
- OVERFLOW_UNDEFINED is set if overflow is undefined for the operation type.
-
- Return TRUE if we were able to calculate the cross product. */
-
-bool
-wide_int_range_cross_product (wide_int &res_lb, wide_int &res_ub,
- enum tree_code code, signop sign,
- const wide_int &vr0_lb, const wide_int &vr0_ub,
- const wide_int &vr1_lb, const wide_int &vr1_ub,
- bool overflow_undefined)
+static void inline
+extract_range_into_wide_ints (const value_range *vr,
+ signop sign, unsigned prec,
+ wide_int &wmin, wide_int &wmax)
{
- wide_int cp1, cp2, cp3, cp4;
-
- /* Compute the 4 cross operations, bailing if we get an overflow we
- can't handle. */
-
- if (!wide_int_binop_overflow (cp1, code, vr0_lb, vr1_lb, sign,
- overflow_undefined))
- return false;
-
- if (wi::eq_p (vr0_lb, vr0_ub))
- cp3 = cp1;
- else if (!wide_int_binop_overflow (cp3, code, vr0_ub, vr1_lb, sign,
- overflow_undefined))
- return false;
-
- if (wi::eq_p (vr1_lb, vr1_ub))
- cp2 = cp1;
- else if (!wide_int_binop_overflow (cp2, code, vr0_lb, vr1_ub, sign,
- overflow_undefined))
- return false;
-
- if (wi::eq_p (vr0_lb, vr0_ub))
- cp4 = cp2;
- else if (!wide_int_binop_overflow (cp4, code, vr0_ub, vr1_ub, sign,
- overflow_undefined))
- return false;
-
- wide_int_range_min_max (res_lb, res_ub, cp1, cp2, cp3, cp4, sign);
- return true;
-}
-
-/* Multiply two ranges when TYPE_OVERFLOW_WRAPS:
-
- [RES_LB, RES_UB] = [MIN0, MAX0] * [MIN1, MAX1]
-
- This is basically fancy code so we don't drop to varying with an
- unsigned [-3,-1]*[-3,-1]. */
-
-bool
-wide_int_range_mult_wrapping (wide_int &res_lb,
- wide_int &res_ub,
- signop sign,
- unsigned prec,
- const wide_int &min0_,
- const wide_int &max0_,
- const wide_int &min1_,
- const wide_int &max1_)
-{
- /* This test requires 2*prec bits if both operands are signed and
- 2*prec + 2 bits if either is not. Therefore, extend the values
- using the sign of the result to PREC2. From here on out,
- everthing is just signed math no matter what the input types
- were. */
- widest2_int min0 = widest2_int::from (min0_, sign);
- widest2_int max0 = widest2_int::from (max0_, sign);
- widest2_int min1 = widest2_int::from (min1_, sign);
- widest2_int max1 = widest2_int::from (max1_, sign);
- widest2_int sizem1 = wi::mask <widest2_int> (prec, false);
- widest2_int size = sizem1 + 1;
-
- /* Canonicalize the intervals. */
- if (sign == UNSIGNED)
- {
- if (wi::ltu_p (size, min0 + max0))
- {
- min0 -= size;
- max0 -= size;
- }
-
- if (wi::ltu_p (size, min1 + max1))
- {
- min1 -= size;
- max1 -= size;
- }
+ if ((vr->type == VR_RANGE
+ || vr->type == VR_ANTI_RANGE)
+ && TREE_CODE (vr->min) == INTEGER_CST
+ && TREE_CODE (vr->max) == INTEGER_CST)
+ {
+ wmin = wi::to_wide (vr->min);
+ wmax = wi::to_wide (vr->max);
+ }
+ else
+ {
+ wmin = wi::min_value (prec, sign);
+ wmax = wi::max_value (prec, sign);
}
-
- widest2_int prod0 = min0 * min1;
- widest2_int prod1 = min0 * max1;
- widest2_int prod2 = max0 * min1;
- widest2_int prod3 = max0 * max1;
-
- /* Sort the 4 products so that min is in prod0 and max is in
- prod3. */
- /* min0min1 > max0max1 */
- if (prod0 > prod3)
- std::swap (prod0, prod3);
-
- /* min0max1 > max0min1 */
- if (prod1 > prod2)
- std::swap (prod1, prod2);
-
- if (prod0 > prod1)
- std::swap (prod0, prod1);
-
- if (prod2 > prod3)
- std::swap (prod2, prod3);
-
- /* diff = max - min. */
- prod2 = prod3 - prod0;
- if (wi::geu_p (prod2, sizem1))
- /* The range covers all values. */
- return false;
-
- res_lb = wide_int::from (prod0, prec, sign);
- res_ub = wide_int::from (prod3, prec, sign);
- return true;
}
-/* Helper to extract a value-range *VR for a multiplicative operation
- *VR0 CODE *VR1. */
+/* Value range wrapper for wide_int_range_multiplicative_op:
+
+ *VR = *VR0 .CODE. *VR1. */
static void
-extract_range_from_multiplicative_op_1 (value_range *vr,
- enum tree_code code,
- value_range *vr0, value_range *vr1)
+extract_range_from_multiplicative_op (value_range *vr,
+ enum tree_code code,
+ const value_range *vr0,
+ const value_range *vr1)
{
- /* Multiplications, divisions and shifts are a bit tricky to handle,
- depending on the mix of signs we have in the two ranges, we
- need to operate on different values to get the minimum and
- maximum values for the new range. One approach is to figure
- out all the variations of range combinations and do the
- operations.
-
- However, this involves several calls to compare_values and it
- is pretty convoluted. It's simpler to do the 4 operations
- (MIN0 OP MIN1, MIN0 OP MAX1, MAX0 OP MIN1 and MAX0 OP MAX0 OP
- MAX1) and then figure the smallest and largest values to form
- the new range. */
gcc_assert (code == MULT_EXPR
|| code == TRUNC_DIV_EXPR
|| code == FLOOR_DIV_EXPR
@@ -1277,8 +1032,7 @@ extract_range_from_multiplicative_op_1 (value_range *vr,
|| code == ROUND_DIV_EXPR
|| code == RSHIFT_EXPR
|| code == LSHIFT_EXPR);
- gcc_assert (vr0->type == VR_RANGE
- && vr0->type == vr1->type);
+ gcc_assert (vr0->type == VR_RANGE && vr0->type == vr1->type);
tree type = TREE_TYPE (vr0->min);
wide_int res_lb, res_ub;
@@ -1286,65 +1040,19 @@ extract_range_from_multiplicative_op_1 (value_range *vr,
wide_int vr0_ub = wi::to_wide (vr0->max);
wide_int vr1_lb = wi::to_wide (vr1->min);
wide_int vr1_ub = wi::to_wide (vr1->max);
- bool overflow_undefined = TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (vr0->min));
-
- if (!wide_int_range_cross_product (res_lb, res_ub,
- code, TYPE_SIGN (type),
- vr0_lb, vr0_ub, vr1_lb, vr1_ub,
- overflow_undefined))
- {
- set_value_range_to_varying (vr);
- return;
- }
- set_value_range (vr, VR_RANGE,
- wide_int_to_tree (type, res_lb),
- wide_int_to_tree (type, res_ub), NULL);
-}
-
-/* For op & or | attempt to optimize:
-
- [LB, UB] op Z
- into:
- [LB op Z, UB op Z]
-
- if Z is a constant which (for op | its bitwise not) has n
- consecutive least significant bits cleared followed by m 1
- consecutive bits set immediately above it and either
- m + n == precision, or (x >> (m + n)) == (y >> (m + n)).
-
- The least significant n bits of all the values in the range are
- cleared or set, the m bits above it are preserved and any bits
- above these are required to be the same for all values in the
- range.
-
- Return TRUE if the min and max can simply be folded. */
-
-bool
-range_easy_mask_min_max (tree_code code,
- const wide_int &lb, const wide_int &ub,
- const wide_int &mask)
-
-{
- wide_int w = mask;
- int m = 0, n = 0;
- if (code == BIT_IOR_EXPR)
- w = ~w;
- if (wi::eq_p (w, 0))
- n = w.get_precision ();
+ bool overflow_undefined = TYPE_OVERFLOW_UNDEFINED (type);
+ bool overflow_wraps = TYPE_OVERFLOW_WRAPS (type);
+ unsigned prec = TYPE_PRECISION (type);
+
+ if (wide_int_range_multiplicative_op (res_lb, res_ub,
+ code, TYPE_SIGN (type), prec,
+ vr0_lb, vr0_ub, vr1_lb, vr1_ub,
+ overflow_undefined, overflow_wraps))
+ set_and_canonicalize_value_range (vr, VR_RANGE,
+ wide_int_to_tree (type, res_lb),
+ wide_int_to_tree (type, res_ub), NULL);
else
- {
- n = wi::ctz (w);
- w = ~(w | wi::mask (n, false, w.get_precision ()));
- if (wi::eq_p (w, 0))
- m = w.get_precision () - n;
- else
- m = wi::ctz (w) - n;
- }
- wide_int new_mask = wi::mask (m + n, true, w.get_precision ());
- if ((new_mask & lb) == (new_mask & ub))
- return true;
-
- return false;
+ set_value_range_to_varying (vr);
}
/* If BOUND will include a symbolic bound, adjust it accordingly,
@@ -1520,8 +1228,11 @@ set_value_range_with_overflow (value_range &vr,
void
extract_range_from_binary_expr_1 (value_range *vr,
enum tree_code code, tree expr_type,
- value_range *vr0_, value_range *vr1_)
+ const value_range *vr0_,
+ const value_range *vr1_)
{
+ signop sign = TYPE_SIGN (expr_type);
+ unsigned int prec = TYPE_PRECISION (expr_type);
value_range vr0 = *vr0_, vr1 = *vr1_;
value_range vrtem0 = VR_INITIALIZER, vrtem1 = VR_INITIALIZER;
enum value_range_type type;
@@ -1640,6 +1351,7 @@ extract_range_from_binary_expr_1 (value_range *vr,
&& code != PLUS_EXPR
&& code != MINUS_EXPR
&& code != RSHIFT_EXPR
+ && code != POINTER_PLUS_EXPR
&& (vr0.type == VR_VARYING
|| vr1.type == VR_VARYING
|| vr0.type != vr1.type
@@ -1659,7 +1371,7 @@ extract_range_from_binary_expr_1 (value_range *vr,
nullness, if both are non null, then the result is nonnull.
If both are null, then the result is null. Otherwise they
are varying. */
- if (range_is_nonnull (&vr0) && range_is_nonnull (&vr1))
+ if (!range_includes_zero_p (&vr0) && !range_includes_zero_p (&vr1))
set_value_range_to_nonnull (vr, expr_type);
else if (range_is_null (&vr0) && range_is_null (&vr1))
set_value_range_to_null (vr, expr_type);
@@ -1670,7 +1382,8 @@ extract_range_from_binary_expr_1 (value_range *vr,
{
/* For pointer types, we are really only interested in asserting
whether the expression evaluates to non-NULL. */
- if (range_is_nonnull (&vr0) || range_is_nonnull (&vr1))
+ if (!range_includes_zero_p (&vr0)
+ || !range_includes_zero_p (&vr1))
set_value_range_to_nonnull (vr, expr_type);
else if (range_is_null (&vr0) && range_is_null (&vr1))
set_value_range_to_null (vr, expr_type);
@@ -1681,7 +1394,7 @@ extract_range_from_binary_expr_1 (value_range *vr,
{
/* For pointer types, we are really only interested in asserting
whether the expression evaluates to non-NULL. */
- if (range_is_nonnull (&vr0) && range_is_nonnull (&vr1))
+ if (!range_includes_zero_p (&vr0) && !range_includes_zero_p (&vr1))
set_value_range_to_nonnull (vr, expr_type);
else if (range_is_null (&vr0) || range_is_null (&vr1))
set_value_range_to_null (vr, expr_type);
@@ -1698,6 +1411,22 @@ extract_range_from_binary_expr_1 (value_range *vr,
range and see what we end up with. */
if (code == PLUS_EXPR || code == MINUS_EXPR)
{
+ /* This will normalize things such that calculating
+ [0,0] - VR_VARYING is not dropped to varying, but is
+ calculated as [MIN+1, MAX]. */
+ if (vr0.type == VR_VARYING)
+ {
+ vr0.type = VR_RANGE;
+ vr0.min = vrp_val_min (expr_type);
+ vr0.max = vrp_val_max (expr_type);
+ }
+ if (vr1.type == VR_VARYING)
+ {
+ vr1.type = VR_RANGE;
+ vr1.min = vrp_val_min (expr_type);
+ vr1.max = vrp_val_max (expr_type);
+ }
+
const bool minus_p = (code == MINUS_EXPR);
tree min_op0 = vr0.min;
tree min_op1 = minus_p ? vr1.max : vr1.min;
@@ -1792,50 +1521,19 @@ extract_range_from_binary_expr_1 (value_range *vr,
else if (code == MIN_EXPR
|| code == MAX_EXPR)
{
- if (vr0.type == VR_RANGE
- && !symbolic_range_p (&vr0))
- {
- type = VR_RANGE;
- if (vr1.type == VR_RANGE
- && !symbolic_range_p (&vr1))
- {
- /* For operations that make the resulting range directly
- proportional to the original ranges, apply the operation to
- the same end of each range. */
- min = int_const_binop (code, vr0.min, vr1.min);
- max = int_const_binop (code, vr0.max, vr1.max);
- }
- else if (code == MIN_EXPR)
- {
- min = vrp_val_min (expr_type);
- max = vr0.max;
- }
- else if (code == MAX_EXPR)
- {
- min = vr0.min;
- max = vrp_val_max (expr_type);
- }
- }
- else if (vr1.type == VR_RANGE
- && !symbolic_range_p (&vr1))
- {
- type = VR_RANGE;
- if (code == MIN_EXPR)
- {
- min = vrp_val_min (expr_type);
- max = vr1.max;
- }
- else if (code == MAX_EXPR)
- {
- min = vr1.min;
- max = vrp_val_max (expr_type);
- }
- }
+ wide_int wmin, wmax;
+ wide_int vr0_min, vr0_max;
+ wide_int vr1_min, vr1_max;
+ extract_range_into_wide_ints (&vr0, sign, prec, vr0_min, vr0_max);
+ extract_range_into_wide_ints (&vr1, sign, prec, vr1_min, vr1_max);
+ if (wide_int_range_min_max (wmin, wmax, code, sign, prec,
+ vr0_min, vr0_max, vr1_min, vr1_max))
+ set_value_range (vr, VR_RANGE,
+ wide_int_to_tree (expr_type, wmin),
+ wide_int_to_tree (expr_type, wmax), NULL);
else
- {
- set_value_range_to_varying (vr);
- return;
- }
+ set_value_range_to_varying (vr);
+ return;
}
else if (code == MULT_EXPR)
{
@@ -1845,40 +1543,16 @@ extract_range_from_binary_expr_1 (value_range *vr,
set_value_range_to_varying (vr);
return;
}
- if (TYPE_OVERFLOW_WRAPS (expr_type))
- {
- signop sign = TYPE_SIGN (expr_type);
- unsigned int prec = TYPE_PRECISION (expr_type);
- wide_int res_lb, res_ub;
- if (!wide_int_range_mult_wrapping (res_lb, res_ub,
- sign, prec,
- wi::to_wide (vr0.min),
- wi::to_wide (vr0.max),
- wi::to_wide (vr1.min),
- wi::to_wide (vr1.max)))
- {
- set_value_range_to_varying (vr);
- return;
- }
- min = wide_int_to_tree (expr_type, res_lb);
- max = wide_int_to_tree (expr_type, res_ub);
- set_and_canonicalize_value_range (vr, VR_RANGE, min, max, NULL);
- return;
- }
- extract_range_from_multiplicative_op_1 (vr, code, &vr0, &vr1);
+ extract_range_from_multiplicative_op (vr, code, &vr0, &vr1);
return;
}
else if (code == RSHIFT_EXPR
|| code == LSHIFT_EXPR)
{
- /* If we have a RSHIFT_EXPR with any shift values outside [0..prec-1],
- then drop to VR_VARYING. Outside of this range we get undefined
- behavior from the shift operation. We cannot even trust
- SHIFT_COUNT_TRUNCATED at this stage, because that applies to rtl
- shifts, and the operation at the tree level may be widened. */
if (range_int_cst_p (&vr1)
- && compare_tree_int (vr1.min, 0) >= 0
- && compare_tree_int (vr1.max, TYPE_PRECISION (expr_type)) == -1)
+ && !wide_int_range_shift_undefined_p (prec,
+ wi::to_wide (vr1.min),
+ wi::to_wide (vr1.max)))
{
if (code == RSHIFT_EXPR)
{
@@ -1891,91 +1565,25 @@ extract_range_from_binary_expr_1 (value_range *vr,
vr0.min = vrp_val_min (expr_type);
vr0.max = vrp_val_max (expr_type);
}
- extract_range_from_multiplicative_op_1 (vr, code, &vr0, &vr1);
- return;
- }
- /* We can map lshifts by constants to MULT_EXPR handling. */
- else if (code == LSHIFT_EXPR
- && range_int_cst_singleton_p (&vr1))
- {
- bool saved_flag_wrapv;
- value_range vr1p = VR_INITIALIZER;
- vr1p.type = VR_RANGE;
- vr1p.min = (wide_int_to_tree
- (expr_type,
- wi::set_bit_in_zero (tree_to_shwi (vr1.min),
- TYPE_PRECISION (expr_type))));
- vr1p.max = vr1p.min;
- /* We have to use a wrapping multiply though as signed overflow
- on lshifts is implementation defined in C89. */
- saved_flag_wrapv = flag_wrapv;
- flag_wrapv = 1;
- extract_range_from_binary_expr_1 (vr, MULT_EXPR, expr_type,
- &vr0, &vr1p);
- flag_wrapv = saved_flag_wrapv;
+ extract_range_from_multiplicative_op (vr, code, &vr0, &vr1);
return;
}
else if (code == LSHIFT_EXPR
&& range_int_cst_p (&vr0))
{
- int prec = TYPE_PRECISION (expr_type);
- int overflow_pos = prec;
- int bound_shift;
- wide_int low_bound, high_bound;
- bool uns = TYPE_UNSIGNED (expr_type);
- bool in_bounds = false;
-
- if (!uns)
- overflow_pos -= 1;
-
- bound_shift = overflow_pos - tree_to_shwi (vr1.max);
- /* If bound_shift == HOST_BITS_PER_WIDE_INT, the llshift can
- overflow. However, for that to happen, vr1.max needs to be
- zero, which means vr1 is a singleton range of zero, which
- means it should be handled by the previous LSHIFT_EXPR
- if-clause. */
- wide_int bound = wi::set_bit_in_zero (bound_shift, prec);
- wide_int complement = ~(bound - 1);
-
- if (uns)
+ wide_int res_lb, res_ub;
+ if (wide_int_range_lshift (res_lb, res_ub, sign, prec,
+ wi::to_wide (vr0.min),
+ wi::to_wide (vr0.max),
+ wi::to_wide (vr1.min),
+ wi::to_wide (vr1.max),
+ TYPE_OVERFLOW_UNDEFINED (expr_type),
+ TYPE_OVERFLOW_WRAPS (expr_type)))
{
- low_bound = bound;
- high_bound = complement;
- if (wi::ltu_p (wi::to_wide (vr0.max), low_bound))
- {
- /* [5, 6] << [1, 2] == [10, 24]. */
- /* We're shifting out only zeroes, the value increases
- monotonically. */
- in_bounds = true;
- }
- else if (wi::ltu_p (high_bound, wi::to_wide (vr0.min)))
- {
- /* [0xffffff00, 0xffffffff] << [1, 2]
- == [0xfffffc00, 0xfffffffe]. */
- /* We're shifting out only ones, the value decreases
- monotonically. */
- in_bounds = true;
- }
- }
- else
- {
- /* [-1, 1] << [1, 2] == [-4, 4]. */
- low_bound = complement;
- high_bound = bound;
- if (wi::lts_p (wi::to_wide (vr0.max), high_bound)
- && wi::lts_p (low_bound, wi::to_wide (vr0.min)))
- {
- /* For non-negative numbers, we're shifting out only
- zeroes, the value increases monotonically.
- For negative numbers, we're shifting out only ones, the
- value decreases monotomically. */
- in_bounds = true;
- }
- }
-
- if (in_bounds)
- {
- extract_range_from_multiplicative_op_1 (vr, code, &vr0, &vr1);
+ min = wide_int_to_tree (expr_type, res_lb);
+ max = wide_int_to_tree (expr_type, res_ub);
+ set_and_canonicalize_value_range (vr, VR_RANGE,
+ min, max, NULL);
return;
}
}
@@ -1989,109 +1597,50 @@ extract_range_from_binary_expr_1 (value_range *vr,
|| code == EXACT_DIV_EXPR
|| code == ROUND_DIV_EXPR)
{
- if (vr0.type != VR_RANGE || symbolic_range_p (&vr0))
- {
- /* For division, if op1 has VR_RANGE but op0 does not, something
- can be deduced just from that range. Say [min, max] / [4, max]
- gives [min / 4, max / 4] range. */
- if (vr1.type == VR_RANGE
- && !symbolic_range_p (&vr1)
- && range_includes_zero_p (vr1.min, vr1.max) == 0)
- {
- vr0.type = type = VR_RANGE;
- vr0.min = vrp_val_min (expr_type);
- vr0.max = vrp_val_max (expr_type);
- }
- else
- {
- set_value_range_to_varying (vr);
- return;
- }
- }
+ wide_int dividend_min, dividend_max, divisor_min, divisor_max;
+ wide_int wmin, wmax, extra_min, extra_max;
+ bool extra_range_p;
- /* For divisions, if flag_non_call_exceptions is true, we must
- not eliminate a division by zero. */
- if (cfun->can_throw_non_call_exceptions
- && (vr1.type != VR_RANGE
- || range_includes_zero_p (vr1.min, vr1.max) != 0))
+ /* Special case explicit division by zero as undefined. */
+ if (range_is_null (&vr1))
{
- set_value_range_to_varying (vr);
+ set_value_range_to_undefined (vr);
return;
}
- /* For divisions, if op0 is VR_RANGE, we can deduce a range
- even if op1 is VR_VARYING, VR_ANTI_RANGE, symbolic or can
- include 0. */
- if (vr0.type == VR_RANGE
- && (vr1.type != VR_RANGE
- || range_includes_zero_p (vr1.min, vr1.max) != 0))
+ /* First, normalize ranges into constants we can handle. Note
+ that VR_ANTI_RANGE's of constants were already normalized
+ before arriving here.
+
+ NOTE: As a future improvement, we may be able to do better
+ with mixed symbolic (anti-)ranges like [0, A]. See note in
+ ranges_from_anti_range. */
+ extract_range_into_wide_ints (&vr0, sign, prec,
+ dividend_min, dividend_max);
+ extract_range_into_wide_ints (&vr1, sign, prec,
+ divisor_min, divisor_max);
+ if (!wide_int_range_div (wmin, wmax, code, sign, prec,
+ dividend_min, dividend_max,
+ divisor_min, divisor_max,
+ TYPE_OVERFLOW_UNDEFINED (expr_type),
+ TYPE_OVERFLOW_WRAPS (expr_type),
+ extra_range_p, extra_min, extra_max))
{
- tree zero = build_int_cst (TREE_TYPE (vr0.min), 0);
- int cmp;
-
- min = NULL_TREE;
- max = NULL_TREE;
- if (TYPE_UNSIGNED (expr_type)
- || value_range_nonnegative_p (&vr1))
- {
- /* For unsigned division or when divisor is known
- to be non-negative, the range has to cover
- all numbers from 0 to max for positive max
- and all numbers from min to 0 for negative min. */
- cmp = compare_values (vr0.max, zero);
- if (cmp == -1)
- {
- /* When vr0.max < 0, vr1.min != 0 and value
- ranges for dividend and divisor are available. */
- if (vr1.type == VR_RANGE
- && !symbolic_range_p (&vr0)
- && !symbolic_range_p (&vr1)
- && compare_values (vr1.min, zero) != 0)
- max = int_const_binop (code, vr0.max, vr1.min);
- else
- max = zero;
- }
- else if (cmp == 0 || cmp == 1)
- max = vr0.max;
- else
- type = VR_VARYING;
- cmp = compare_values (vr0.min, zero);
- if (cmp == 1)
- {
- /* For unsigned division when value ranges for dividend
- and divisor are available. */
- if (vr1.type == VR_RANGE
- && !symbolic_range_p (&vr0)
- && !symbolic_range_p (&vr1)
- && compare_values (vr1.max, zero) != 0)
- min = int_const_binop (code, vr0.min, vr1.max);
- else
- min = zero;
- }
- else if (cmp == 0 || cmp == -1)
- min = vr0.min;
- else
- type = VR_VARYING;
- }
- else
- {
- /* Otherwise the range is -max .. max or min .. -min
- depending on which bound is bigger in absolute value,
- as the division can change the sign. */
- abs_extent_range (vr, vr0.min, vr0.max);
- return;
- }
- if (type == VR_VARYING)
- {
- set_value_range_to_varying (vr);
- return;
- }
+ set_value_range_to_varying (vr);
+ return;
}
- else if (range_int_cst_p (&vr0) && range_int_cst_p (&vr1))
+ set_value_range (vr, VR_RANGE,
+ wide_int_to_tree (expr_type, wmin),
+ wide_int_to_tree (expr_type, wmax), NULL);
+ if (extra_range_p)
{
- extract_range_from_multiplicative_op_1 (vr, code, &vr0, &vr1);
- return;
+ value_range extra_range = VR_INITIALIZER;
+ set_value_range (&extra_range, VR_RANGE,
+ wide_int_to_tree (expr_type, extra_min),
+ wide_int_to_tree (expr_type, extra_max), NULL);
+ vrp_meet (vr, &extra_range);
}
+ return;
}
else if (code == TRUNC_MOD_EXPR)
{
@@ -2100,187 +1649,80 @@ extract_range_from_binary_expr_1 (value_range *vr,
set_value_range_to_undefined (vr);
return;
}
- /* ABS (A % B) < ABS (B) and either
- 0 <= A % B <= A or A <= A % B <= 0. */
- type = VR_RANGE;
- signop sgn = TYPE_SIGN (expr_type);
- unsigned int prec = TYPE_PRECISION (expr_type);
wide_int wmin, wmax, tmp;
- if (vr1.type == VR_RANGE && !symbolic_range_p (&vr1))
- {
- wmax = wi::to_wide (vr1.max) - 1;
- if (sgn == SIGNED)
- {
- tmp = -1 - wi::to_wide (vr1.min);
- wmax = wi::smax (wmax, tmp);
- }
- }
- else
- {
- wmax = wi::max_value (prec, sgn);
- /* X % INT_MIN may be INT_MAX. */
- if (sgn == UNSIGNED)
- wmax = wmax - 1;
- }
-
- if (sgn == UNSIGNED)
- wmin = wi::zero (prec);
- else
- {
- wmin = -wmax;
- if (vr0.type == VR_RANGE && TREE_CODE (vr0.min) == INTEGER_CST)
- {
- tmp = wi::to_wide (vr0.min);
- if (wi::gts_p (tmp, 0))
- tmp = wi::zero (prec);
- wmin = wi::smax (wmin, tmp);
- }
- }
-
- if (vr0.type == VR_RANGE && TREE_CODE (vr0.max) == INTEGER_CST)
- {
- tmp = wi::to_wide (vr0.max);
- if (sgn == SIGNED && wi::neg_p (tmp))
- tmp = wi::zero (prec);
- wmax = wi::min (wmax, tmp, sgn);
- }
-
+ wide_int vr0_min, vr0_max, vr1_min, vr1_max;
+ extract_range_into_wide_ints (&vr0, sign, prec, vr0_min, vr0_max);
+ extract_range_into_wide_ints (&vr1, sign, prec, vr1_min, vr1_max);
+ wide_int_range_trunc_mod (wmin, wmax, sign, prec,
+ vr0_min, vr0_max, vr1_min, vr1_max);
min = wide_int_to_tree (expr_type, wmin);
max = wide_int_to_tree (expr_type, wmax);
+ set_value_range (vr, VR_RANGE, min, max, NULL);
+ return;
}
else if (code == BIT_AND_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_EXPR)
{
- bool int_cst_range0, int_cst_range1;
wide_int may_be_nonzero0, may_be_nonzero1;
wide_int must_be_nonzero0, must_be_nonzero1;
-
- int_cst_range0 = zero_nonzero_bits_from_vr (expr_type, &vr0,
- &may_be_nonzero0,
- &must_be_nonzero0);
- int_cst_range1 = zero_nonzero_bits_from_vr (expr_type, &vr1,
- &may_be_nonzero1,
- &must_be_nonzero1);
-
- if (code == BIT_AND_EXPR || code == BIT_IOR_EXPR)
- {
- value_range *vr0p = NULL, *vr1p = NULL;
- if (range_int_cst_singleton_p (&vr1))
- {
- vr0p = &vr0;
- vr1p = &vr1;
- }
- else if (range_int_cst_singleton_p (&vr0))
- {
- vr0p = &vr1;
- vr1p = &vr0;
- }
- /* For op & or | attempt to optimize:
- [x, y] op z into [x op z, y op z]. */
- if (vr0p && range_int_cst_p (vr0p)
- && range_easy_mask_min_max (code, wi::to_wide (vr0p->min),
- wi::to_wide (vr0p->max),
- wi::to_wide (vr1p->min)))
- {
- min = int_const_binop (code, vr0p->min, vr1p->min);
- max = int_const_binop (code, vr0p->max, vr1p->min);
- }
- }
-
- type = VR_RANGE;
- if (min && max)
- /* Optimized above already. */;
- else if (code == BIT_AND_EXPR)
- {
- min = wide_int_to_tree (expr_type,
- must_be_nonzero0 & must_be_nonzero1);
- wide_int wmax = may_be_nonzero0 & may_be_nonzero1;
- /* If both input ranges contain only negative values we can
- truncate the result range maximum to the minimum of the
- input range maxima. */
- if (int_cst_range0 && int_cst_range1
- && tree_int_cst_sgn (vr0.max) < 0
- && tree_int_cst_sgn (vr1.max) < 0)
- {
- wmax = wi::min (wmax, wi::to_wide (vr0.max),
- TYPE_SIGN (expr_type));
- wmax = wi::min (wmax, wi::to_wide (vr1.max),
- TYPE_SIGN (expr_type));
- }
- /* If either input range contains only non-negative values
- we can truncate the result range maximum to the respective
- maximum of the input range. */
- if (int_cst_range0 && tree_int_cst_sgn (vr0.min) >= 0)
- wmax = wi::min (wmax, wi::to_wide (vr0.max),
- TYPE_SIGN (expr_type));
- if (int_cst_range1 && tree_int_cst_sgn (vr1.min) >= 0)
- wmax = wi::min (wmax, wi::to_wide (vr1.max),
- TYPE_SIGN (expr_type));
- max = wide_int_to_tree (expr_type, wmax);
- cmp = compare_values (min, max);
- /* PR68217: In case of signed & sign-bit-CST should
- result in [-INF, 0] instead of [-INF, INF]. */
- if (cmp == -2 || cmp == 1)
+ wide_int wmin, wmax;
+ wide_int vr0_min, vr0_max, vr1_min, vr1_max;
+ vrp_set_zero_nonzero_bits (expr_type, &vr0,
+ &may_be_nonzero0, &must_be_nonzero0);
+ vrp_set_zero_nonzero_bits (expr_type, &vr1,
+ &may_be_nonzero1, &must_be_nonzero1);
+ extract_range_into_wide_ints (&vr0, sign, prec, vr0_min, vr0_max);
+ extract_range_into_wide_ints (&vr1, sign, prec, vr1_min, vr1_max);
+ if (code == BIT_AND_EXPR)
+ {
+ if (wide_int_range_bit_and (wmin, wmax, sign, prec,
+ vr0_min, vr0_max,
+ vr1_min, vr1_max,
+ must_be_nonzero0,
+ may_be_nonzero0,
+ must_be_nonzero1,
+ may_be_nonzero1))
{
- wide_int sign_bit
- = wi::set_bit_in_zero (TYPE_PRECISION (expr_type) - 1,
- TYPE_PRECISION (expr_type));
- if (!TYPE_UNSIGNED (expr_type)
- && ((int_cst_range0
- && value_range_constant_singleton (&vr0)
- && !wi::cmps (wi::to_wide (vr0.min), sign_bit))
- || (int_cst_range1
- && value_range_constant_singleton (&vr1)
- && !wi::cmps (wi::to_wide (vr1.min), sign_bit))))
- {
- min = TYPE_MIN_VALUE (expr_type);
- max = build_int_cst (expr_type, 0);
- }
+ min = wide_int_to_tree (expr_type, wmin);
+ max = wide_int_to_tree (expr_type, wmax);
+ set_value_range (vr, VR_RANGE, min, max, NULL);
}
+ else
+ set_value_range_to_varying (vr);
+ return;
}
else if (code == BIT_IOR_EXPR)
{
- max = wide_int_to_tree (expr_type,
- may_be_nonzero0 | may_be_nonzero1);
- wide_int wmin = must_be_nonzero0 | must_be_nonzero1;
- /* If the input ranges contain only positive values we can
- truncate the minimum of the result range to the maximum
- of the input range minima. */
- if (int_cst_range0 && int_cst_range1
- && tree_int_cst_sgn (vr0.min) >= 0
- && tree_int_cst_sgn (vr1.min) >= 0)
+ if (wide_int_range_bit_ior (wmin, wmax, sign,
+ vr0_min, vr0_max,
+ vr1_min, vr1_max,
+ must_be_nonzero0,
+ may_be_nonzero0,
+ must_be_nonzero1,
+ may_be_nonzero1))
{
- wmin = wi::max (wmin, wi::to_wide (vr0.min),
- TYPE_SIGN (expr_type));
- wmin = wi::max (wmin, wi::to_wide (vr1.min),
- TYPE_SIGN (expr_type));
+ min = wide_int_to_tree (expr_type, wmin);
+ max = wide_int_to_tree (expr_type, wmax);
+ set_value_range (vr, VR_RANGE, min, max, NULL);
}
- /* If either input range contains only negative values
- we can truncate the minimum of the result range to the
- respective minimum range. */
- if (int_cst_range0 && tree_int_cst_sgn (vr0.max) < 0)
- wmin = wi::max (wmin, wi::to_wide (vr0.min),
- TYPE_SIGN (expr_type));
- if (int_cst_range1 && tree_int_cst_sgn (vr1.max) < 0)
- wmin = wi::max (wmin, wi::to_wide (vr1.min),
- TYPE_SIGN (expr_type));
- min = wide_int_to_tree (expr_type, wmin);
+ else
+ set_value_range_to_varying (vr);
+ return;
}
else if (code == BIT_XOR_EXPR)
{
- wide_int result_zero_bits = ((must_be_nonzero0 & must_be_nonzero1)
- | ~(may_be_nonzero0 | may_be_nonzero1));
- wide_int result_one_bits
- = (wi::bit_and_not (must_be_nonzero0, may_be_nonzero1)
- | wi::bit_and_not (must_be_nonzero1, may_be_nonzero0));
- max = wide_int_to_tree (expr_type, ~result_zero_bits);
- min = wide_int_to_tree (expr_type, result_one_bits);
- /* If the range has all positive or all negative values the
- result is better than VARYING. */
- if (tree_int_cst_sgn (min) < 0
- || tree_int_cst_sgn (max) >= 0)
- ;
+ if (wide_int_range_bit_xor (wmin, wmax, sign, prec,
+ must_be_nonzero0,
+ may_be_nonzero0,
+ must_be_nonzero1,
+ may_be_nonzero1))
+ {
+ min = wide_int_to_tree (expr_type, wmin);
+ max = wide_int_to_tree (expr_type, wmax);
+ set_value_range (vr, VR_RANGE, min, max, NULL);
+ }
else
- max = min = NULL_TREE;
+ set_value_range_to_varying (vr);
+ return;
}
}
else
@@ -2318,85 +1760,6 @@ extract_range_from_binary_expr_1 (value_range *vr,
set_value_range (vr, type, min, max, NULL);
}
-/* Calculates the absolute value of a range and puts the result in VR.
- VR0 is the input range. TYPE is the type of the resulting
- range. */
-
-static void
-extract_range_from_abs_expr (value_range &vr, tree type, value_range &vr0)
-{
- /* Pass through vr0 in the easy cases. */
- if (TYPE_UNSIGNED (type)
- || value_range_nonnegative_p (&vr0))
- {
- copy_value_range (&vr, &vr0);
- return;
- }
-
- /* For the remaining varying or symbolic ranges we can't do anything
- useful. */
- if (vr0.type == VR_VARYING
- || symbolic_range_p (&vr0))
- {
- set_value_range_to_varying (&vr);
- return;
- }
-
- /* -TYPE_MIN_VALUE = TYPE_MIN_VALUE with flag_wrapv so we can't get a
- useful range. */
- if (!TYPE_OVERFLOW_UNDEFINED (type)
- && ((vr0.type == VR_RANGE
- && vrp_val_is_min (vr0.min))
- || (vr0.type == VR_ANTI_RANGE
- && !vrp_val_is_min (vr0.min))))
- {
- set_value_range_to_varying (&vr);
- return;
- }
-
- /* ABS_EXPR may flip the range around, if the original range
- included negative values. */
- tree min, max;
- if (!vrp_val_is_min (vr0.min))
- min = fold_unary_to_constant (ABS_EXPR, type, vr0.min);
- else
- min = TYPE_MAX_VALUE (type);
-
- if (!vrp_val_is_min (vr0.max))
- max = fold_unary_to_constant (ABS_EXPR, type, vr0.max);
- else
- max = TYPE_MAX_VALUE (type);
-
- int cmp = compare_values (min, max);
- gcc_assert (vr0.type != VR_ANTI_RANGE);
-
- /* If the range contains zero then we know that the minimum value in the
- range will be zero. */
- if (range_includes_zero_p (vr0.min, vr0.max) == 1)
- {
- if (cmp == 1)
- max = min;
- min = build_int_cst (type, 0);
- }
- else
- {
- /* If the range was reversed, swap MIN and MAX. */
- if (cmp == 1)
- std::swap (min, max);
- }
-
- cmp = compare_values (min, max);
- if (cmp == -2 || cmp == 1)
- {
- /* If the new range has its limits swapped around (MIN > MAX),
- then the operation caused one of them to wrap around, mark
- the new range VARYING. */
- set_value_range_to_varying (&vr);
- }
- else
- set_value_range (&vr, vr0.type, min, max, NULL);
-}
-
/* Extract range information from a unary operation CODE based on
the range of its operand *VR0 with type OP0_TYPE with resulting type TYPE.
The resulting range is stored in *VR. */
@@ -2404,8 +1767,10 @@ extract_range_from_abs_expr (value_range &vr, tree type, value_range &vr0)
void
extract_range_from_unary_expr (value_range *vr,
enum tree_code code, tree type,
- value_range *vr0_, tree op0_type)
+ const value_range *vr0_, tree op0_type)
{
+ signop sign = TYPE_SIGN (type);
+ unsigned int prec = TYPE_PRECISION (type);
value_range vr0 = *vr0_, vrtem0 = VR_INITIALIZER, vrtem1 = VR_INITIALIZER;
/* VRP only operates on integral and pointer types. */
@@ -2477,7 +1842,7 @@ extract_range_from_unary_expr (value_range *vr,
determining if it evaluates to NULL [0, 0] or non-NULL (~[0, 0]). */
if (POINTER_TYPE_P (type))
{
- if (range_is_nonnull (&vr0))
+ if (!range_includes_zero_p (&vr0))
set_value_range_to_nonnull (vr, type);
else if (range_is_null (&vr0))
set_value_range_to_null (vr, type);
@@ -2486,48 +1851,57 @@ extract_range_from_unary_expr (value_range *vr,
return;
}
- /* If VR0 is varying and we increase the type precision, assume
- a full range for the following transformation. */
- if (vr0.type == VR_VARYING
- && INTEGRAL_TYPE_P (inner_type)
- && TYPE_PRECISION (inner_type) < TYPE_PRECISION (outer_type))
- {
- vr0.type = VR_RANGE;
- vr0.min = TYPE_MIN_VALUE (inner_type);
- vr0.max = TYPE_MAX_VALUE (inner_type);
- }
-
- /* If VR0 is a constant range or anti-range and the conversion is
- not truncating we can convert the min and max values and
- canonicalize the resulting range. Otherwise we can do the
- conversion if the size of the range is less than what the
- precision of the target type can represent and the range is
- not an anti-range. */
- if ((vr0.type == VR_RANGE
- || vr0.type == VR_ANTI_RANGE)
+ /* We normalize everything to a VR_RANGE, but for constant
+ anti-ranges we must handle them by leaving the final result
+ as an anti range. This allows us to convert things like
+ ~[0,5] seamlessly. */
+ value_range_type vr_type = VR_RANGE;
+ if (vr0.type == VR_ANTI_RANGE
&& TREE_CODE (vr0.min) == INTEGER_CST
- && TREE_CODE (vr0.max) == INTEGER_CST
- && (TYPE_PRECISION (outer_type) >= TYPE_PRECISION (inner_type)
- || (vr0.type == VR_RANGE
- && integer_zerop (int_const_binop (RSHIFT_EXPR,
- int_const_binop (MINUS_EXPR, vr0.max, vr0.min),
- size_int (TYPE_PRECISION (outer_type)))))))
- {
- tree new_min, new_max;
- new_min = force_fit_type (outer_type, wi::to_widest (vr0.min),
- 0, false);
- new_max = force_fit_type (outer_type, wi::to_widest (vr0.max),
- 0, false);
- set_and_canonicalize_value_range (vr, vr0.type,
- new_min, new_max, NULL);
- return;
+ && TREE_CODE (vr0.max) == INTEGER_CST)
+ vr_type = VR_ANTI_RANGE;
+
+ /* NOTES: Previously we were returning VARYING for all symbolics, but
+ we can do better by treating them as [-MIN, +MAX]. For
+ example, converting [SYM, SYM] from INT to LONG UNSIGNED,
+ we can return: ~[0x8000000, 0xffffffff7fffffff].
+
+ We were also failing to convert ~[0,0] from char* to unsigned,
+ instead choosing to return VR_VARYING. Now we return ~[0,0]. */
+ wide_int vr0_min, vr0_max, wmin, wmax;
+ signop inner_sign = TYPE_SIGN (inner_type);
+ signop outer_sign = TYPE_SIGN (outer_type);
+ unsigned inner_prec = TYPE_PRECISION (inner_type);
+ unsigned outer_prec = TYPE_PRECISION (outer_type);
+ extract_range_into_wide_ints (&vr0, inner_sign, inner_prec,
+ vr0_min, vr0_max);
+ if (wide_int_range_convert (wmin, wmax,
+ inner_sign, inner_prec,
+ outer_sign, outer_prec,
+ vr0_min, vr0_max))
+ {
+ tree min = wide_int_to_tree (outer_type, wmin);
+ tree max = wide_int_to_tree (outer_type, wmax);
+ set_and_canonicalize_value_range (vr, vr_type, min, max, NULL);
}
-
- set_value_range_to_varying (vr);
+ else
+ set_value_range_to_varying (vr);
return;
}
else if (code == ABS_EXPR)
- return extract_range_from_abs_expr (*vr, type, vr0);
+ {
+ wide_int wmin, wmax;
+ wide_int vr0_min, vr0_max;
+ extract_range_into_wide_ints (&vr0, sign, prec, vr0_min, vr0_max);
+ if (wide_int_range_abs (wmin, wmax, sign, prec, vr0_min, vr0_max,
+ TYPE_OVERFLOW_UNDEFINED (type)))
+ set_value_range (vr, VR_RANGE,
+ wide_int_to_tree (type, wmin),
+ wide_int_to_tree (type, wmax), NULL);
+ else
+ set_value_range_to_varying (vr);
+ return;
+ }
/* For unhandled operations fall back to varying. */
set_value_range_to_varying (vr);
@@ -2537,7 +1911,7 @@ extract_range_from_unary_expr (value_range *vr,
/* Debugging dumps. */
void dump_value_range (FILE *, const value_range *);
-void debug_value_range (value_range *);
+void debug_value_range (const value_range *);
void dump_all_value_ranges (FILE *);
void dump_vr_equiv (FILE *, bitmap);
void debug_vr_equiv (bitmap);
@@ -2602,12 +1976,18 @@ dump_value_range (FILE *file, const value_range *vr)
/* Dump value range VR to stderr. */
DEBUG_FUNCTION void
-debug_value_range (value_range *vr)
+debug_value_range (const value_range *vr)
{
dump_value_range (stderr, vr);
fprintf (stderr, "\n");
}
+void
+value_range::dump () const
+{
+ debug_value_range (this);
+}
+
/* Given a COND_EXPR COND of the form 'V OP W', and an SSA name V,
create a new SSA name N and return the assertion assignment
@@ -4043,7 +3423,7 @@ find_switch_asserts (basic_block bb, gswitch *last)
for (idx = 0; idx < n; ++idx)
{
ci[idx].expr = gimple_switch_label (last, idx);
- ci[idx].bb = label_to_block (CASE_LABEL (ci[idx].expr));
+ ci[idx].bb = label_to_block (cfun, CASE_LABEL (ci[idx].expr));
}
edge default_edge = find_edge (bb, ci[0].bb);
qsort (ci, n, sizeof (struct case_info), compare_case_labels);
@@ -4783,7 +4163,7 @@ void
vrp_prop::check_array_ref (location_t location, tree ref,
bool ignore_off_by_one)
{
- value_range *vr = NULL;
+ const value_range *vr = NULL;
tree low_sub, up_sub;
tree low_bound, up_bound, up_bound_p1;
@@ -4838,14 +4218,13 @@ vrp_prop::check_array_ref (location_t location, tree ref,
tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
+ bool warned = false;
+
/* Empty array. */
if (up_bound && tree_int_cst_equal (low_bound, up_bound_p1))
- {
- warning_at (location, OPT_Warray_bounds,
- "array subscript %E is above array bounds of %qT",
- low_bound, artype);
- TREE_NO_WARNING (ref) = 1;
- }
+ warned = warning_at (location, OPT_Warray_bounds,
+ "array subscript %E is above array bounds of %qT",
+ low_bound, artype);
if (TREE_CODE (low_sub) == SSA_NAME)
{
@@ -4866,12 +4245,10 @@ vrp_prop::check_array_ref (location_t location, tree ref,
: tree_int_cst_le (up_bound, up_sub))
&& TREE_CODE (low_sub) == INTEGER_CST
&& tree_int_cst_le (low_sub, low_bound))
- {
- warning_at (location, OPT_Warray_bounds,
- "array subscript [%E, %E] is outside array bounds of %qT",
- low_sub, up_sub, artype);
- TREE_NO_WARNING (ref) = 1;
- }
+ warned = warning_at (location, OPT_Warray_bounds,
+ "array subscript [%E, %E] is outside "
+ "array bounds of %qT",
+ low_sub, up_sub, artype);
}
else if (up_bound
&& TREE_CODE (up_sub) == INTEGER_CST
@@ -4885,10 +4262,9 @@ vrp_prop::check_array_ref (location_t location, tree ref,
dump_generic_expr (MSG_NOTE, TDF_SLIM, ref);
fprintf (dump_file, "\n");
}
- warning_at (location, OPT_Warray_bounds,
- "array subscript %E is above array bounds of %qT",
- up_sub, artype);
- TREE_NO_WARNING (ref) = 1;
+ warned = warning_at (location, OPT_Warray_bounds,
+ "array subscript %E is above array bounds of %qT",
+ up_sub, artype);
}
else if (TREE_CODE (low_sub) == INTEGER_CST
&& tree_int_cst_lt (low_sub, low_bound))
@@ -4899,9 +4275,18 @@ vrp_prop::check_array_ref (location_t location, tree ref,
dump_generic_expr (MSG_NOTE, TDF_SLIM, ref);
fprintf (dump_file, "\n");
}
- warning_at (location, OPT_Warray_bounds,
- "array subscript %E is below array bounds of %qT",
- low_sub, artype);
+ warned = warning_at (location, OPT_Warray_bounds,
+ "array subscript %E is below array bounds of %qT",
+ low_sub, artype);
+ }
+
+ if (warned)
+ {
+ ref = TREE_OPERAND (ref, 0);
+
+ if (DECL_P (ref))
+ inform (DECL_SOURCE_LOCATION (ref), "while referencing %qD", ref);
+
TREE_NO_WARNING (ref) = 1;
}
}
@@ -4916,7 +4301,8 @@ vrp_prop::check_array_ref (location_t location, tree ref,
the address of the just-past-the-end element of an array). */
void
-vrp_prop::check_mem_ref (location_t location, tree ref, bool ignore_off_by_one)
+vrp_prop::check_mem_ref (location_t location, tree ref,
+ bool ignore_off_by_one)
{
if (TREE_NO_WARNING (ref))
return;
@@ -4946,7 +4332,7 @@ vrp_prop::check_mem_ref (location_t location, tree ref, bool ignore_off_by_one)
/* The range of the byte offset into the reference. */
offset_int offrange[2] = { 0, 0 };
- value_range *vr = NULL;
+ const value_range *vr = NULL;
/* Determine the offsets and increment OFFRANGE for the bounds of each.
The loop computes the the range of the final offset for expressions
@@ -5048,9 +4434,13 @@ vrp_prop::check_mem_ref (location_t location, tree ref, bool ignore_off_by_one)
a reference/subscript via a pointer to an object that is not
an element of an array. References to members of structs and
unions are excluded because MEM_REF doesn't make it possible
- to identify the member where the reference originated. */
+ to identify the member where the reference originated.
+ Incomplete types are excluded as well because their size is
+ not known. */
tree reftype = TREE_TYPE (arg);
if (POINTER_TYPE_P (reftype)
+ || !COMPLETE_TYPE_P (reftype)
+ || TREE_CODE (TYPE_SIZE_UNIT (reftype)) != INTEGER_CST
|| RECORD_OR_UNION_TYPE_P (reftype))
return;
@@ -5134,16 +4524,21 @@ vrp_prop::check_mem_ref (location_t location, tree ref, bool ignore_off_by_one)
offrange[1] = offrange[1] / eltsize;
}
+ bool warned;
if (offrange[0] == offrange[1])
- warning_at (location, OPT_Warray_bounds,
- "array subscript %wi is outside array bounds "
- "of %qT",
- offrange[0].to_shwi (), reftype);
+ warned = warning_at (location, OPT_Warray_bounds,
+ "array subscript %wi is outside array bounds "
+ "of %qT",
+ offrange[0].to_shwi (), reftype);
else
- warning_at (location, OPT_Warray_bounds,
- "array subscript [%wi, %wi] is outside array bounds "
- "of %qT",
- offrange[0].to_shwi (), offrange[1].to_shwi (), reftype);
+ warned = warning_at (location, OPT_Warray_bounds,
+ "array subscript [%wi, %wi] is outside "
+ "array bounds of %qT",
+ offrange[0].to_shwi (),
+ offrange[1].to_shwi (), reftype);
+ if (warned && DECL_P (arg))
+ inform (DECL_SOURCE_LOCATION (arg), "while referencing %qD", arg);
+
TREE_NO_WARNING (ref) = 1;
return;
}
@@ -5183,60 +4578,69 @@ vrp_prop::search_for_addr_array (tree t, location_t location)
}
while (handled_component_p (t) || TREE_CODE (t) == MEM_REF);
- if (TREE_CODE (t) == MEM_REF
- && TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
- && !TREE_NO_WARNING (t))
- {
- tree tem = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
- tree low_bound, up_bound, el_sz;
- offset_int idx;
- if (TREE_CODE (TREE_TYPE (tem)) != ARRAY_TYPE
- || TREE_CODE (TREE_TYPE (TREE_TYPE (tem))) == ARRAY_TYPE
- || !TYPE_DOMAIN (TREE_TYPE (tem)))
- return;
+ if (TREE_CODE (t) != MEM_REF
+ || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR
+ || TREE_NO_WARNING (t))
+ return;
- low_bound = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (tem)));
- up_bound = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tem)));
- el_sz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (tem)));
- if (!low_bound
- || TREE_CODE (low_bound) != INTEGER_CST
- || !up_bound
- || TREE_CODE (up_bound) != INTEGER_CST
- || !el_sz
- || TREE_CODE (el_sz) != INTEGER_CST)
- return;
+ tree tem = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
+ tree low_bound, up_bound, el_sz;
+ if (TREE_CODE (TREE_TYPE (tem)) != ARRAY_TYPE
+ || TREE_CODE (TREE_TYPE (TREE_TYPE (tem))) == ARRAY_TYPE
+ || !TYPE_DOMAIN (TREE_TYPE (tem)))
+ return;
- if (!mem_ref_offset (t).is_constant (&idx))
- return;
+ low_bound = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (tem)));
+ up_bound = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tem)));
+ el_sz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (tem)));
+ if (!low_bound
+ || TREE_CODE (low_bound) != INTEGER_CST
+ || !up_bound
+ || TREE_CODE (up_bound) != INTEGER_CST
+ || !el_sz
+ || TREE_CODE (el_sz) != INTEGER_CST)
+ return;
+
+ offset_int idx;
+ if (!mem_ref_offset (t).is_constant (&idx))
+ return;
- idx = wi::sdiv_trunc (idx, wi::to_offset (el_sz));
- if (idx < 0)
+ bool warned = false;
+ idx = wi::sdiv_trunc (idx, wi::to_offset (el_sz));
+ if (idx < 0)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Array bound warning for ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
- fprintf (dump_file, "\n");
- }
- warning_at (location, OPT_Warray_bounds,
- "array subscript %wi is below array bounds of %qT",
- idx.to_shwi (), TREE_TYPE (tem));
- TREE_NO_WARNING (t) = 1;
+ fprintf (dump_file, "Array bound warning for ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
+ fprintf (dump_file, "\n");
}
- else if (idx > (wi::to_offset (up_bound)
- - wi::to_offset (low_bound) + 1))
+ warned = warning_at (location, OPT_Warray_bounds,
+ "array subscript %wi is below "
+ "array bounds of %qT",
+ idx.to_shwi (), TREE_TYPE (tem));
+ }
+ else if (idx > (wi::to_offset (up_bound)
+ - wi::to_offset (low_bound) + 1))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Array bound warning for ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
- fprintf (dump_file, "\n");
- }
- warning_at (location, OPT_Warray_bounds,
- "array subscript %wu is above array bounds of %qT",
- idx.to_uhwi (), TREE_TYPE (tem));
- TREE_NO_WARNING (t) = 1;
+ fprintf (dump_file, "Array bound warning for ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
+ fprintf (dump_file, "\n");
}
+ warned = warning_at (location, OPT_Warray_bounds,
+ "array subscript %wu is above "
+ "array bounds of %qT",
+ idx.to_uhwi (), TREE_TYPE (tem));
+ }
+
+ if (warned)
+ {
+ if (DECL_P (t))
+ inform (DECL_SOURCE_LOCATION (t), "while referencing %qD", t);
+
+ TREE_NO_WARNING (t) = 1;
}
}
@@ -5818,7 +5222,7 @@ vrp_prop::visit_stmt (gimple *stmt, edge *taken_edge_p, tree *output_p)
return SSA_PROP_VARYING. */
value_range new_vr = VR_INITIALIZER;
extract_range_basic (&new_vr, use_stmt);
- value_range *old_vr = get_value_range (use_lhs);
+ const value_range *old_vr = get_value_range (use_lhs);
if (old_vr->type != new_vr.type
|| !vrp_operand_equal_p (old_vr->min, new_vr.min)
|| !vrp_operand_equal_p (old_vr->max, new_vr.max)
@@ -6446,7 +5850,7 @@ intersect_ranges (enum value_range_type *vr0type,
in *VR0. This may not be the smallest possible such range. */
static void
-vrp_intersect_ranges_1 (value_range *vr0, value_range *vr1)
+vrp_intersect_ranges_1 (value_range *vr0, const value_range *vr1)
{
value_range saved;
@@ -6503,7 +5907,7 @@ vrp_intersect_ranges_1 (value_range *vr0, value_range *vr1)
}
void
-vrp_intersect_ranges (value_range *vr0, value_range *vr1)
+vrp_intersect_ranges (value_range *vr0, const value_range *vr1)
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -6562,17 +5966,9 @@ vrp_meet_1 (value_range *vr0, const value_range *vr1)
{
/* Failed to find an efficient meet. Before giving up and setting
the result to VARYING, see if we can at least derive a useful
- anti-range. FIXME, all this nonsense about distinguishing
- anti-ranges from ranges is necessary because of the odd
- semantics of range_includes_zero_p and friends. */
- if (((saved.type == VR_RANGE
- && range_includes_zero_p (saved.min, saved.max) == 0)
- || (saved.type == VR_ANTI_RANGE
- && range_includes_zero_p (saved.min, saved.max) == 1))
- && ((vr1->type == VR_RANGE
- && range_includes_zero_p (vr1->min, vr1->max) == 0)
- || (vr1->type == VR_ANTI_RANGE
- && range_includes_zero_p (vr1->min, vr1->max) == 1)))
+ anti-range. */
+ if (range_includes_zero_p (&saved) == 0
+ && range_includes_zero_p (vr1) == 0)
{
set_value_range_to_nonnull (vr0, TREE_TYPE (saved.min));
@@ -6824,7 +6220,7 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
op = lhs_of_dominating_assert (op, bb, stmt);
- value_range *vr = vr_values->get_value_range (op);
+ const value_range *vr = vr_values->get_value_range (op);
if ((vr->type != VR_RANGE && vr->type != VR_ANTI_RANGE)
|| symbolic_range_p (vr))
return NULL_TREE;
@@ -7004,9 +6400,6 @@ vrp_dom_walker::after_dom_children (basic_block bb)
static void
identify_jump_threads (class vr_values *vr_values)
{
- int i;
- edge e;
-
/* Ugh. When substituting values earlier in this pass we can
wipe the dominance information. So rebuild the dominator
information as we need it within the jump threading code. */
@@ -7019,11 +6412,6 @@ identify_jump_threads (class vr_values *vr_values)
recompute it. */
mark_dfs_back_edges ();
- /* Do not thread across edges we are about to remove. Just marking
- them as EDGE_IGNORE will do. */
- FOR_EACH_VEC_ELT (to_remove_edges, i, e)
- e->flags |= EDGE_IGNORE;
-
/* Allocate our unwinder stack to unwind any temporary equivalences
that might be recorded. */
const_and_copies *equiv_stack = new const_and_copies ();
@@ -7037,10 +6425,6 @@ identify_jump_threads (class vr_values *vr_values)
walker.vr_values = vr_values;
walker.walk (cfun->cfg->x_entry_block_ptr);
- /* Clear EDGE_IGNORE. */
- FOR_EACH_VEC_ELT (to_remove_edges, i, e)
- e->flags &= ~EDGE_IGNORE;
-
/* We do not actually update the CFG or SSA graphs at this point as
ASSERT_EXPRs are still in the IL and cfg cleanup code does not yet
handle ASSERT_EXPRs gracefully. */
@@ -7073,7 +6457,7 @@ vrp_prop::vrp_finalize (bool warn_array_bounds_p)
if (!name)
continue;
- value_range *vr = get_value_range (name);
+ const value_range *vr = get_value_range (name);
if (!name
|| (vr->type == VR_VARYING)
|| (vr->type == VR_UNDEFINED)
@@ -7082,10 +6466,7 @@ vrp_prop::vrp_finalize (bool warn_array_bounds_p)
continue;
if (POINTER_TYPE_P (TREE_TYPE (name))
- && ((vr->type == VR_RANGE
- && range_includes_zero_p (vr->min, vr->max) == 0)
- || (vr->type == VR_ANTI_RANGE
- && range_includes_zero_p (vr->min, vr->max) == 1)))
+ && range_includes_zero_p (vr) == 0)
set_ptr_nonnull (name);
else if (!POINTER_TYPE_P (TREE_TYPE (name)))
set_range_info (name, vr->type,
@@ -7160,9 +6541,6 @@ vrp_prop::vrp_finalize (bool warn_array_bounds_p)
static unsigned int
execute_vrp (bool warn_array_bounds_p)
{
- int i;
- edge e;
- switch_update *su;
loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
@@ -7173,8 +6551,6 @@ execute_vrp (bool warn_array_bounds_p)
EDGE_DFS_BACK. */
insert_range_assertions ();
- to_remove_edges.create (10);
- to_update_switch_stmts.create (5);
threadedge_initialize_values ();
/* For visiting PHI nodes we need EDGE_DFS_BACK computed. */
@@ -7226,35 +6602,7 @@ execute_vrp (bool warn_array_bounds_p)
processing by the pass manager. */
thread_through_all_blocks (false);
- /* Remove dead edges from SWITCH_EXPR optimization. This leaves the
- CFG in a broken state and requires a cfg_cleanup run. */
- FOR_EACH_VEC_ELT (to_remove_edges, i, e)
- remove_edge (e);
- /* Update SWITCH_EXPR case label vector. */
- FOR_EACH_VEC_ELT (to_update_switch_stmts, i, su)
- {
- size_t j;
- size_t n = TREE_VEC_LENGTH (su->vec);
- tree label;
- gimple_switch_set_num_labels (su->stmt, n);
- for (j = 0; j < n; j++)
- gimple_switch_set_label (su->stmt, j, TREE_VEC_ELT (su->vec, j));
- /* As we may have replaced the default label with a regular one
- make sure to make it a real default label again. This ensures
- optimal expansion. */
- label = gimple_switch_label (su->stmt, 0);
- CASE_LOW (label) = NULL_TREE;
- CASE_HIGH (label) = NULL_TREE;
- }
-
- if (to_remove_edges.length () > 0)
- {
- free_dominance_info (CDI_DOMINATORS);
- loops_state_set (LOOPS_NEED_FIXUP);
- }
-
- to_remove_edges.release ();
- to_update_switch_stmts.release ();
+ vrp_prop.vr_values.cleanup_edges_and_switches ();
threadedge_finalize_values ();
scev_finalize ();
diff --git a/gcc/tree-vrp.h b/gcc/tree-vrp.h
index daf12ce..655cf05 100644
--- a/gcc/tree-vrp.h
+++ b/gcc/tree-vrp.h
@@ -49,15 +49,18 @@ struct GTY((for_user)) value_range
/* Set of SSA names whose value ranges are equivalent to this one.
This set is only valid when TYPE is VR_RANGE or VR_ANTI_RANGE. */
bitmap equiv;
+
+ /* Dump value range to stderr. */
+ void dump () const;
};
-extern void vrp_intersect_ranges (value_range *vr0, value_range *vr1);
+extern void vrp_intersect_ranges (value_range *vr0, const value_range *vr1);
extern void vrp_meet (value_range *vr0, const value_range *vr1);
extern void dump_value_range (FILE *, const value_range *);
extern void extract_range_from_unary_expr (value_range *vr,
enum tree_code code,
tree type,
- value_range *vr0_,
+ const value_range *vr0_,
tree op0_type);
extern bool vrp_operand_equal_p (const_tree, const_tree);
@@ -83,7 +86,7 @@ extern void register_edge_assert_for (tree, edge, enum tree_code,
tree, tree, vec<assert_info> &);
extern bool stmt_interesting_for_vrp (gimple *);
extern void set_value_range_to_varying (value_range *);
-extern int range_includes_zero_p (tree, tree);
+extern bool range_includes_zero_p (const value_range *);
extern bool infer_value_range (gimple *, tree, tree_code *, tree *);
extern void set_value_range_to_nonnull (value_range *, tree);
@@ -93,59 +96,30 @@ extern void set_and_canonicalize_value_range (value_range *,
enum value_range_type,
tree, tree, bitmap);
extern bool vrp_bitmap_equal_p (const_bitmap, const_bitmap);
-extern bool range_is_nonnull (value_range *);
-extern tree value_range_constant_singleton (value_range *);
-extern bool symbolic_range_p (value_range *);
+extern tree value_range_constant_singleton (const value_range *);
+extern bool symbolic_range_p (const value_range *);
extern int compare_values (tree, tree);
extern int compare_values_warnv (tree, tree, bool *);
extern bool vrp_val_is_min (const_tree);
extern bool vrp_val_is_max (const_tree);
-extern void copy_value_range (value_range *, value_range *);
+extern void copy_value_range (value_range *, const value_range *);
extern void set_value_range_to_value (value_range *, tree, bitmap);
-extern bool wide_int_range_cross_product (wide_int &res_lb, wide_int &res_ub,
- enum tree_code code, signop sign,
- const wide_int &, const wide_int &,
- const wide_int &, const wide_int &,
- bool overflow_undefined);
-extern bool wide_int_range_mult_wrapping (wide_int &res_lb,
- wide_int &res_ub,
- signop sign,
- unsigned prec,
- const wide_int &min0_,
- const wide_int &max0_,
- const wide_int &min1_,
- const wide_int &max1_);
extern void extract_range_from_binary_expr_1 (value_range *, enum tree_code,
- tree, value_range *,
- value_range *);
+ tree, const value_range *,
+ const value_range *);
extern tree vrp_val_min (const_tree);
extern tree vrp_val_max (const_tree);
extern void set_value_range_to_null (value_range *, tree);
-extern bool range_int_cst_p (value_range *);
+extern bool range_int_cst_p (const value_range *);
extern int operand_less_p (tree, tree);
extern bool find_case_label_range (gswitch *, tree, tree, size_t *, size_t *);
extern bool find_case_label_index (gswitch *, size_t, tree, size_t *);
-extern void zero_nonzero_bits_from_bounds (signop, const wide_int&,
- const wide_int&, wide_int *,
- wide_int *);
-extern bool zero_nonzero_bits_from_vr (const tree, value_range *,
+extern bool vrp_set_zero_nonzero_bits (const tree, const value_range *,
wide_int *, wide_int *);
-extern bool range_easy_mask_min_max (tree_code,
- const wide_int &lb, const wide_int &ub,
- const wide_int &mask);
extern bool overflow_comparison_p (tree_code, tree, tree, bool, tree *);
-extern bool range_int_cst_singleton_p (value_range *);
+extern bool range_int_cst_singleton_p (const value_range *);
extern int value_inside_range (tree, tree, tree);
extern tree get_single_symbol (tree, bool *, tree *);
extern void maybe_set_nonzero_bits (edge, tree);
extern value_range_type determine_value_range (tree, wide_int *, wide_int *);
-
-struct switch_update {
- gswitch *stmt;
- tree vec;
-};
-
-extern vec<edge> to_remove_edges;
-extern vec<switch_update> to_update_switch_stmts;
-
#endif /* GCC_TREE_VRP_H */
diff --git a/gcc/tree.c b/gcc/tree.c
index 28952e5..c3ac8f3 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -5240,7 +5240,7 @@ need_assembler_name_p (tree decl)
{
/* Do not set assembler name on builtins. Allow RTL expansion to
decide whether to expand inline or via a regular call. */
- if (DECL_BUILT_IN (decl)
+ if (fndecl_built_in_p (decl)
&& DECL_BUILT_IN_CLASS (decl) != BUILT_IN_FRONTEND)
return false;
@@ -5339,12 +5339,7 @@ free_lang_data_in_decl (tree decl)
(DECL_CONTEXT (DECL_ABSTRACT_ORIGIN (decl))))
DECL_ABSTRACT_ORIGIN (decl) = NULL_TREE;
- /* Sometimes the C++ frontend doesn't manage to transform a temporary
- DECL_VINDEX referring to itself into a vtable slot number as it
- should. Happens with functions that are copied and then forgotten
- about. Just clear it, it won't matter anymore. */
- if (DECL_VINDEX (decl) && !tree_fits_shwi_p (DECL_VINDEX (decl)))
- DECL_VINDEX (decl) = NULL_TREE;
+ DECL_VINDEX (decl) = NULL_TREE;
}
else if (VAR_P (decl))
{
@@ -5371,15 +5366,37 @@ free_lang_data_in_decl (tree decl)
nodes and thus we can't use TREE_CHAIN in multiple lists. */
tree *nextp = &BLOCK_VARS (DECL_INITIAL (decl));
while (*nextp)
- {
- tree var = *nextp;
- if (TREE_CODE (var) == FUNCTION_DECL
- && DECL_BUILT_IN (var))
+ {
+ tree var = *nextp;
+ if (fndecl_built_in_p (var))
*nextp = TREE_CHAIN (var);
else
nextp = &TREE_CHAIN (var);
}
}
+ /* We need to keep field decls associated with their trees. Otherwise tree
+ merging may merge some fileds and keep others disjoint wich in turn will
+ not do well with TREE_CHAIN pointers linking them.
+
+ Also do not drop containing types for virtual methods and tables because
+ these are needed by devirtualization. */
+ if (TREE_CODE (decl) != FIELD_DECL
+ && ((TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
+ || !DECL_VIRTUAL_P (decl)))
+ {
+ tree ctx = DECL_CONTEXT (decl);
+ /* Variably modified types are needed for tree_is_indexable to decide
+ whether the type needs to go to local or global section.
+ This code is semi-broken but for now it is easiest to keep contexts
+ as expected. */
+ if (ctx && TYPE_P (ctx)
+ && !variably_modified_type_p (ctx, NULL_TREE))
+ {
+ while (ctx && TYPE_P (ctx))
+ ctx = TYPE_CONTEXT (ctx);
+ DECL_CONTEXT (decl) = ctx;
+ }
+ }
}
@@ -5502,9 +5519,14 @@ find_decls_types_r (tree *tp, int *ws, void *data)
fld_worklist_push (TYPE_POINTER_TO (t), fld);
fld_worklist_push (TYPE_REFERENCE_TO (t), fld);
fld_worklist_push (TYPE_NAME (t), fld);
- /* Do not walk TYPE_NEXT_PTR_TO or TYPE_NEXT_REF_TO. We do not stream
- them and thus do not and want not to reach unused pointer types
- this way. */
+ /* While we do not stream TYPE_POINTER_TO and TYPE_REFERENCE_TO
+ lists, we may look types up in these lists and use them while
+ optimizing the function body. Thus we need to free lang data
+ in them. */
+ if (TREE_CODE (t) == POINTER_TYPE)
+ fld_worklist_push (TYPE_NEXT_PTR_TO (t), fld);
+ if (TREE_CODE (t) == REFERENCE_TYPE)
+ fld_worklist_push (TYPE_NEXT_REF_TO (t), fld);
if (!POINTER_TYPE_P (t))
fld_worklist_push (TYPE_MIN_VALUE_RAW (t), fld);
/* TYPE_MAX_VALUE_RAW is TYPE_BINFO for record types. */
@@ -5542,11 +5564,7 @@ find_decls_types_r (tree *tp, int *ws, void *data)
tem = TYPE_FIELDS (t);
while (tem)
{
- if (TREE_CODE (tem) == FIELD_DECL
- || (TREE_CODE (tem) == TYPE_DECL
- && !DECL_IGNORED_P (tem)
- && debug_info_level > DINFO_LEVEL_TERSE
- && !is_redundant_typedef (tem)))
+ if (TREE_CODE (tem) == FIELD_DECL)
fld_worklist_push (tem, fld);
tem = TREE_CHAIN (tem);
}
@@ -8971,7 +8989,7 @@ decl_function_context (const_tree decl)
C++ should really be fixed to use DECL_CONTEXT for the real context,
and use something else for the "virtual context". */
- else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VINDEX (decl))
+ else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl))
context
= TYPE_MAIN_VARIANT
(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));
@@ -9081,7 +9099,7 @@ get_call_combined_fn (const_tree call)
return as_combined_fn (CALL_EXPR_IFN (call));
tree fndecl = get_callee_fndecl (call);
- if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+ if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
return as_combined_fn (DECL_FUNCTION_CODE (fndecl));
return CFN_LAST;
@@ -9802,8 +9820,7 @@ build_common_tree_nodes (bool signed_char)
int_n_trees[i].signed_type = make_signed_type (int_n_data[i].bitsize);
int_n_trees[i].unsigned_type = make_unsigned_type (int_n_data[i].bitsize);
- if (int_n_data[i].bitsize > LONG_LONG_TYPE_SIZE
- && int_n_enabled_p[i])
+ if (int_n_enabled_p[i])
{
integer_types[itk_intN_0 + i * 2] = int_n_trees[i].signed_type;
integer_types[itk_unsigned_intN_0 + i * 2] = int_n_trees[i].unsigned_type;
@@ -12614,6 +12631,7 @@ warn_deprecated_use (tree node, tree attr)
bool w = false;
if (DECL_P (node))
{
+ auto_diagnostic_group d;
if (msg)
w = warning (OPT_Wdeprecated_declarations,
"%qD is deprecated: %s", node, (const char *) msg);
@@ -12637,6 +12655,7 @@ warn_deprecated_use (tree node, tree attr)
what = DECL_NAME (TYPE_NAME (node));
}
+ auto_diagnostic_group d;
if (what)
{
if (msg)
diff --git a/gcc/tree.h b/gcc/tree.h
index 7bed035..4f415b7a 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1743,6 +1743,13 @@ extern tree maybe_wrap_with_location (tree, location_t);
#define SSA_NAME_IS_DEFAULT_DEF(NODE) \
SSA_NAME_CHECK (NODE)->base.default_def_flag
+/* Nonzero if this SSA_NAME is known to point to memory that may not
+ be written to. This is set for default defs of function parameters
+ that have a corresponding r or R specification in the functions
+ fn spec attribute. This is used by alias analysis. */
+#define SSA_NAME_POINTS_TO_READONLY_MEMORY(NODE) \
+ SSA_NAME_CHECK (NODE)->base.deprecated_flag
+
/* Attributes for SSA_NAMEs for pointer-type variables. */
#define SSA_NAME_PTR_INFO(N) \
SSA_NAME_CHECK (N)->ssa_name.info.ptr_info
@@ -2995,14 +3002,6 @@ extern vec<tree, va_gc> **decl_debug_args_insert (tree);
#define DECL_STRUCT_FUNCTION(NODE) \
(FUNCTION_DECL_CHECK (NODE)->function_decl.f)
-/* In a FUNCTION_DECL, nonzero means a built in function of a
- standard library or more generally a built in function that is
- recognized by optimizers and expanders.
-
- Note that it is different from the DECL_IS_BUILTIN accessor. For
- instance, user declared prototypes of C library functions are not
- DECL_IS_BUILTIN but may be DECL_BUILT_IN. */
-#define DECL_BUILT_IN(NODE) (DECL_BUILT_IN_CLASS (NODE) != NOT_BUILT_IN)
/* For a builtin function, identify which part of the compiler defined it. */
#define DECL_BUILT_IN_CLASS(NODE) \
@@ -5799,7 +5798,6 @@ extern void gt_pch_nx (tree &);
extern void gt_pch_nx (tree &, gt_pointer_operator, void *);
extern bool nonnull_arg_p (const_tree);
-extern bool is_redundant_typedef (const_tree);
extern bool default_is_empty_record (const_tree);
extern HOST_WIDE_INT arg_int_size_in_bytes (const_tree);
extern tree arg_size_in_bytes (const_tree);
@@ -5843,4 +5841,44 @@ type_has_mode_precision_p (const_tree t)
return known_eq (TYPE_PRECISION (t), GET_MODE_PRECISION (TYPE_MODE (t)));
}
+/* Return true if a FUNCTION_DECL NODE is a GCC built-in function.
+
+ Note that it is different from the DECL_IS_BUILTIN accessor. For
+ instance, user declared prototypes of C library functions are not
+ DECL_IS_BUILTIN but may be DECL_BUILT_IN. */
+
+inline bool
+fndecl_built_in_p (const_tree node)
+{
+ return (DECL_BUILT_IN_CLASS (node) != NOT_BUILT_IN);
+}
+
+/* Return true if a FUNCTION_DECL NODE is a GCC built-in function
+ of class KLASS. */
+
+inline bool
+fndecl_built_in_p (const_tree node, built_in_class klass)
+{
+ return (fndecl_built_in_p (node) && DECL_BUILT_IN_CLASS (node) == klass);
+}
+
+/* Return true if a FUNCTION_DECL NODE is a GCC built-in function
+ of class KLASS with name equal to NAME. */
+
+inline bool
+fndecl_built_in_p (const_tree node, int name, built_in_class klass)
+{
+ return (fndecl_built_in_p (node, klass) && DECL_FUNCTION_CODE (node) == name);
+}
+
+/* Return true if a FUNCTION_DECL NODE is a GCC built-in function
+ of BUILT_IN_NORMAL class with name equal to NAME. */
+
+inline bool
+fndecl_built_in_p (const_tree node, built_in_function name)
+{
+ return (fndecl_built_in_p (node, BUILT_IN_NORMAL)
+ && DECL_FUNCTION_CODE (node) == name);
+}
+
#endif /* GCC_TREE_H */
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index 722f570..9bbcecc 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -663,7 +663,7 @@ bool
is_ubsan_builtin_p (tree t)
{
return TREE_CODE (t) == FUNCTION_DECL
- && DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
+ && fndecl_built_in_p (t, BUILT_IN_NORMAL)
&& strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
"__builtin___ubsan_", 18) == 0;
}
diff --git a/gcc/value-prof.c b/gcc/value-prof.c
index 77d4849..29489e0 100644
--- a/gcc/value-prof.c
+++ b/gcc/value-prof.c
@@ -821,12 +821,9 @@ gimple_divmod_fixed_value_transform (gimple_stmt_iterator *si)
if (dump_file)
{
- fprintf (dump_file, "Div/mod by constant ");
- print_generic_expr (dump_file, value, TDF_SLIM);
- fprintf (dump_file, "=");
+ fprintf (dump_file, "Transformation done: div/mod by constant ");
print_generic_expr (dump_file, tree_val, TDF_SLIM);
- fprintf (dump_file, " transformation on insn ");
- print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
+ fprintf (dump_file, "\n");
}
gimple_assign_set_rhs_from_tree (si, result);
@@ -956,18 +953,15 @@ gimple_mod_pow2_value_transform (gimple_stmt_iterator *si)
|| optimize_bb_for_size_p (gimple_bb (stmt)))
return false;
- if (dump_file)
- {
- fprintf (dump_file, "Mod power of 2 transformation on insn ");
- print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
- }
-
/* Compute probability of taking the optimal path. */
all = count + wrong_values;
if (check_counter (stmt, "pow2", &count, &all, gimple_bb (stmt)->count))
return false;
+ if (dump_file)
+ fprintf (dump_file, "Transformation done: mod power of 2\n");
+
if (all > 0)
prob = profile_probability::probability_in_gcov_type (count, all);
else
@@ -1151,10 +1145,7 @@ gimple_mod_subtract_transform (gimple_stmt_iterator *si)
gimple_remove_histogram_value (cfun, stmt, histogram);
if (dump_file)
- {
- fprintf (dump_file, "Mod subtract transformation on insn ");
- print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
- }
+ fprintf (dump_file, "Transformation done: mod subtract\n");
/* Compute probability of taking the optimal path(s). */
if (all > 0)
@@ -1527,14 +1518,11 @@ interesting_stringop_to_profile_p (gcall *call, int *size_arg)
enum built_in_function fcode;
fcode = DECL_FUNCTION_CODE (gimple_call_fndecl (call));
- if (fcode != BUILT_IN_MEMCPY && fcode != BUILT_IN_MEMPCPY
- && fcode != BUILT_IN_MEMSET && fcode != BUILT_IN_BZERO)
- return false;
-
switch (fcode)
{
case BUILT_IN_MEMCPY:
case BUILT_IN_MEMPCPY:
+ case BUILT_IN_MEMMOVE:
*size_arg = 2;
return validate_gimple_arglist (call, POINTER_TYPE, POINTER_TYPE,
INTEGER_TYPE, VOID_TYPE);
@@ -1547,7 +1535,7 @@ interesting_stringop_to_profile_p (gcall *call, int *size_arg)
return validate_gimple_arglist (call, POINTER_TYPE, INTEGER_TYPE,
VOID_TYPE);
default:
- gcc_unreachable ();
+ return false;
}
}
@@ -1710,6 +1698,7 @@ gimple_stringops_transform (gimple_stmt_iterator *gsi)
{
case BUILT_IN_MEMCPY:
case BUILT_IN_MEMPCPY:
+ case BUILT_IN_MEMMOVE:
src = gimple_call_arg (stmt, 1);
src_align = get_pointer_alignment (src);
if (!can_move_by_pieces (val, MIN (dest_align, src_align)))
@@ -1744,11 +1733,9 @@ gimple_stringops_transform (gimple_stmt_iterator *gsi)
}
if (dump_file)
- {
- fprintf (dump_file, "Single value %i stringop transformation on ",
- (int)val);
- print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
- }
+ fprintf (dump_file,
+ "Transformation done: single value %i stringop for %s\n",
+ (int)val, built_in_names[(int)fcode]);
gimple_stringop_fixed_value (stmt, tree_val, prob, count, all);
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 0d3609e..e46bc59 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -2401,7 +2401,7 @@ static hash_set<tree> *pending_assemble_externals_set;
static bool
incorporeal_function_p (tree decl)
{
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl))
+ if (TREE_CODE (decl) == FUNCTION_DECL && fndecl_built_in_p (decl))
{
const char *name;
@@ -3146,7 +3146,9 @@ compare_constant (const tree t1, const tree t2)
return FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1), TREE_FIXED_CST (t2));
case STRING_CST:
- if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
+ if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2))
+ || int_size_in_bytes (TREE_TYPE (t1))
+ != int_size_in_bytes (TREE_TYPE (t2)))
return 0;
return (TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
@@ -3303,8 +3305,9 @@ get_constant_size (tree exp)
HOST_WIDE_INT size;
size = int_size_in_bytes (TREE_TYPE (exp));
- if (TREE_CODE (exp) == STRING_CST)
- size = MAX (TREE_STRING_LENGTH (exp), size);
+ gcc_checking_assert (size >= 0);
+ gcc_checking_assert (TREE_CODE (exp) != STRING_CST
+ || size >= TREE_STRING_LENGTH (exp));
return size;
}
@@ -3923,7 +3926,6 @@ output_constant_pool_2 (fixed_size_mode mode, rtx x, unsigned int align)
case MODE_UFRACT:
case MODE_ACCUM:
case MODE_UACCUM:
- case MODE_POINTER_BOUNDS:
assemble_integer (x, GET_MODE_SIZE (mode), align, 1);
break;
@@ -4774,6 +4776,30 @@ initializer_constant_valid_for_bitfield_p (tree value)
return false;
}
+/* Check if a STRING_CST fits into the field.
+ Tolerate only the case when the NUL termination
+ does not fit into the field. */
+
+static bool
+check_string_literal (tree string, unsigned HOST_WIDE_INT size)
+{
+ tree type = TREE_TYPE (string);
+ tree eltype = TREE_TYPE (type);
+ unsigned HOST_WIDE_INT elts = tree_to_uhwi (TYPE_SIZE_UNIT (eltype));
+ unsigned HOST_WIDE_INT mem_size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
+ int len = TREE_STRING_LENGTH (string);
+
+ if (elts != 1 && elts != 2 && elts != 4)
+ return false;
+ if (len < 0 || len % elts != 0)
+ return false;
+ if (size < (unsigned)len)
+ return false;
+ if (mem_size != size)
+ return false;
+ return true;
+}
+
/* output_constructor outer state of relevance in recursive calls, typically
for nested aggregate bitfields. */
@@ -4942,6 +4968,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
case STRING_CST:
thissize
= MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp), size);
+ gcc_checking_assert (check_string_literal (exp, size));
assemble_string (TREE_STRING_POINTER (exp), thissize);
break;
case VECTOR_CST:
@@ -5161,6 +5188,8 @@ output_constructor_regular_field (oc_local_state *local)
on the chain is a TYPE_DECL of the enclosing struct. */
const_tree next = DECL_CHAIN (local->field);
gcc_assert (!fieldsize || !next || TREE_CODE (next) != FIELD_DECL);
+ tree size = TYPE_SIZE_UNIT (TREE_TYPE (local->val));
+ gcc_checking_assert (compare_tree_int (size, fieldsize) == 0);
}
else
fieldsize = tree_to_uhwi (DECL_SIZE_UNIT (local->field));
diff --git a/gcc/vec.c b/gcc/vec.c
index beb857f..ac3226b 100644
--- a/gcc/vec.c
+++ b/gcc/vec.c
@@ -201,21 +201,12 @@ qsort_chk_error (const void *p1, const void *p2, const void *p3,
internal_error ("qsort checking failed");
}
-/* Wrapper around qsort with checking that CMP is consistent on given input.
-
- Strictly speaking, passing invalid (non-transitive, non-anti-commutative)
- comparators to libc qsort can result in undefined behavior. Therefore we
- should ideally perform consistency checks prior to invoking qsort, but in
- order to do that optimally we'd need to sort the array ourselves beforehand
- with a sorting routine known to be "safe". Instead, we expect that most
- implementations in practice will still produce some permutation of input
- array even for invalid comparators, which enables us to perform checks on
- the output array. */
+/* Verify anti-symmetry and transitivity for comparator CMP on sorted array
+ of N SIZE-sized elements pointed to by BASE. */
void
qsort_chk (void *base, size_t n, size_t size,
int (*cmp)(const void *, const void *))
{
- gcc_qsort (base, n, size, cmp);
#if 0
#define LIM(n) (n)
#else
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index bba170f..6b6a918 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see
#include "alloc-pool.h"
#include "attribs.h"
#include "vr-values.h"
+#include "cfghooks.h"
/* Set value range VR to a non-negative range of type TYPE. */
@@ -343,7 +344,7 @@ vr_values::vrp_stmt_computes_nonzero (gimple *stmt)
&& TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
{
value_range *vr = get_value_range (TREE_OPERAND (base, 0));
- if (range_is_nonnull (vr))
+ if (!range_includes_zero_p (vr))
return true;
}
}
@@ -1107,12 +1108,8 @@ vr_values::extract_range_basic (value_range *vr, gimple *stmt)
if (TREE_CODE (arg) == SSA_NAME)
{
value_range *vr0 = get_value_range (arg);
- /* If arg is non-zero, then ffs or popcount
- are non-zero. */
- if ((vr0->type == VR_RANGE
- && range_includes_zero_p (vr0->min, vr0->max) == 0)
- || (vr0->type == VR_ANTI_RANGE
- && range_includes_zero_p (vr0->min, vr0->max) == 1))
+ /* If arg is non-zero, then ffs or popcount are non-zero. */
+ if (range_includes_zero_p (vr0) == 0)
mini = 1;
/* If some high bits are known to be zero,
we can decrease the maximum. */
@@ -1922,6 +1919,8 @@ vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges")
vr_value = XCNEWVEC (value_range *, num_vr_values);
vr_phi_edge_counts = XCNEWVEC (int, num_ssa_names);
bitmap_obstack_initialize (&vrp_equiv_obstack);
+ to_remove_edges.create (10);
+ to_update_switch_stmts.create (5);
}
/* Free VRP lattice. */
@@ -1938,6 +1937,12 @@ vr_values::~vr_values ()
and not available. */
vr_value = NULL;
vr_phi_edge_counts = NULL;
+
+ /* If there are entries left in TO_REMOVE_EDGES or TO_UPDATE_SWITCH_STMTS
+ then an EVRP client did not clean up properly. Catch it now rather
+ than seeing something more obscure later. */
+ gcc_assert (to_remove_edges.is_empty ()
+ && to_update_switch_stmts.is_empty ());
}
@@ -2711,7 +2716,7 @@ vr_values::vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p)
}
*taken_edge_p = find_edge (gimple_bb (stmt),
- label_to_block (CASE_LABEL (val)));
+ label_to_block (cfun, CASE_LABEL (val)));
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -3300,10 +3305,10 @@ vr_values::simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi,
else
return false;
- if (!zero_nonzero_bits_from_vr (TREE_TYPE (op0), &vr0, &may_be_nonzero0,
+ if (!vrp_set_zero_nonzero_bits (TREE_TYPE (op0), &vr0, &may_be_nonzero0,
&must_be_nonzero0))
return false;
- if (!zero_nonzero_bits_from_vr (TREE_TYPE (op1), &vr1, &may_be_nonzero1,
+ if (!vrp_set_zero_nonzero_bits (TREE_TYPE (op1), &vr1, &may_be_nonzero1,
&must_be_nonzero1))
return false;
@@ -3764,7 +3769,8 @@ vr_values::simplify_switch_using_ranges (gswitch *stmt)
for (i = 0; i < n2; ++i)
{
e = find_edge (gimple_bb (stmt),
- label_to_block (CASE_LABEL (TREE_VEC_ELT (vec2, i))));
+ label_to_block (cfun,
+ CASE_LABEL (TREE_VEC_ELT (vec2, i))));
e->aux = (void *)-1;
}
@@ -3783,6 +3789,7 @@ vr_values::simplify_switch_using_ranges (gswitch *stmt)
}
to_remove_edges.safe_push (e);
e->flags &= ~EDGE_EXECUTABLE;
+ e->flags |= EDGE_IGNORE;
}
/* And queue an update for the stmt. */
@@ -3792,6 +3799,45 @@ vr_values::simplify_switch_using_ranges (gswitch *stmt)
return false;
}
+void
+vr_values::cleanup_edges_and_switches (void)
+{
+ int i;
+ edge e;
+ switch_update *su;
+
+ /* Remove dead edges from SWITCH_EXPR optimization. This leaves the
+ CFG in a broken state and requires a cfg_cleanup run. */
+ FOR_EACH_VEC_ELT (to_remove_edges, i, e)
+ remove_edge (e);
+
+ /* Update SWITCH_EXPR case label vector. */
+ FOR_EACH_VEC_ELT (to_update_switch_stmts, i, su)
+ {
+ size_t j;
+ size_t n = TREE_VEC_LENGTH (su->vec);
+ tree label;
+ gimple_switch_set_num_labels (su->stmt, n);
+ for (j = 0; j < n; j++)
+ gimple_switch_set_label (su->stmt, j, TREE_VEC_ELT (su->vec, j));
+ /* As we may have replaced the default label with a regular one
+ make sure to make it a real default label again. This ensures
+ optimal expansion. */
+ label = gimple_switch_label (su->stmt, 0);
+ CASE_LOW (label) = NULL_TREE;
+ CASE_HIGH (label) = NULL_TREE;
+ }
+
+ if (!to_remove_edges.is_empty ())
+ {
+ free_dominance_info (CDI_DOMINATORS);
+ loops_state_set (LOOPS_NEED_FIXUP);
+ }
+
+ to_remove_edges.release ();
+ to_update_switch_stmts.release ();
+}
+
/* Simplify an integral conversion from an SSA name in STMT. */
static bool
diff --git a/gcc/vr-values.h b/gcc/vr-values.h
index 80b16ca..487a800c 100644
--- a/gcc/vr-values.h
+++ b/gcc/vr-values.h
@@ -68,6 +68,9 @@ class vr_values
value_range *allocate_value_range (void)
{ return vrp_value_range_pool.allocate (); }
+ /* */
+ void cleanup_edges_and_switches (void);
+
private:
void add_equivalence (bitmap *, const_tree);
bool vrp_stmt_computes_nonzero (gimple *);
@@ -124,6 +127,19 @@ class vr_values
number of executable edges we saw the last time we visited the
node. */
int *vr_phi_edge_counts;
+
+ /* Vectors of edges that need removing and switch statements that
+ need updating. It is expected that a pass using the simplification
+ routines will, at the end of the pass, clean up the edges and
+ switch statements. The class dtor will try to detect cases
+ that do not follow that expectation. */
+ struct switch_update {
+ gswitch *stmt;
+ tree vec;
+ };
+
+ vec<edge> to_remove_edges;
+ vec<switch_update> to_update_switch_stmts;
};
#define VR_INITIALIZER { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL }
diff --git a/gcc/wide-int-range.cc b/gcc/wide-int-range.cc
new file mode 100644
index 0000000..a85fe9f
--- /dev/null
+++ b/gcc/wide-int-range.cc
@@ -0,0 +1,841 @@
+/* Support routines for range operations on wide ints.
+ Copyright (C) 2018 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 "tree.h"
+#include "function.h"
+#include "fold-const.h"
+#include "wide-int-range.h"
+
+/* Wrapper around wide_int_binop that adjusts for overflow.
+
+ Return true if we can compute the result; i.e. if the operation
+ doesn't overflow or if the overflow is undefined. In the latter
+ case (if the operation overflows and overflow is undefined), then
+ adjust the result to be -INF or +INF depending on CODE, VAL1 and
+ VAL2. Return the value in *RES.
+
+ Return false for division by zero, for which the result is
+ indeterminate. */
+
+static bool
+wide_int_binop_overflow (wide_int &res,
+ enum tree_code code,
+ const wide_int &w0, const wide_int &w1,
+ signop sign, bool overflow_undefined)
+{
+ wi::overflow_type overflow;
+ if (!wide_int_binop (res, code, w0, w1, sign, &overflow))
+ return false;
+
+ /* If the operation overflowed return -INF or +INF depending on the
+ operation and the combination of signs of the operands. */
+ if (overflow && overflow_undefined)
+ {
+ switch (code)
+ {
+ case MULT_EXPR:
+ /* For multiplication, the sign of the overflow is given
+ by the comparison of the signs of the operands. */
+ if (sign == UNSIGNED || w0.sign_mask () == w1.sign_mask ())
+ res = wi::max_value (w0.get_precision (), sign);
+ else
+ res = wi::min_value (w0.get_precision (), sign);
+ return true;
+
+ case TRUNC_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case CEIL_DIV_EXPR:
+ case EXACT_DIV_EXPR:
+ case ROUND_DIV_EXPR:
+ /* For division, the only case is -INF / -1 = +INF. */
+ res = wi::max_value (w0.get_precision (), sign);
+ return true;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+ return !overflow;
+}
+
+/* For range [LB, UB] compute two wide_int bit masks.
+
+ In the MAY_BE_NONZERO bit mask, if some bit is unset, it means that
+ for all numbers in the range the bit is 0, otherwise it might be 0
+ or 1.
+
+ In the MUST_BE_NONZERO bit mask, if some bit is set, it means that
+ for all numbers in the range the bit is 1, otherwise it might be 0
+ or 1. */
+
+void
+wide_int_range_set_zero_nonzero_bits (signop sign,
+ const wide_int &lb, const wide_int &ub,
+ wide_int &may_be_nonzero,
+ wide_int &must_be_nonzero)
+{
+ may_be_nonzero = wi::minus_one (lb.get_precision ());
+ must_be_nonzero = wi::zero (lb.get_precision ());
+
+ if (wi::eq_p (lb, ub))
+ {
+ may_be_nonzero = lb;
+ must_be_nonzero = may_be_nonzero;
+ }
+ else if (wi::ge_p (lb, 0, sign) || wi::lt_p (ub, 0, sign))
+ {
+ wide_int xor_mask = lb ^ ub;
+ may_be_nonzero = lb | ub;
+ must_be_nonzero = lb & ub;
+ if (xor_mask != 0)
+ {
+ wide_int mask = wi::mask (wi::floor_log2 (xor_mask), false,
+ may_be_nonzero.get_precision ());
+ may_be_nonzero = may_be_nonzero | mask;
+ must_be_nonzero = wi::bit_and_not (must_be_nonzero, mask);
+ }
+ }
+}
+
+/* Order 2 sets of wide int ranges (w0/w1, w2/w3) and set MIN/MAX
+ accordingly. */
+
+static void
+wide_int_range_order_set (wide_int &min, wide_int &max,
+ wide_int &w0, wide_int &w1,
+ wide_int &w2, wide_int &w3,
+ signop sign)
+{
+ /* Order pairs w0,w1 and w2,w3. */
+ if (wi::gt_p (w0, w1, sign))
+ std::swap (w0, w1);
+ if (wi::gt_p (w2, w3, sign))
+ std::swap (w2, w3);
+
+ /* Choose min and max from the ordered pairs. */
+ min = wi::min (w0, w2, sign);
+ max = wi::max (w1, w3, sign);
+}
+
+/* Calculate the cross product of two sets of ranges (VR0 and VR1) and
+ store the result in [RES_LB, RES_UB].
+
+ CODE is the operation to perform with sign SIGN.
+
+ OVERFLOW_UNDEFINED is set if overflow is undefined for the operation type.
+
+ Return TRUE if we were able to calculate the cross product. */
+
+bool
+wide_int_range_cross_product (wide_int &res_lb, wide_int &res_ub,
+ enum tree_code code, signop sign,
+ const wide_int &vr0_lb, const wide_int &vr0_ub,
+ const wide_int &vr1_lb, const wide_int &vr1_ub,
+ bool overflow_undefined)
+{
+ wide_int cp1, cp2, cp3, cp4;
+
+ /* Compute the 4 cross operations, bailing if we get an overflow we
+ can't handle. */
+
+ if (!wide_int_binop_overflow (cp1, code, vr0_lb, vr1_lb, sign,
+ overflow_undefined))
+ return false;
+
+ if (wi::eq_p (vr0_lb, vr0_ub))
+ cp3 = cp1;
+ else if (!wide_int_binop_overflow (cp3, code, vr0_ub, vr1_lb, sign,
+ overflow_undefined))
+ return false;
+
+ if (wi::eq_p (vr1_lb, vr1_ub))
+ cp2 = cp1;
+ else if (!wide_int_binop_overflow (cp2, code, vr0_lb, vr1_ub, sign,
+ overflow_undefined))
+ return false;
+
+ if (wi::eq_p (vr0_lb, vr0_ub))
+ cp4 = cp2;
+ else if (!wide_int_binop_overflow (cp4, code, vr0_ub, vr1_ub, sign,
+ overflow_undefined))
+ return false;
+
+ wide_int_range_order_set (res_lb, res_ub, cp1, cp2, cp3, cp4, sign);
+ return true;
+}
+
+/* Multiply two ranges when TYPE_OVERFLOW_WRAPS:
+
+ [RES_LB, RES_UB] = [MIN0, MAX0] * [MIN1, MAX1]
+
+ This is basically fancy code so we don't drop to varying with an
+ unsigned [-3,-1]*[-3,-1].
+
+ Return TRUE if we were able to perform the operation. */
+
+bool
+wide_int_range_mult_wrapping (wide_int &res_lb,
+ wide_int &res_ub,
+ signop sign,
+ unsigned prec,
+ const wide_int &min0_,
+ const wide_int &max0_,
+ const wide_int &min1_,
+ const wide_int &max1_)
+{
+ /* This test requires 2*prec bits if both operands are signed and
+ 2*prec + 2 bits if either is not. Therefore, extend the values
+ using the sign of the result to PREC2. From here on out,
+ everthing is just signed math no matter what the input types
+ were. */
+ widest2_int min0 = widest2_int::from (min0_, sign);
+ widest2_int max0 = widest2_int::from (max0_, sign);
+ widest2_int min1 = widest2_int::from (min1_, sign);
+ widest2_int max1 = widest2_int::from (max1_, sign);
+ widest2_int sizem1 = wi::mask <widest2_int> (prec, false);
+ widest2_int size = sizem1 + 1;
+
+ /* Canonicalize the intervals. */
+ if (sign == UNSIGNED)
+ {
+ if (wi::ltu_p (size, min0 + max0))
+ {
+ min0 -= size;
+ max0 -= size;
+ }
+
+ if (wi::ltu_p (size, min1 + max1))
+ {
+ min1 -= size;
+ max1 -= size;
+ }
+ }
+
+ widest2_int prod0 = min0 * min1;
+ widest2_int prod1 = min0 * max1;
+ widest2_int prod2 = max0 * min1;
+ widest2_int prod3 = max0 * max1;
+
+ /* Sort the 4 products so that min is in prod0 and max is in
+ prod3. */
+ /* min0min1 > max0max1 */
+ if (prod0 > prod3)
+ std::swap (prod0, prod3);
+
+ /* min0max1 > max0min1 */
+ if (prod1 > prod2)
+ std::swap (prod1, prod2);
+
+ if (prod0 > prod1)
+ std::swap (prod0, prod1);
+
+ if (prod2 > prod3)
+ std::swap (prod2, prod3);
+
+ /* diff = max - min. */
+ prod2 = prod3 - prod0;
+ if (wi::geu_p (prod2, sizem1))
+ /* The range covers all values. */
+ return false;
+
+ res_lb = wide_int::from (prod0, prec, sign);
+ res_ub = wide_int::from (prod3, prec, sign);
+ return true;
+}
+
+/* Perform multiplicative operation CODE on two ranges:
+
+ [RES_LB, RES_UB] = [VR0_LB, VR0_UB] .CODE. [VR1_LB, VR1_LB]
+
+ Return TRUE if we were able to perform the operation.
+
+ NOTE: If code is MULT_EXPR and TYPE_OVERFLOW_WRAPS, the resulting
+ range must be canonicalized by the caller because its components
+ may be swapped. */
+
+bool
+wide_int_range_multiplicative_op (wide_int &res_lb, wide_int &res_ub,
+ enum tree_code code,
+ signop sign,
+ unsigned prec,
+ const wide_int &vr0_lb,
+ const wide_int &vr0_ub,
+ const wide_int &vr1_lb,
+ const wide_int &vr1_ub,
+ bool overflow_undefined,
+ bool overflow_wraps)
+{
+ /* Multiplications, divisions and shifts are a bit tricky to handle,
+ depending on the mix of signs we have in the two ranges, we
+ need to operate on different values to get the minimum and
+ maximum values for the new range. One approach is to figure
+ out all the variations of range combinations and do the
+ operations.
+
+ However, this involves several calls to compare_values and it
+ is pretty convoluted. It's simpler to do the 4 operations
+ (MIN0 OP MIN1, MIN0 OP MAX1, MAX0 OP MIN1 and MAX0 OP MAX0 OP
+ MAX1) and then figure the smallest and largest values to form
+ the new range. */
+ if (code == MULT_EXPR && overflow_wraps)
+ return wide_int_range_mult_wrapping (res_lb, res_ub,
+ sign, prec,
+ vr0_lb, vr0_ub, vr1_lb, vr1_ub);
+ return wide_int_range_cross_product (res_lb, res_ub,
+ code, sign,
+ vr0_lb, vr0_ub, vr1_lb, vr1_ub,
+ overflow_undefined);
+}
+
+/* Perform a left shift operation on two ranges:
+
+ [RES_LB, RES_UB] = [VR0_LB, VR0_UB] << [VR1_LB, VR1_LB]
+
+ Return TRUE if we were able to perform the operation.
+
+ NOTE: The resulting range must be canonicalized by the caller
+ because its contents components may be swapped. */
+
+bool
+wide_int_range_lshift (wide_int &res_lb, wide_int &res_ub,
+ signop sign, unsigned prec,
+ const wide_int &vr0_lb, const wide_int &vr0_ub,
+ const wide_int &vr1_lb, const wide_int &vr1_ub,
+ bool overflow_undefined, bool overflow_wraps)
+{
+ /* Transform left shifts by constants into multiplies. */
+ if (wi::eq_p (vr1_lb, vr1_ub))
+ {
+ unsigned shift = vr1_ub.to_uhwi ();
+ wide_int tmp = wi::set_bit_in_zero (shift, prec);
+ return wide_int_range_multiplicative_op (res_lb, res_ub,
+ MULT_EXPR, sign, prec,
+ vr0_lb, vr0_ub, tmp, tmp,
+ overflow_undefined,
+ /*overflow_wraps=*/true);
+ }
+
+ int overflow_pos = prec;
+ if (sign == SIGNED)
+ overflow_pos -= 1;
+ int bound_shift = overflow_pos - vr1_ub.to_shwi ();
+ /* If bound_shift == HOST_BITS_PER_WIDE_INT, the llshift can
+ overflow. However, for that to happen, vr1.max needs to be
+ zero, which means vr1 is a singleton range of zero, which
+ means it should be handled by the previous LSHIFT_EXPR
+ if-clause. */
+ wide_int bound = wi::set_bit_in_zero (bound_shift, prec);
+ wide_int complement = ~(bound - 1);
+ wide_int low_bound, high_bound;
+ bool in_bounds = false;
+ if (sign == UNSIGNED)
+ {
+ low_bound = bound;
+ high_bound = complement;
+ if (wi::ltu_p (vr0_ub, low_bound))
+ {
+ /* [5, 6] << [1, 2] == [10, 24]. */
+ /* We're shifting out only zeroes, the value increases
+ monotonically. */
+ in_bounds = true;
+ }
+ else if (wi::ltu_p (high_bound, vr0_lb))
+ {
+ /* [0xffffff00, 0xffffffff] << [1, 2]
+ == [0xfffffc00, 0xfffffffe]. */
+ /* We're shifting out only ones, the value decreases
+ monotonically. */
+ in_bounds = true;
+ }
+ }
+ else
+ {
+ /* [-1, 1] << [1, 2] == [-4, 4]. */
+ low_bound = complement;
+ high_bound = bound;
+ if (wi::lts_p (vr0_ub, high_bound)
+ && wi::lts_p (low_bound, vr0_lb))
+ {
+ /* For non-negative numbers, we're shifting out only
+ zeroes, the value increases monotonically.
+ For negative numbers, we're shifting out only ones, the
+ value decreases monotomically. */
+ in_bounds = true;
+ }
+ }
+ if (in_bounds)
+ return wide_int_range_multiplicative_op (res_lb, res_ub,
+ LSHIFT_EXPR, sign, prec,
+ vr0_lb, vr0_ub,
+ vr1_lb, vr1_ub,
+ overflow_undefined,
+ overflow_wraps);
+ return false;
+}
+
+/* Return TRUE if a bit operation on two ranges can be easily
+ optimized in terms of a mask.
+
+ Basically, for BIT_AND_EXPR or BIT_IOR_EXPR see if we can optimize:
+
+ [LB, UB] op Z
+ into:
+ [LB op Z, UB op Z]
+
+ It is up to the caller to perform the actual folding above. */
+
+static bool
+wide_int_range_can_optimize_bit_op (tree_code code,
+ const wide_int &lb, const wide_int &ub,
+ const wide_int &mask)
+
+{
+ if (code != BIT_AND_EXPR && code != BIT_IOR_EXPR)
+ return false;
+ /* If Z is a constant which (for op | its bitwise not) has n
+ consecutive least significant bits cleared followed by m 1
+ consecutive bits set immediately above it and either
+ m + n == precision, or (x >> (m + n)) == (y >> (m + n)).
+
+ The least significant n bits of all the values in the range are
+ cleared or set, the m bits above it are preserved and any bits
+ above these are required to be the same for all values in the
+ range. */
+
+ wide_int w = mask;
+ int m = 0, n = 0;
+ if (code == BIT_IOR_EXPR)
+ w = ~w;
+ if (wi::eq_p (w, 0))
+ n = w.get_precision ();
+ else
+ {
+ n = wi::ctz (w);
+ w = ~(w | wi::mask (n, false, w.get_precision ()));
+ if (wi::eq_p (w, 0))
+ m = w.get_precision () - n;
+ else
+ m = wi::ctz (w) - n;
+ }
+ wide_int new_mask = wi::mask (m + n, true, w.get_precision ());
+ if ((new_mask & lb) == (new_mask & ub))
+ return true;
+
+ return false;
+}
+
+/* Helper function for wide_int_range_optimize_bit_op.
+
+ Calculates bounds and mask for a pair of ranges. The mask is the
+ singleton range among the ranges, if any. The bounds are the
+ bounds for the remaining range. */
+
+bool
+wide_int_range_get_mask_and_bounds (wide_int &mask,
+ wide_int &lower_bound,
+ wide_int &upper_bound,
+ const wide_int &vr0_min,
+ const wide_int &vr0_max,
+ const wide_int &vr1_min,
+ const wide_int &vr1_max)
+{
+ if (wi::eq_p (vr1_min, vr1_max))
+ {
+ mask = vr1_min;
+ lower_bound = vr0_min;
+ upper_bound = vr0_max;
+ return true;
+ }
+ else if (wi::eq_p (vr0_min, vr0_max))
+ {
+ mask = vr0_min;
+ lower_bound = vr1_min;
+ upper_bound = vr1_max;
+ return true;
+ }
+ return false;
+}
+
+/* Optimize a bit operation (BIT_AND_EXPR or BIT_IOR_EXPR) if
+ possible. If so, return TRUE and store the result in
+ [RES_LB, RES_UB]. */
+
+bool
+wide_int_range_optimize_bit_op (wide_int &res_lb, wide_int &res_ub,
+ enum tree_code code,
+ signop sign,
+ const wide_int &vr0_min,
+ const wide_int &vr0_max,
+ const wide_int &vr1_min,
+ const wide_int &vr1_max)
+{
+ gcc_assert (code == BIT_AND_EXPR || code == BIT_IOR_EXPR);
+
+ wide_int lower_bound, upper_bound, mask;
+ if (!wide_int_range_get_mask_and_bounds (mask, lower_bound, upper_bound,
+ vr0_min, vr0_max, vr1_min, vr1_max))
+ return false;
+ if (wide_int_range_can_optimize_bit_op (code,
+ lower_bound, upper_bound, mask))
+ {
+ wi::overflow_type ovf;
+ wide_int_binop (res_lb, code, lower_bound, mask, sign, &ovf);
+ wide_int_binop (res_ub, code, upper_bound, mask, sign, &ovf);
+ return true;
+ }
+ return false;
+}
+
+/* Calculate the XOR of two ranges and store the result in [WMIN,WMAX].
+ The two input ranges are described by their MUST_BE_NONZERO and
+ MAY_BE_NONZERO bit masks.
+
+ Return TRUE if we were able to successfully calculate the new range. */
+
+bool
+wide_int_range_bit_xor (wide_int &wmin, wide_int &wmax,
+ signop sign,
+ unsigned prec,
+ const wide_int &must_be_nonzero0,
+ const wide_int &may_be_nonzero0,
+ const wide_int &must_be_nonzero1,
+ const wide_int &may_be_nonzero1)
+{
+ wide_int result_zero_bits = ((must_be_nonzero0 & must_be_nonzero1)
+ | ~(may_be_nonzero0 | may_be_nonzero1));
+ wide_int result_one_bits
+ = (wi::bit_and_not (must_be_nonzero0, may_be_nonzero1)
+ | wi::bit_and_not (must_be_nonzero1, may_be_nonzero0));
+ wmax = ~result_zero_bits;
+ wmin = result_one_bits;
+ /* If the range has all positive or all negative values, the result
+ is better than VARYING. */
+ if (wi::lt_p (wmin, 0, sign) || wi::ge_p (wmax, 0, sign))
+ return true;
+ wmin = wi::min_value (prec, sign);
+ wmax = wi::max_value (prec, sign);
+ return false;
+}
+
+/* Calculate the IOR of two ranges and store the result in [WMIN,WMAX].
+ Return TRUE if we were able to successfully calculate the new range. */
+
+bool
+wide_int_range_bit_ior (wide_int &wmin, wide_int &wmax,
+ signop sign,
+ const wide_int &vr0_min,
+ const wide_int &vr0_max,
+ const wide_int &vr1_min,
+ const wide_int &vr1_max,
+ const wide_int &must_be_nonzero0,
+ const wide_int &may_be_nonzero0,
+ const wide_int &must_be_nonzero1,
+ const wide_int &may_be_nonzero1)
+{
+ if (wide_int_range_optimize_bit_op (wmin, wmax, BIT_IOR_EXPR, sign,
+ vr0_min, vr0_max,
+ vr1_min, vr1_max))
+ return true;
+ wmin = must_be_nonzero0 | must_be_nonzero1;
+ wmax = may_be_nonzero0 | may_be_nonzero1;
+ /* If the input ranges contain only positive values we can
+ truncate the minimum of the result range to the maximum
+ of the input range minima. */
+ if (wi::ge_p (vr0_min, 0, sign)
+ && wi::ge_p (vr1_min, 0, sign))
+ {
+ wmin = wi::max (wmin, vr0_min, sign);
+ wmin = wi::max (wmin, vr1_min, sign);
+ }
+ /* If either input range contains only negative values
+ we can truncate the minimum of the result range to the
+ respective minimum range. */
+ if (wi::lt_p (vr0_max, 0, sign))
+ wmin = wi::max (wmin, vr0_min, sign);
+ if (wi::lt_p (vr1_max, 0, sign))
+ wmin = wi::max (wmin, vr1_min, sign);
+ /* If the limits got swapped around, indicate error so we can adjust
+ the range to VARYING. */
+ if (wi::gt_p (wmin, wmax,sign))
+ return false;
+ return true;
+}
+
+/* Calculate the bitwise AND of two ranges and store the result in [WMIN,WMAX].
+ Return TRUE if we were able to successfully calculate the new range. */
+
+bool
+wide_int_range_bit_and (wide_int &wmin, wide_int &wmax,
+ signop sign,
+ unsigned prec,
+ const wide_int &vr0_min,
+ const wide_int &vr0_max,
+ const wide_int &vr1_min,
+ const wide_int &vr1_max,
+ const wide_int &must_be_nonzero0,
+ const wide_int &may_be_nonzero0,
+ const wide_int &must_be_nonzero1,
+ const wide_int &may_be_nonzero1)
+{
+ if (wide_int_range_optimize_bit_op (wmin, wmax, BIT_AND_EXPR, sign,
+ vr0_min, vr0_max,
+ vr1_min, vr1_max))
+ return true;
+ wmin = must_be_nonzero0 & must_be_nonzero1;
+ wmax = may_be_nonzero0 & may_be_nonzero1;
+ /* If both input ranges contain only negative values we can
+ truncate the result range maximum to the minimum of the
+ input range maxima. */
+ if (wi::lt_p (vr0_max, 0, sign) && wi::lt_p (vr1_max, 0, sign))
+ {
+ wmax = wi::min (wmax, vr0_max, sign);
+ wmax = wi::min (wmax, vr1_max, sign);
+ }
+ /* If either input range contains only non-negative values
+ we can truncate the result range maximum to the respective
+ maximum of the input range. */
+ if (wi::ge_p (vr0_min, 0, sign))
+ wmax = wi::min (wmax, vr0_max, sign);
+ if (wi::ge_p (vr1_min, 0, sign))
+ wmax = wi::min (wmax, vr1_max, sign);
+ /* PR68217: In case of signed & sign-bit-CST should
+ result in [-INF, 0] instead of [-INF, INF]. */
+ if (wi::gt_p (wmin, wmax, sign))
+ {
+ wide_int sign_bit = wi::set_bit_in_zero (prec - 1, prec);
+ if (sign == SIGNED
+ && ((wi::eq_p (vr0_min, vr0_max)
+ && !wi::cmps (vr0_min, sign_bit))
+ || (wi::eq_p (vr1_min, vr1_max)
+ && !wi::cmps (vr1_min, sign_bit))))
+ {
+ wmin = wi::min_value (prec, sign);
+ wmax = wi::zero (prec);
+ }
+ }
+ /* If the limits got swapped around, indicate error so we can adjust
+ the range to VARYING. */
+ if (wi::gt_p (wmin, wmax,sign))
+ return false;
+ return true;
+}
+
+/* Calculate TRUNC_MOD_EXPR on two ranges and store the result in
+ [WMIN,WMAX]. */
+
+void
+wide_int_range_trunc_mod (wide_int &wmin, wide_int &wmax,
+ signop sign,
+ unsigned prec,
+ const wide_int &vr0_min,
+ const wide_int &vr0_max,
+ const wide_int &vr1_min,
+ const wide_int &vr1_max)
+{
+ wide_int tmp;
+
+ /* ABS (A % B) < ABS (B) and either
+ 0 <= A % B <= A or A <= A % B <= 0. */
+ wmax = vr1_max - 1;
+ if (sign == SIGNED)
+ {
+ tmp = -1 - vr1_min;
+ wmax = wi::smax (wmax, tmp);
+ }
+
+ if (sign == UNSIGNED)
+ wmin = wi::zero (prec);
+ else
+ {
+ wmin = -wmax;
+ tmp = vr0_min;
+ if (wi::gts_p (tmp, 0))
+ tmp = wi::zero (prec);
+ wmin = wi::smax (wmin, tmp);
+ }
+ tmp = vr0_max;
+ if (sign == SIGNED && wi::neg_p (tmp))
+ tmp = wi::zero (prec);
+ wmax = wi::min (wmax, tmp, sign);
+}
+
+/* Calculate ABS_EXPR on a range and store the result in [MIN, MAX]. */
+
+bool
+wide_int_range_abs (wide_int &min, wide_int &max,
+ signop sign, unsigned prec,
+ const wide_int &vr0_min, const wide_int &vr0_max,
+ bool overflow_undefined)
+{
+ /* Pass through VR0 the easy cases. */
+ if (sign == UNSIGNED || wi::ge_p (vr0_min, 0, sign))
+ {
+ min = vr0_min;
+ max = vr0_max;
+ return true;
+ }
+
+ /* -TYPE_MIN_VALUE = TYPE_MIN_VALUE with flag_wrapv so we can't get a
+ useful range. */
+ wide_int min_value = wi::min_value (prec, sign);
+ wide_int max_value = wi::max_value (prec, sign);
+ if (!overflow_undefined && wi::eq_p (vr0_min, min_value))
+ return false;
+
+ /* ABS_EXPR may flip the range around, if the original range
+ included negative values. */
+ if (wi::eq_p (vr0_min, min_value))
+ min = max_value;
+ else
+ min = wi::abs (vr0_min);
+ if (wi::eq_p (vr0_max, min_value))
+ max = max_value;
+ else
+ max = wi::abs (vr0_max);
+
+ /* If the range contains zero then we know that the minimum value in the
+ range will be zero. */
+ if (wi::le_p (vr0_min, 0, sign) && wi::ge_p (vr0_max, 0, sign))
+ {
+ if (wi::gt_p (min, max, sign))
+ max = min;
+ min = wi::zero (prec);
+ }
+ else
+ {
+ /* If the range was reversed, swap MIN and MAX. */
+ if (wi::gt_p (min, max, sign))
+ std::swap (min, max);
+ }
+
+ /* If the new range has its limits swapped around (MIN > MAX), then
+ the operation caused one of them to wrap around. The only thing
+ we know is that the result is positive. */
+ if (wi::gt_p (min, max, sign))
+ {
+ min = wi::zero (prec);
+ max = max_value;
+ }
+ return true;
+}
+
+/* Convert range in [VR0_MIN, VR0_MAX] with INNER_SIGN and INNER_PREC,
+ to a range in [MIN, MAX] with OUTER_SIGN and OUTER_PREC.
+
+ Return TRUE if we were able to successfully calculate the new range.
+
+ Caller is responsible for canonicalizing the resulting range. */
+
+bool
+wide_int_range_convert (wide_int &min, wide_int &max,
+ signop inner_sign,
+ unsigned inner_prec,
+ signop outer_sign,
+ unsigned outer_prec,
+ const wide_int &vr0_min,
+ const wide_int &vr0_max)
+{
+ /* If the conversion is not truncating we can convert the min and
+ max values and canonicalize the resulting range. Otherwise we
+ can do the conversion if the size of the range is less than what
+ the precision of the target type can represent. */
+ if (outer_prec >= inner_prec
+ || wi::rshift (wi::sub (vr0_max, vr0_min),
+ wi::uhwi (outer_prec, inner_prec),
+ inner_sign) == 0)
+ {
+ min = wide_int::from (vr0_min, outer_prec, inner_sign);
+ max = wide_int::from (vr0_max, outer_prec, inner_sign);
+ return (!wi::eq_p (min, wi::min_value (outer_prec, outer_sign))
+ || !wi::eq_p (max, wi::max_value (outer_prec, outer_sign)));
+ }
+ return false;
+}
+
+/* Calculate a division operation on two ranges and store the result in
+ [WMIN, WMAX] U [EXTRA_MIN, EXTRA_MAX].
+
+ If EXTRA_RANGE_P is set upon return, EXTRA_MIN/EXTRA_MAX hold
+ meaningful information, otherwise they should be ignored.
+
+ Return TRUE if we were able to successfully calculate the new range. */
+
+bool
+wide_int_range_div (wide_int &wmin, wide_int &wmax,
+ tree_code code, signop sign, unsigned prec,
+ const wide_int &dividend_min, const wide_int &dividend_max,
+ const wide_int &divisor_min, const wide_int &divisor_max,
+ bool overflow_undefined,
+ bool overflow_wraps,
+ bool &extra_range_p,
+ wide_int &extra_min, wide_int &extra_max)
+{
+ extra_range_p = false;
+
+ /* If we know we won't divide by zero, just do the division. */
+ if (!wide_int_range_includes_zero_p (divisor_min, divisor_max, sign))
+ return wide_int_range_multiplicative_op (wmin, wmax, code, sign, prec,
+ dividend_min, dividend_max,
+ divisor_min, divisor_max,
+ overflow_undefined,
+ overflow_wraps);
+
+ /* If flag_non_call_exceptions, we must not eliminate a division
+ by zero. */
+ if (cfun->can_throw_non_call_exceptions)
+ return false;
+
+ /* If we're definitely dividing by zero, there's nothing to do. */
+ if (wide_int_range_zero_p (divisor_min, divisor_max, prec))
+ return false;
+
+ /* Perform the division in 2 parts, [LB, -1] and [1, UB],
+ which will skip any division by zero.
+
+ First divide by the negative numbers, if any. */
+ if (wi::neg_p (divisor_min, sign))
+ {
+ if (!wide_int_range_multiplicative_op (wmin, wmax,
+ code, sign, prec,
+ dividend_min, dividend_max,
+ divisor_min, wi::minus_one (prec),
+ overflow_undefined,
+ overflow_wraps))
+ return false;
+ extra_range_p = true;
+ }
+ /* Then divide by the non-zero positive numbers, if any. */
+ if (wi::gt_p (divisor_max, wi::zero (prec), sign))
+ {
+ if (!wide_int_range_multiplicative_op (extra_range_p ? extra_min : wmin,
+ extra_range_p ? extra_max : wmax,
+ code, sign, prec,
+ dividend_min, dividend_max,
+ wi::one (prec), divisor_max,
+ overflow_undefined,
+ overflow_wraps))
+ return false;
+ }
+ else
+ extra_range_p = false;
+ return true;
+}
diff --git a/gcc/wide-int-range.h b/gcc/wide-int-range.h
new file mode 100644
index 0000000..e9ee418
--- /dev/null
+++ b/gcc/wide-int-range.h
@@ -0,0 +1,186 @@
+/* Support routines for range operations on wide ints.
+ Copyright (C) 2018 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_WIDE_INT_RANGE_H
+#define GCC_WIDE_INT_RANGE_H
+
+extern bool wide_int_range_cross_product (wide_int &res_lb, wide_int &res_ub,
+ enum tree_code code, signop sign,
+ const wide_int &, const wide_int &,
+ const wide_int &, const wide_int &,
+ bool overflow_undefined);
+extern bool wide_int_range_mult_wrapping (wide_int &res_lb,
+ wide_int &res_ub,
+ signop sign,
+ unsigned prec,
+ const wide_int &min0_,
+ const wide_int &max0_,
+ const wide_int &min1_,
+ const wide_int &max1_);
+extern bool wide_int_range_multiplicative_op (wide_int &res_lb,
+ wide_int &res_ub,
+ enum tree_code code,
+ signop sign,
+ unsigned prec,
+ const wide_int &vr0_lb,
+ const wide_int &vr0_ub,
+ const wide_int &vr1_lb,
+ const wide_int &vr1_ub,
+ bool overflow_undefined,
+ bool overflow_wraps);
+extern bool wide_int_range_lshift (wide_int &res_lb, wide_int &res_ub,
+ signop sign, unsigned prec,
+ const wide_int &, const wide_int &,
+ const wide_int &, const wide_int &,
+ bool overflow_undefined,
+ bool overflow_wraps);
+extern void wide_int_range_set_zero_nonzero_bits (signop,
+ const wide_int &lb,
+ const wide_int &ub,
+ wide_int &may_be_nonzero,
+ wide_int &must_be_nonzero);
+extern bool wide_int_range_optimize_bit_op (wide_int &res_lb, wide_int &res_ub,
+ enum tree_code code,
+ signop sign,
+ const wide_int &vr0_lb,
+ const wide_int &vr0_ub,
+ const wide_int &vr1_lb,
+ const wide_int &vr1_ub);
+extern bool wide_int_range_get_mask_and_bounds (wide_int &mask,
+ wide_int &lower_bound,
+ wide_int &upper_bound,
+ const wide_int &vr0_min,
+ const wide_int &vr0_max,
+ const wide_int &vr1_min,
+ const wide_int &vr1_max);
+extern bool wide_int_range_bit_xor (wide_int &wmin, wide_int &wmax,
+ signop sign,
+ unsigned prec,
+ const wide_int &must_be_nonzero0,
+ const wide_int &may_be_nonzero0,
+ const wide_int &must_be_nonzero1,
+ const wide_int &may_be_nonzero1);
+extern bool wide_int_range_bit_ior (wide_int &wmin, wide_int &wmax,
+ signop sign,
+ const wide_int &vr0_min,
+ const wide_int &vr0_max,
+ const wide_int &vr1_min,
+ const wide_int &vr1_max,
+ const wide_int &must_be_nonzero0,
+ const wide_int &may_be_nonzero0,
+ const wide_int &must_be_nonzero1,
+ const wide_int &may_be_nonzero1);
+extern bool wide_int_range_bit_and (wide_int &wmin, wide_int &wmax,
+ signop sign,
+ unsigned prec,
+ const wide_int &vr0_min,
+ const wide_int &vr0_max,
+ const wide_int &vr1_min,
+ const wide_int &vr1_max,
+ const wide_int &must_be_nonzero0,
+ const wide_int &may_be_nonzero0,
+ const wide_int &must_be_nonzero1,
+ const wide_int &may_be_nonzero1);
+extern void wide_int_range_trunc_mod (wide_int &wmin, wide_int &wmax,
+ signop sign,
+ unsigned prec,
+ const wide_int &vr0_min,
+ const wide_int &vr0_max,
+ const wide_int &vr1_min,
+ const wide_int &vr1_max);
+extern bool wide_int_range_abs (wide_int &min, wide_int &max,
+ signop sign, unsigned prec,
+ const wide_int &vr0_min,
+ const wide_int &vr0_max,
+ bool overflow_undefined);
+extern bool wide_int_range_convert (wide_int &min, wide_int &max,
+ signop inner_sign,
+ unsigned inner_prec,
+ signop outer_sign,
+ unsigned outer_prec,
+ const wide_int &vr0_min,
+ const wide_int &vr0_max);
+extern bool wide_int_range_div (wide_int &wmin, wide_int &wmax,
+ enum tree_code code,
+ signop sign, unsigned prec,
+ const wide_int &dividend_min,
+ const wide_int &dividend_max,
+ const wide_int &divisor_min,
+ const wide_int &divisor_max,
+ bool overflow_undefined,
+ bool overflow_wraps,
+ bool &extra_range_p,
+ wide_int &extra_min, wide_int &extra_max);
+
+/* Return TRUE if shifting by range [MIN, MAX] is undefined behavior. */
+
+inline bool
+wide_int_range_shift_undefined_p (unsigned prec,
+ const wide_int &min, const wide_int &max)
+{
+ /* ?? Note: The original comment said this only applied to
+ RSHIFT_EXPR, but it was being applied to both left and right
+ shifts. */
+
+ /* Shifting by any values outside [0..prec-1], gets undefined
+ behavior from the shift operation. We cannot even trust
+ SHIFT_COUNT_TRUNCATED at this stage, because that applies to rtl
+ shifts, and the operation at the tree level may be widened. */
+ return wi::sign_mask (min) || wi::ge_p (max, prec, UNSIGNED);
+}
+
+/* Calculate MIN/MAX_EXPR of two ranges and store the result in [MIN, MAX]. */
+
+inline bool
+wide_int_range_min_max (wide_int &min, wide_int &max,
+ tree_code code,
+ signop sign, unsigned prec,
+ const wide_int &vr0_min, const wide_int &vr0_max,
+ const wide_int &vr1_min, const wide_int &vr1_max)
+{
+ wi::overflow_type overflow;
+ wide_int_binop (min, code, vr0_min, vr1_min, sign, &overflow);
+ wide_int_binop (max, code, vr0_max, vr1_max, sign, &overflow);
+ /* If the new range covers the entire domain, that's really no range
+ at all. */
+ if (min == wi::min_value (prec, sign)
+ && max == wi::max_value (prec, sign))
+ return false;
+ return true;
+}
+
+/* Return TRUE if 0 is within [WMIN, WMAX]. */
+
+inline bool
+wide_int_range_includes_zero_p (const wide_int &wmin, const wide_int &wmax,
+ signop sign)
+{
+ return wi::le_p (wmin, 0, sign) && wi::ge_p (wmax, 0, sign);
+}
+
+/* Return TRUE if [WMIN, WMAX] is the singleton 0. */
+
+inline bool
+wide_int_range_zero_p (const wide_int &wmin, const wide_int &wmax,
+ unsigned prec)
+{
+ return wmin == wmax && wi::eq_p (wmin, wi::zero (prec));
+}
+
+#endif /* GCC_WIDE_INT_RANGE_H */